User Tools

Site Tools


source_code_osmworldmapkitextractor.zip

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
source_code_osmworldmapkitextractor.zip [2016/07/06 18:56]
ryanduan [Extractor.cs] updated sample
source_code_osmworldmapkitextractor.zip [2017/02/23 21:55] (current)
ryanduan Updated Extractor code
Line 35: Line 35:
 using System.Windows.Forms;​ using System.Windows.Forms;​
 using ThinkGeo.MapSuite.Core;​ using ThinkGeo.MapSuite.Core;​
 +using WorldMapKitDataExtractor.Model;​
  
 namespace WorldMapKitDataExtractor namespace WorldMapKitDataExtractor
Line 56: Line 57:
                 Extractor extractor = new Extractor(txtInputDatabase.Text,​ txtOutputDatabase.Text);​                 Extractor extractor = new Extractor(txtInputDatabase.Text,​ txtOutputDatabase.Text);​
                 extractor.InputDataPrj = ManagedProj4Projection.GetEpsgParametersString(int.Parse(txtInputDatabaseSrid.Text));​                 extractor.InputDataPrj = ManagedProj4Projection.GetEpsgParametersString(int.Parse(txtInputDatabaseSrid.Text));​
-                extractor.UpdateStatus = value => { Dispatcher.Invoke(() => { lblStatus.Content = string.Format("​Status:​ {0}", value); }); }; +                extractor.UpdateStatus = value => { Dispatcher.Invoke(() => { lblStatus.Content = string.Format("​Status:​ {0}", value); }); };
                 extractor.PreserveCountryLevelData = chkPreserveCountryLevelData.IsChecked == true;                 extractor.PreserveCountryLevelData = chkPreserveCountryLevelData.IsChecked == true;
-                Collection<​Feature> boundariesFeatures = new Collection<​Feature>();+                Collection<​BoundingBoxWithZoomLevels> boundariesFeatures = new Collection<​BoundingBoxWithZoomLevels>(); 
 + 
 +                if(extractor.PreserveCountryLevelData) 
 +                { 
 +                    RectangleShape boundingBox = new RectangleShape();​ 
 +                    switch(txtInputDatabaseSrid.Text) 
 +                    { 
 +                        case "​4326":​ 
 +                            boundingBox = new RectangleShape(-180,​ 90, 180, -90); 
 +                            break; 
 +                        case "​3857":​ 
 +                            boundingBox = new RectangleShape(-20026376,​ 20048966, 20026376, -20048966);​ 
 +                            break; 
 +                        default: 
 +                            boundingBox = new RectangleShape(0,​ 0, 0, 0); 
 +                            break; 
 +                    } 
 +                    boundariesFeatures.Add(new BoundingBoxWithZoomLevels(boundingBox,​ (int)cmbCountryStartZoomLevel.SelectedValue,​ (int)cmbCountryEndZoomLevel.SelectedValue));​ 
 +                }
  
                 if (rbtnShapeFile.IsChecked == true)                 if (rbtnShapeFile.IsChecked == true)
Line 73: Line 92:
                     foreach (DataRowView row in selectItems)                     foreach (DataRowView row in selectItems)
                     {                     {
-                        boundariesFeatures.Add(shapeFileLayer.QueryTools.GetFeatureById(row.Row[0].ToString(),​ ReturningColumnsType.NoColumns));​+                        boundariesFeatures.Add(new BoundingBoxWithZoomLevels(shapeFileLayer.QueryTools.GetFeatureById(row.Row[0].ToString(),​ ReturningColumnsType.NoColumns).GetBoundingBox(),​ 1, 20));
                     }                     }
                 }                 }
                 else                 else
                 {                 {
-                    ​var uppperLeftPoint ​txtUpperLeftPoint.Text.Split(',').Select(a ​=> double.Parse(a.Trim())).ToArray(); +                    ​BoundingBoxRow row1 new BoundingBoxRow(txtUpperLeft1txtLowerRight1,​ cmbStartZoomLevel1,​ cmbEndZoomLevel1,​ chkEnable1)
-                    ​var lowerRightPoint ​txtLowerRightPoint.Text.Split(',').Select(a ​=> double.Parse(a.Trim())).ToArray();+                    BoundingBoxRow row2 new BoundingBoxRow(txtUpperLeft2,​ txtLowerRight2,​ cmbStartZoomLevel2,​ cmbEndZoomLevel2,​ chkEnable2)
 +                    BoundingBoxRow row3 = new BoundingBoxRow(txtUpperLeft3,​ txtLowerRight3,​ cmbStartZoomLevel3,​ cmbEndZoomLevel3,​ chkEnable3); 
 +                    ​BoundingBoxRow row4 new BoundingBoxRow(txtUpperLeft4txtLowerRight4,​ cmbStartZoomLevel4,​ cmbEndZoomLevel4,​ chkEnable4)
 +                    BoundingBoxRow row5 new BoundingBoxRow(txtUpperLeft5,​ txtLowerRight5,​ cmbStartZoomLevel5,​ cmbEndZoomLevel5,​ chkEnable5)
 + 
 +                    BoundingBoxRow[] boundingBoxRows = { row1, row2, row3, row4, row5 };
  
-                    RectangleShape boundingBox = new RectangleShape(uppperLeftPoint[0],​ uppperLeftPoint[1],​ lowerRightPoint[0],​ lowerRightPoint[1]);​ 
                     extractor.BoundaryPrj = ManagedProj4Projection.GetEpsgParametersString(int.Parse(boundarySrid.Text));​                     extractor.BoundaryPrj = ManagedProj4Projection.GetEpsgParametersString(int.Parse(boundarySrid.Text));​
  
-                    boundariesFeatures.Add(new ​Feature(boundingBox));​+                    ​foreach (BoundingBoxRow row in boundingBoxRows) 
 +                    { 
 +                        if ((bool)row.chkRowEnabled.IsChecked) 
 +                        { 
 +                            var uppperLeftPoint = row.txtUpperLeftPoint.Text.Split(','​).Select(a => double.Parse(a.Trim())).ToArray();​ 
 +                            var lowerRightPoint = row.txtLowerRightPoint.Text.Split(','​).Select(a => double.Parse(a.Trim())).ToArray();​ 
 + 
 +                            RectangleShape boundingBox = new RectangleShape(uppperLeftPoint[0],​ uppperLeftPoint[1],​ lowerRightPoint[0],​ lowerRightPoint[1]);​ 
 + 
 +                            ​boundariesFeatures.Add(new ​BoundingBoxWithZoomLevels(boundingBox, (int)row.cmbStartZoomLevel.SelectedValue,​ (int)row.cmbEndZoomLevel.SelectedValue)); 
 +                        } 
 +                    }
                 }                 }
  
Line 97: Line 131:
             int srid;             int srid;
             if (!File.Exists(txtInputDatabase.Text))             if (!File.Exists(txtInputDatabase.Text))
-                errorMessage.AppendLine("​Please enter currect ​input database file path."​);​+                errorMessage.AppendLine("​Please enter correct ​input database file path."​);​
  
             if (!int.TryParse(txtInputDatabaseSrid.Text,​ out srid))             if (!int.TryParse(txtInputDatabaseSrid.Text,​ out srid))
-                errorMessage.AppendLine("​Please enter currect ​SRID for input database."​);​+                errorMessage.AppendLine("​Please enter correct ​SRID for input database."​);​
  
             if (string.IsNullOrEmpty(txtOutputDatabase.Text))             if (string.IsNullOrEmpty(txtOutputDatabase.Text))
-                errorMessage.AppendLine("​Please enter currect ​output database file path."​);​+                errorMessage.AppendLine("​Please enter correct ​output database file path."​);​
  
             if (rbtnShapeFile.IsChecked == true)             if (rbtnShapeFile.IsChecked == true)
             {             {
                 if (!File.Exists(txtShapeFile.Text))                 if (!File.Exists(txtShapeFile.Text))
-                    errorMessage.AppendLine("​Please enter currect ​shape file path."​);​+                    errorMessage.AppendLine("​Please enter correct ​shape file path."​);​
  
                 if (!File.Exists(Path.ChangeExtension(txtShapeFile.Text,​ "​.prj"​)) && !int.TryParse(shapeFileSrid.Text,​ out srid))                 if (!File.Exists(Path.ChangeExtension(txtShapeFile.Text,​ "​.prj"​)) && !int.TryParse(shapeFileSrid.Text,​ out srid))
-                    errorMessage.AppendLine("​Please enter currect ​SRID for boundary shaplefile."​);​+                    errorMessage.AppendLine("​Please enter correct ​SRID for boundary shaplefile."​);​
             }             }
  
-            if (rbtnBoundingBox.IsChecked == true && ​!int.TryParse(boundarySrid.Text,​ out srid)) +            if (rbtnBoundingBox.IsChecked == true
-                errorMessage.AppendLine("​Please enter currect ​SRID for boundary."​);​+            { 
 +                if(!int.TryParse(boundarySrid.Text,​ out srid)) 
 +                    errorMessage.AppendLine("​Please enter correct ​SRID for boundary."​);​ 
 + 
 +                if((bool)chkPreserveCountryLevelData.IsChecked) 
 +                { 
 +                    if((int)cmbCountryStartZoomLevel.SelectedValue > (int)cmbCountryEndZoomLevel.SelectedValue) 
 +                        errorMessage.AppendLine("​Invalid ZoomLevel Input for Preserve Country-Level Data."​);​ 
 +                } 
 + 
 +                BoundingBoxRow row1 = new BoundingBoxRow(txtUpperLeft1,​ txtLowerRight1,​ cmbStartZoomLevel1,​ cmbEndZoomLevel1,​ chkEnable1);​ 
 +                BoundingBoxRow row2 = new BoundingBoxRow(txtUpperLeft2,​ txtLowerRight2,​ cmbStartZoomLevel2,​ cmbEndZoomLevel2,​ chkEnable2);​ 
 +                BoundingBoxRow row3 = new BoundingBoxRow(txtUpperLeft3,​ txtLowerRight3,​ cmbStartZoomLevel3,​ cmbEndZoomLevel3,​ chkEnable3);​ 
 +                BoundingBoxRow row4 = new BoundingBoxRow(txtUpperLeft4,​ txtLowerRight4,​ cmbStartZoomLevel4,​ cmbEndZoomLevel4,​ chkEnable4);​ 
 +                BoundingBoxRow row5 = new BoundingBoxRow(txtUpperLeft5,​ txtLowerRight5,​ cmbStartZoomLevel5,​ cmbEndZoomLevel5,​ chkEnable5);​ 
 + 
 +                BoundingBoxRow[] boundingBoxRows = { row1, row2, row3, row4, row5 }; 
 + 
 +                foreach (BoundingBoxRow row in boundingBoxRows) 
 +                { 
 +                    if ((bool)row.chkRowEnabled.IsChecked) 
 +                    { 
 +                        var upperLeftPoint = row.txtUpperLeftPoint.Text.Split(','​).Select(a => double.Parse(a.Trim())).ToArray();​ 
 +                        var lowerRightPoint = row.txtLowerRightPoint.Text.Split(','​).Select(a => double.Parse(a.Trim())).ToArray();​ 
 + 
 +                        if(upperLeftPoint[0] > lowerRightPoint[0] || upperLeftPoint[1] < lowerRightPoint[1]) 
 +                            errorMessage.AppendLine("​Invalid BoundingBox Input."​);​ 
 + 
 +                        if ((int)row.cmbStartZoomLevel.SelectedValue > (int)row.cmbEndZoomLevel.SelectedValue || (int)row.cmbStartZoomLevel.SelectedValue < 0 || (int)row.cmbEndZoomLevel.SelectedValue < 0) 
 +                            errorMessage.AppendLine("​Invalid ZoomLevel Input."​);​ 
 +                    } 
 +                } 
 + 
 +                if(!((bool)chkEnable1.IsChecked || (bool)chkEnable2.IsChecked || (bool)chkEnable3.IsChecked || (bool)chkEnable4.IsChecked || (bool)chkEnable5.IsChecked)) 
 +                    errorMessage.AppendLine("​Please enable a bounding box."​);​ 
 +            } 
 + 
  
             if (!string.IsNullOrEmpty(errorMessage.ToString()))             if (!string.IsNullOrEmpty(errorMessage.ToString()))
Line 220: Line 291:
         {         {
             Close();             Close();
 +        }
 +
 +        private void Window_Loaded(object sender, RoutedEventArgs e)
 +        {
 +            System.Windows.Controls.ComboBox[] zoomLevelBoxes = { cmbEndZoomLevel1,​ cmbEndZoomLevel2,​ cmbEndZoomLevel3,​ cmbEndZoomLevel4,​ cmbEndZoomLevel5,​
 +                                                                  cmbStartZoomLevel1,​ cmbStartZoomLevel2,​ cmbStartZoomLevel3,​ cmbStartZoomLevel4,​ cmbStartZoomLevel5,​
 +                                                                  cmbCountryStartZoomLevel,​ cmbCountryEndZoomLevel };
 +
 +            foreach (System.Windows.Controls.ComboBox comboBox in zoomLevelBoxes)
 +            {
 +                int[] zoomLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
 +                comboBox.ItemsSource = zoomLevels;
 +            }
 +
 +            cmbStartZoomLevel1.SelectedIndex = 7;
 +            cmbEndZoomLevel1.SelectedIndex = 19;
 +            cmbCountryStartZoomLevel.SelectedIndex = 0;
 +            cmbCountryEndZoomLevel.SelectedIndex = 6;
         }         }
     }     }
 } }
 +
  
 </​code>​ </​code>​
Line 349: Line 439:
 using System.Text;​ using System.Text;​
 using ThinkGeo.MapSuite.Core;​ using ThinkGeo.MapSuite.Core;​
 +using System.Linq;​
 +using WorldMapKitDataExtractor.Model;​
  
 namespace WorldMapKitDataExtractor namespace WorldMapKitDataExtractor
Line 401: Line 493:
         }         }
  
-        public void ExtractDataByShape(IEnumerable<FeatureboundaryFeatures)+        public void ExtractDataByShape(Collection<BoundingBoxWithZoomLevelsboundaryFeatureSet)
         {         {
             UpdateStatus("​Beginning to extract world map kit data by shape file."​);​             UpdateStatus("​Beginning to extract world map kit data by shape file."​);​
  
-            ​var projectedBoundaryFeatures ​ProjectedBoundaryFeatures(boundaryFeatures);+            ​Collection<​BoundingBoxWithZoomLevels>​ projectedBoundaryFeaturesWithZoomLevels ​new Collection<​BoundingBoxWithZoomLevels>​(); 
 +            Collection<​RectangleShape>​ projectedBoundingBoxes = new Collection<​RectangleShape>​();​ 
 + 
 +            foreach (BoundingBoxWithZoomLevels boundaryFeatureWithZoomLevels in boundaryFeatureSet) 
 +            { 
 +                RectangleShape projectedBoundaryFeature = ProjectBoundingBox(boundaryFeatureWithZoomLevels.BoundingBox);​ 
 +                projectedBoundaryFeaturesWithZoomLevels.Add(new BoundingBoxWithZoomLevels(projectedBoundaryFeature,​ boundaryFeatureWithZoomLevels.StartingZoomLevel,​ boundaryFeatureWithZoomLevels.EndingZoomLevel));​ 
 +                projectedBoundingBoxes.Add(projectedBoundaryFeature);​ 
 +            } 
             SQLiteConnection.CreateFile(outputDataPath);​             SQLiteConnection.CreateFile(outputDataPath);​
             SQLiteConnection targetDatabaseConnection = new SQLiteConnection($"​Data Source={outputDataPath};​Version=3;"​);​             SQLiteConnection targetDatabaseConnection = new SQLiteConnection($"​Data Source={outputDataPath};​Version=3;"​);​
Line 412: Line 513:
             sourceDatabaseConnection.Open();​             sourceDatabaseConnection.Open();​
  
-            ​CopyDataToABuffer(ExtentHelper.GetBoundingBoxOfItems(projectedBoundaryFeatures), sourceDatabaseConnection);​ +            ​//this is the set of layers we use to determine which tables to grab for each bounding area 
-            ProcessBaselandByShapes(projectedBoundaryFeatures, targetDatabaseConnection);​+            OsmWorldMapKitLayer wmkLayer = new OsmWorldMapKitLayer(sourceDatabaseConnection.ConnectionString,​ OsmWorldMapKitDatabaseType.Sqlite);​ 
 +            wmkLayer.Open(); 
 + 
 +            CopyDataToABuffer(GetBoundingBoxesForLayers(projectedBoundaryFeaturesWithZoomLevels,​ sourceDatabaseConnection,​ wmkLayer.Layers), sourceDatabaseConnection);​ 
 +            ProcessBaselandByShapes(projectedBoundingBoxes, targetDatabaseConnection);​
  
             UpdateStatus("​Executing vacuum for output database."​);​             UpdateStatus("​Executing vacuum for output database."​);​
Line 423: Line 528:
         }         }
  
-        private void CopyDataToABuffer(RectangleShape ​boundingBox, SQLiteConnection sourceDatabaseConnection)+        private void CopyDataToABuffer(Dictionary<​FeatureLayer,​ Collection<​RectangleShape>> layersWithBoundingShapes, SQLiteConnection sourceDatabaseConnection)
         {         {
-            ​var views GetViews(sourceDatabaseConnection);+            ​Proj4Projection proj4 new Proj4Projection(inputDataPrj,​ inputDataPrj);​ 
 +            GeographyUnit geographyUnit = proj4.GetInternalGeographyUnit();
  
             //OSM WorldMapKit contains several views and view indices that we want to grab as well for our OSMLayer, so we create temporary tables of the data from these within the boundingbox             //OSM WorldMapKit contains several views and view indices that we want to grab as well for our OSMLayer, so we create temporary tables of the data from these within the boundingbox
 +
 +            var views = GetViews(sourceDatabaseConnection);​
  
             foreach (View view in views)             foreach (View view in views)
             {             {
-                ​UpdateStatus($"​Creating temporary table for {view.Name}")+                ​if (layersWithBoundingShapes.Keys.Where(featureLayer => featureLayer.Name == view.Name).Count() > 0) 
- +                { 
-                StringBuilder createNewTempTableFromViewCommand = new StringBuilder(); +                    ​Collection<​RectangleShape>​ boundingBoxes = layersWithBoundingShapes[layersWithBoundingShapes.Keys.Where(featureLayer => featureLayer.Name == view.Name).ElementAt(0)]
- +                    ​CreateTempTableForView(viewboundingBoxes,​ sourceDatabaseConnection); 
-                ​createNewTempTableFromViewCommand.AppendFormat("​CREATE TEMP TABLE {0} AS ", ​view.Name)+                } 
-                createNewTempTableFromViewCommand.AppendFormat("​SELECT * FROM {0} WHERE id in (", view.Name); +                else 
-                ​createNewTempTableFromViewCommand.AppendFormat("​SELECT id FROM {0} WHERE id in ("view.BaseTable); +                ​{ 
-                ​createNewTempTableFromViewCommand.AppendFormat("​SELECT id from idx_{0}_geometry WHERE maxx < {1} AND maxy {2} AND minx > {3} AND miny > {4}));"​view.NameboundingBox.UpperRightPoint.XboundingBox.UpperRightPoint.YboundingBox.LowerLeftPoint.X,​ boundingBox.LowerLeftPoint.Y); +                    //create the table so the database is valid 
- +                    CreateTempTableForView(view,​ new Collection<RectangleShape>() new RectangleShape(0000) }sourceDatabaseConnection); 
-                ​ExecuteNonQueryCommand(createNewTempTableFromViewCommand.ToString(),​ sourceDatabaseConnection);​+                ​}
             }             }
- 
-            Proj4Projection proj4 = new Proj4Projection(inputDataPrj,​ inputDataPrj);​ 
-            GeographyUnit geographyUnit = proj4.GetInternalGeographyUnit();​ 
  
             //get the features from every table within the bounding box and add them to the temporary output file             //get the features from every table within the bounding box and add them to the temporary output file
 +
             var tables = GetTables(sourceDatabaseConnection);​             var tables = GetTables(sourceDatabaseConnection);​
             foreach (var table in tables)             foreach (var table in tables)
Line 454: Line 560:
                 source.Open();​                 source.Open();​
  
-                Collection<​Feature>​ intersectFeatures = GetFeaturesIntersects(source, boundingBox,​ ReturningColumnsType.AllColumns);+                Collection<​Feature>​ intersectFeatures = new Collection<​Feature>​();
  
-                if (preserveCountryLevelData && (table.TableName.Equals("​osm_baseland_polygon"​) || table.TableName.Equals("​osm_baseland1m_polygon"​))) +                if (layersWithBoundingShapes.Keys.Where(featureLayer => featureLayer.Name == table.TableName).Count() > 0) 
-                    intersectFeatures = source.GetAllFeatures(ReturningColumnsType.AllColumns);​+                { 
 +                    intersectFeatures = GetFeaturesIntersects(source, layersWithBoundingShapes[layersWithBoundingShapes.Keys.Where(featureLayer => featureLayer.Name == table.TableName).ElementAt(0)], ​ReturningColumnsType.AllColumns);​ 
 +                }
  
                 Collection<​string>​ targetTables = SqliteFeatureSource.GetTableNames($@"​Data Source={outputDataPath};​Version=3;"​);​                 Collection<​string>​ targetTables = SqliteFeatureSource.GetTableNames($@"​Data Source={outputDataPath};​Version=3;"​);​
Line 469: Line 577:
  
                 int counter = 0;                 int counter = 0;
-                foreach (var feature in intersectFeatures)+                ​UpdateStatus($"​Adding <1000 new features."​);​ 
 +                ​foreach (var feature in intersectFeatures.Distinct(new FeatureComparer()))
                 {                 {
-                    UpdateStatus($"​Adding new feature: {feature.Id}."​);​ 
                     tempSource.AddFeature(feature);​                     tempSource.AddFeature(feature);​
                     counter++;                     counter++;
 +                    if (counter % 1000 == 0)
 +                    {
 +                        UpdateStatus($"​Adding {counter} new features."​);​
 +                    }
                 }                 }
                 UpdateStatus("​Commiting sqlite database transaction."​);​                 UpdateStatus("​Commiting sqlite database transaction."​);​
Line 481: Line 593:
         }         }
  
-        ​private IEnumerable<​Feature>​ ProjectedBoundaryFeatures(IEnumerable<​Feature>​ boundaryFeatures) +        private void ProcessBaselandByShapes(Collection<RectangleShapeboundingBoxes, SQLiteConnection connection)
-        { +
-            Proj4Projection proj = new Proj4Projection(boundaryPrj,​ inputDataPrj);​ +
-            proj.Open();​ +
-            foreach (Feature feature in boundaryFeatures) +
-            { +
-                yield return proj.ConvertToExternalProjection(feature);​ +
-            } +
-            proj.Close();​ +
-        } +
- +
-        ​private void ProcessBaselandByShapes(IEnumerable<FeatureboundaryFeatures, SQLiteConnection connection)+
         {         {
             UpdateStatus("​Processing baseland by shapes."​);​             UpdateStatus("​Processing baseland by shapes."​);​
-            if (!preserveCountryLevelData) ​return; +            if (!preserveCountryLevelData) 
- +                ​return;
-            MultipolygonShape boundaryShape = new MultipolygonShape();​ +
-            foreach (Feature feature in boundaryFeatures) +
-            { +
-                ​boundaryShape.Polygons.Add(feature.GetBoundingBox().ToPolygon());​ +
-            } +
- +
-            Feature boundaryFeature = new Feature(boundaryShape);​ +
-            boundaryFeature = SqlTypesGeometryHelper.MakeValid(boundaryFeature);+
  
 +            //remove full world bounding box from boundary features
 +            boundingBoxes.RemoveAt(0);​
  
             SqliteFeatureSource baselandFeatureSource = new SqliteFeatureSource(connection.ConnectionString,​ "​osm_baseland_polygon",​ "​id",​ "​geometry"​);​             SqliteFeatureSource baselandFeatureSource = new SqliteFeatureSource(connection.ConnectionString,​ "​osm_baseland_polygon",​ "​id",​ "​geometry"​);​
Line 514: Line 609:
  
             UpdateStatus("​Querying baseland features from osm_baseland_polygon table."​);​             UpdateStatus("​Querying baseland features from osm_baseland_polygon table."​);​
-            ​Collection<​Feature>​ baselandFeatures = baselandFeatureSource.SpatialQuery(boundaryShape, QueryType.Intersects,​ ReturningColumnsType.NoColumns);​+            ​List<​Feature>​ baselandFeatures ​= new List<​Feature>​();​ 
 +            foreach (var boundingBox in boundingBoxes) 
 +            { 
 +                Collection<​Feature>​ features ​= baselandFeatureSource.SpatialQuery(boundingBox, QueryType.Intersects,​ ReturningColumnsType.NoColumns);​ 
 +                baselandFeatures.AddRange(features);​ 
 +            }
  
             UpdateStatus("​Querying baseland1m features from osm_baseland1m_polygon table."​);​             UpdateStatus("​Querying baseland1m features from osm_baseland1m_polygon table."​);​
             Collection<​Feature>​ baseland1mFeatures = baseland1mFeatureSource.GetAllFeatures(ReturningColumnsType.NoColumns);​             Collection<​Feature>​ baseland1mFeatures = baseland1mFeatureSource.GetAllFeatures(ReturningColumnsType.NoColumns);​
 +
 +            if (baselandFeatures.Count == 0 || baseland1mFeatures.Count == 0)
 +            {
 +                UpdateStatus("​Cannot process baseland by shapes - one or more tables is empty"​);​
 +                return;
 +            }
  
             Collection<​Feature>​ newBaselandFeatures = new Collection<​Feature>​();​             Collection<​Feature>​ newBaselandFeatures = new Collection<​Feature>​();​
  
 +            int counter = 0;
 +            UpdateStatus($"​Getting <1000 intersection features for baseland feature."​);​
             foreach (Feature feature in baselandFeatures)             foreach (Feature feature in baselandFeatures)
             {             {
-                UpdateStatus($"​Getting intersection feature for baseland feature: {feature.Id}."​);​ 
- 
                 Feature validFeature = SqlTypesGeometryHelper.MakeValid(feature);​                 Feature validFeature = SqlTypesGeometryHelper.MakeValid(feature);​
-                newBaselandFeatures.Add(validFeature.GetIntersection(boundaryFeature));+                ​Feature intersectionFeature = GetInterSection(validFeature,​ boundingBoxes);​ 
 +                if (!(intersectionFeature == null)) 
 +                { 
 +                    ​newBaselandFeatures.Add(intersectionFeature);​ 
 +                    counter++;​ 
 +                    if (counter % 1000 == 0) 
 +                    { 
 +                        UpdateStatus($"​Getting {counter} intersection features for baseland feature."​); 
 +                    } 
 +                }
             }             }
  
 +            counter = 0;
 +            UpdateStatus($"​Getting <1000 difference features for baseland1m feature."​);​
             foreach (Feature feature in baseland1mFeatures)             foreach (Feature feature in baseland1mFeatures)
             {             {
-                ​UpdateStatus($"​Getting difference feature for baseland1m feature: {feature.Id}."​);​ +                if (IsDisjointed(feature, boundingBoxes)) 
-                ​if (feature.IsDisjointed(boundaryFeature)) newBaselandFeatures.Add(feature);​+                { 
 +                    ​newBaselandFeatures.Add(feature);​ 
 +                    counter++;​ 
 +                }
                 else                 else
                 {                 {
                     Feature validFeature = SqlTypesGeometryHelper.MakeValid(feature);​                     Feature validFeature = SqlTypesGeometryHelper.MakeValid(feature);​
-                    Feature difference = SqlTypesGeometryHelper.GetDifference(validFeature, ​boundaryFeature);+                    Feature difference = GetDifference(validFeature, ​boundingBoxes);
  
-                    if (difference != null) newBaselandFeatures.Add(difference);​+                    if (difference != null) 
 +                    { 
 +                        ​newBaselandFeatures.Add(difference); 
 +                        counter++;​ 
 +                    } 
 +                } 
 +                if (counter != 0 && counter % 1000 == 0) 
 +                { 
 +                    UpdateStatus($"​Getting {counter} difference features for baseland1m feature."​);
                 }                 }
             }             }
Line 548: Line 676:
             baselandFeatureSource.ExecuteNonQuery("​DELETE FROM idx_osm_baseland_polygon_geometry;"​);​             baselandFeatureSource.ExecuteNonQuery("​DELETE FROM idx_osm_baseland_polygon_geometry;"​);​
  
-            ​int counter = 0;+            counter = 0
 +            UpdateStatus($"​Adding <1000 new features."​);
             foreach (Feature f in newBaselandFeatures)             foreach (Feature f in newBaselandFeatures)
             {             {
-                UpdateStatus($"​Adding new baseland feature: {f.Id}."​);​ 
                 Feature feature = new Feature(f.GetWellKnownBinary());​                 Feature feature = new Feature(f.GetWellKnownBinary());​
                 baselandFeatureSource.AddFeature(feature);​                 baselandFeatureSource.AddFeature(feature);​
                 counter++;                 counter++;
 +                if (counter % 1000 == 0)
 +                {
 +                    UpdateStatus($"​Adding {counter} new features."​);​
 +                }
             }             }
             UpdateStatus("​Commiting sqlite database transaction."​);​             UpdateStatus("​Commiting sqlite database transaction."​);​
Line 629: Line 761:
                     if (!(columnName.Equals("​geometry"​) || columnName.Equals("​id"​)))                     if (!(columnName.Equals("​geometry"​) || columnName.Equals("​id"​)))
                     {                     {
-                        switch(columnType)+                        switch (columnType)
                         {                         {
                             case "​character varying":​                             case "​character varying":​
Line 640: Line 772:
                             case "​double precision":​                             case "​double precision":​
                                 table.Columns.Add(new SqliteColumn() { ColumnName = columnName, ColumnType = SqliteColumnType.Real });                                 table.Columns.Add(new SqliteColumn() { ColumnName = columnName, ColumnType = SqliteColumnType.Real });
 +                                break;
 +                            case "​numeric":​
 +                                table.Columns.Add(new SqliteColumn() { ColumnName = columnName, ColumnType = SqliteColumnType.Text });
                                 break;                                 break;
                             default:                             default:
                                 table.Columns.Add(new SqliteColumn() { ColumnName = columnName, ColumnType = (SqliteColumnType)Enum.Parse(typeof(SqliteColumnType),​ columnType, true) });                                 table.Columns.Add(new SqliteColumn() { ColumnName = columnName, ColumnType = (SqliteColumnType)Enum.Parse(typeof(SqliteColumnType),​ columnType, true) });
                                 break;                                 break;
-                        }                                                    +                        }
                     }                     }
                 }                 }
Line 654: Line 789:
  
             return tables;             return tables;
 +        }
 +
 +        private void CreateTempTableForView(View view, Collection<​RectangleShape>​ boundingBoxes,​ SQLiteConnection sourceDatabaseConnection)
 +        {
 +            UpdateStatus($"​Creating temporary table for {view.Name}"​);​
 +
 +            StringBuilder createNewTempTableFromViewCommand = new StringBuilder();​
 +
 +            createNewTempTableFromViewCommand.AppendFormat("​CREATE TEMP TABLE {0} AS ", view.Name);
 +            createNewTempTableFromViewCommand.AppendFormat("​SELECT * FROM {0} WHERE id in (", view.Name);
 +            createNewTempTableFromViewCommand.AppendFormat("​SELECT id FROM {0} WHERE id in (", view.BaseTable);​
 +            createNewTempTableFromViewCommand.AppendFormat("​SELECT id from idx_{0}_geometry WHERE (maxx < {1} AND maxy < {2} AND minx > {3} AND miny > {4})", view.Name, boundingBoxes[0].UpperRightPoint.X,​ boundingBoxes[0].UpperRightPoint.Y,​ boundingBoxes[0].LowerLeftPoint.X,​ boundingBoxes[0].LowerLeftPoint.Y);​
 +            for (int i = 1; i < boundingBoxes.Count;​ i++)
 +            {
 +                createNewTempTableFromViewCommand.AppendFormat("​ OR (maxx < {0} AND maxy < {1} AND minx > {2} AND miny > {3})", boundingBoxes[i].UpperRightPoint.X,​ boundingBoxes[i].UpperRightPoint.Y,​ boundingBoxes[i].LowerLeftPoint.X,​ boundingBoxes[i].LowerLeftPoint.Y);​
 +            }
 +
 +            createNewTempTableFromViewCommand.AppendFormat("​));"​);​
 +
 +            ExecuteNonQueryCommand(createNewTempTableFromViewCommand.ToString(),​ sourceDatabaseConnection);​
         }         }
  
Line 668: Line 823:
         }         }
  
-        private ​Collection<​Feature>​ GetFeaturesIntersects(FeatureSource source, BaseShape targetShape,​ ReturningColumnsType returningColumnsType)+        private ​RectangleShape ProjectBoundingBox(RectangleShape boundingBox)
         {         {
-            ​RectangleShape boundingBox ​targetShape.GetBoundingBox(); +            ​Proj4Projection proj new Proj4Projection(boundaryPrj,​ inputDataPrj);​ 
-            ​Collection<​Feature>​ allPossibleFeatures ​source.GetFeaturesInsideBoundingBox(boundingBox, returningColumnsType);+            proj.Open(); 
 +            ​RectangleShape projectedBoundaryFeature ​proj.ConvertToExternalProjection(boundingBox);​ 
 +            proj.Close();​ 
 +            return projectedBoundaryFeature;​ 
 +        }
  
-            ​Collection<​Feature> ​returnFeatures ​= new Collection<​Feature>​();​ +        private ​Collection<​Feature> ​GetFeaturesIntersects(FeatureSource source, Collection<​RectangleShape>​ boundingBoxes,​ ReturningColumnsType returningColumnsType) 
-            foreach (Feature feature ​in allPossibleFeatures)+        { 
 +            List<​Feature>​ results ​= new List<​Feature>​();​ 
 +            foreach (var boundingBox ​in boundingBoxes)
             {             {
-                ​ShapeValidationResult validationResult ​feature.GetShape().Validate(ShapeValidationMode.Simple); +                ​Collection<​Feature>​ allPossibleFeatures ​source.GetFeaturesInsideBoundingBox(boundingBox,​ returningColumnsType)
-                ​if (validationResult.IsValid && ​feature.GetShape().Intersects(targetShape))+ 
 +                Collection<​Feature>​ returnFeatures = new Collection<​Feature>​(); 
 +                ​foreach ​(Feature ​feature ​in allPossibleFeatures)
                 {                 {
-                    returnFeatures.Add(feature);​+                    ​ShapeValidationResult validationResult = feature.GetShape().Validate(ShapeValidationMode.Simple);​ 
 + 
 +                    if (validationResult.IsValid && feature.GetShape().Intersects(boundingBox)) 
 +                    { 
 +                        ​returnFeatures.Add(feature);​ 
 +                    }
                 }                 }
 +                results.AddRange(returnFeatures);​
             }             }
-            ​return ​returnFeatures;+ 
 +            ​return ​new Collection<​Feature>​(results);​ 
 +        } 
 + 
 +        private Dictionary<​FeatureLayer,​ Collection<​RectangleShape>>​ GetBoundingBoxesForLayers(Collection<​BoundingBoxWithZoomLevels>​ boundaryFeatures,​ SQLiteConnection sourceDatabaseConnection,​ Collection<​FeatureLayer>​ featureLayers) 
 +        { 
 +            Dictionary<​FeatureLayer,​ Collection<​RectangleShape>>​ layersWithBoundingBoxes = new Dictionary<​FeatureLayer,​ Collection<​RectangleShape>>​();​ 
 + 
 +            foreach (BoundingBoxWithZoomLevels boundingBoxParameters in boundaryFeatures) 
 +            { 
 +                Collection<​FeatureLayer>​ layersForBoundingBoxes = GetAllFeatureLayers(featureLayers,​ boundingBoxParameters.StartingZoomLevel,​ boundingBoxParameters.EndingZoomLevel);​ 
 + 
 +                foreach (FeatureLayer featureLayer in layersForBoundingBoxes) 
 +                { 
 +                    if (!layersWithBoundingBoxes.Keys.Contains(featureLayer)) 
 +                    { 
 +                        var boxes = new Collection<​RectangleShape>​();​ 
 +                        boxes.Add(boundingBoxParameters.BoundingBox);​ 
 +                        layersWithBoundingBoxes.Add(featureLayer,​ boxes); 
 +                    } 
 +                    else 
 +                    { 
 +                        layersWithBoundingBoxes[featureLayer].Add(boundingBoxParameters.BoundingBox);​ 
 +                    } 
 +                } 
 +            } 
 + 
 +            return layersWithBoundingBoxes;​ 
 +        } 
 + 
 +        private Collection<​FeatureLayer>​ GetAllFeatureLayers(Collection<​FeatureLayer>​ featureLayers,​ int fromZoomLevelNumber,​ int toZoomLevelNumber) 
 +        { 
 +            Collection<​FeatureLayer>​ featureLayersForZoomLevels = new Collection<​FeatureLayer>​();​ 
 +            Dictionary<​int,​ Collection<​FeatureLayer>>​ allZoomLevelFeatureLayers = GetAllFeatureLayersCore(featureLayers);​ 
 + 
 +            for (int i = fromZoomLevelNumber;​ i <= toZoomLevelNumber;​ i++) 
 +            { 
 +                foreach (FeatureLayer featureLayer in allZoomLevelFeatureLayers[i]) 
 +                { 
 +                    if (!featureLayersForZoomLevels.Contains(featureLayer)) 
 +                    { 
 +                        featureLayersForZoomLevels.Add(featureLayer);​ 
 +                    } 
 +                } 
 +            } 
 +            return featureLayersForZoomLevels;​ 
 +        } 
 + 
 +        private Dictionary<​int,​ Collection<​FeatureLayer>>​ GetAllFeatureLayersCore(Collection<​FeatureLayer>​ featureLayers) 
 +        { 
 +            Dictionary<​int,​ Collection<​FeatureLayer>>​ featureLayersInAllZoomLevels = new Dictionary<​int,​ Collection<​FeatureLayer>>​();​ 
 +            for (int i = 1; i <= 20; i++) 
 +            { 
 +                featureLayersInAllZoomLevels.Add(i,​ new Collection<​FeatureLayer>​());​ 
 +            } 
 + 
 +            foreach (FeatureLayer layer in featureLayers) 
 +            { 
 +                Collection<​ZoomLevel>​ layerZoomLevels = layer.ZoomLevelSet.GetZoomLevels();​ 
 + 
 +                for (int i = 1; i <= 20; i++) 
 +                { 
 +                    ZoomLevel zoomLevel = layerZoomLevels[i - 1]; 
 + 
 +                    if (zoomLevel.CustomStyles.Count != 0 || !IsDefaultStyleSet(zoomLevel)) 
 +                    { 
 +                        if ((int)zoomLevel.ApplyUntilZoomLevel == 0) 
 +                        { 
 +                            if (!featureLayersInAllZoomLevels[i].Contains(layer)) 
 +                            { 
 +                                featureLayersInAllZoomLevels[i].Add(layer);​ 
 +                            } 
 +                        } 
 +                        else 
 +                        { 
 +                            for (int j = i; j <= (int)zoomLevel.ApplyUntilZoomLevel;​ j++) 
 +                            { 
 +                                if (!featureLayersInAllZoomLevels[j].Contains(layer)) 
 +                                { 
 +                                    featureLayersInAllZoomLevels[j].Add(layer);​ 
 +                                } 
 +                            } 
 +                        } 
 +                    } 
 +                } 
 +            } 
 + 
 +            return featureLayersInAllZoomLevels;​ 
 +        } 
 + 
 +        private bool IsDefaultStyleSet(ZoomLevel zoomLevel) 
 +        { 
 +            return IsDefaultAreaStyle(zoomLevel.DefaultAreaStyle) && IsDefaultLineStyle(zoomLevel.DefaultLineStyle) && IsDefaultPointStyle(zoomLevel.DefaultPointStyle) && IsDefaultTextStyle(zoomLevel.DefaultTextStyle);​ 
 +        } 
 + 
 +        private bool IsDefaultAreaStyle(AreaStyle style) 
 +        { 
 +            if (!style.IsActive) 
 +            { 
 +                return true; 
 +            } 
 + 
 +            bool isDefault = false; 
 + 
 +            if (style.OutlinePen.Color.IsTransparent && style.FillSolidBrush.Color.IsTransparent && style.OutlinePen.Brush is GeoSolidBrush) 
 +            { 
 +                isDefault = true; 
 +            } 
 + 
 +            if (isDefault && style.Advanced.FillCustomBrush != null) 
 +            { 
 +                isDefault = false; 
 +            } 
 + 
 +            if (isDefault && style.CustomAreaStyles.Count != 0) 
 +            { 
 +                isDefault = false; 
 +            } 
 + 
 +            return isDefault;​ 
 +        } 
 + 
 +        private bool IsDefaultLineStyle(LineStyle style) 
 +        { 
 +            if (!style.IsActive) 
 +            { 
 +                return true; 
 +            } 
 + 
 +            bool isDefault = false; 
 + 
 +            if (style.OuterPen.Color.IsTransparent && style.InnerPen.Color.IsTransparent && style.CenterPen.Color.IsTransparent) 
 +            { 
 +                if (style.OuterPen.Brush is GeoSolidBrush && style.InnerPen.Brush is GeoSolidBrush && style.CenterPen.Brush is GeoSolidBrush) 
 +                { 
 +                    isDefault = true; 
 +                } 
 +            } 
 + 
 +            if (style.CustomLineStyles.Count > 0) 
 +            { 
 +                isDefault = false; 
 +            } 
 + 
 +            return isDefault;​ 
 +        } 
 + 
 +        private bool IsDefaultPointStyle(PointStyle style) 
 +        { 
 +            if (!style.IsActive) 
 +            { 
 +                return true; 
 +            } 
 + 
 +            switch (style.PointType) 
 +            { 
 +                case PointType.Symbol:​ 
 +                    bool isDefault = false; 
 +                    if (style.SymbolPen.Color.IsTransparent && style.SymbolSolidBrush.Color.IsTransparent && style.SymbolPen.Brush is GeoSolidBrush) 
 +                    { 
 +                        isDefault = true; 
 +                    } 
 + 
 +                    if (isDefault && style.Advanced.CustomBrush != null) 
 +                    { 
 +                        isDefault = false; 
 +                    } 
 + 
 +                    return isDefault && style.CustomPointStyles.Count == 0; 
 + 
 +                case PointType.Bitmap:​ 
 +                    return style.Image == null && style.CustomPointStyles.Count == 0; 
 + 
 +                case PointType.Character:​ 
 +                    return style.CharacterSolidBrush.Color.IsTransparent && style.CustomPointStyles.Count == 0; 
 +                default: 
 +                    return true; 
 +            } 
 +        } 
 + 
 +        private bool IsDefaultTextStyle(TextStyle style) 
 +        { 
 +            if (!style.IsActive) 
 +            { 
 +                return true; 
 +            } 
 + 
 +            bool isDefault = false; 
 + 
 +            if (style.TextSolidBrush.Color.IsTransparent) 
 +            { 
 +                isDefault = true; 
 +            } 
 + 
 +            if (isDefault && style.Advanced.TextCustomBrush != null) 
 +            { 
 +                isDefault = false; 
 +            } 
 + 
 +            return isDefault;​ 
 +        } 
 + 
 +        private Feature GetInterSection(Feature feature, Collection<​RectangleShape>​ boundingBoxes) 
 +        { 
 +            Feature result = null; 
 + 
 +            foreach (var boundingBox in boundingBoxes) 
 +            { 
 +                var intersection = feature.GetIntersection(boundingBox.GetFeature());​ 
 +                if (result == null) 
 +                { 
 +                    result = intersection;​ 
 +                } 
 +                else if (intersection != null) 
 +                { 
 +                    result = result.Union(intersection);​ 
 +                } 
 +            } 
 + 
 +            return result; 
 +        } 
 + 
 +        private bool IsDisjointed(Feature feature, Collection<​RectangleShape>​ boundingBoxes) 
 +        { 
 +            bool result = true; 
 +            foreach (var boundingBox in boundingBoxes) 
 +            { 
 +                result = result && feature.IsDisjointed(boundingBox.GetFeature());​ 
 +            } 
 +            return result; 
 +        } 
 + 
 +        private Feature GetDifference(Feature feature, Collection<​RectangleShape>​ boundingBoxes) 
 +        { 
 +            Feature result = null; 
 +            foreach (var boundingBox in boundingBoxes) 
 +            { 
 +                if (result == null) 
 +                { 
 +                    result = SqlTypesGeometryHelper.GetDifference(feature,​ boundingBox.GetFeature());​ 
 +                } 
 +                else 
 +                { 
 +                    result = SqlTypesGeometryHelper.GetDifference(result,​ boundingBox.GetFeature());​ 
 +                } 
 +            } 
 + 
 +            return result;
         }         }
     }     }
 } }
 +
  
 </​code>​ </​code>​
Line 732: Line 1149:
 } }
 </​code>​ </​code>​
 +
 +====BoundingBoxRow.cs====
 +<code csharp>
 +namespace WorldMapKitDataExtractor.Model
 +{
 +    public class BoundingBoxRow
 +    {
 +        public System.Windows.Controls.TextBox txtUpperLeftPoint { get; set; }
 +
 +        public System.Windows.Controls.TextBox txtLowerRightPoint { get; set; }
 +
 +        public System.Windows.Controls.ComboBox cmbStartZoomLevel { get; set; }
 +
 +        public System.Windows.Controls.ComboBox cmbEndZoomLevel { get; set; }
 +
 +        public System.Windows.Controls.CheckBox chkRowEnabled { get; set; }
 +
 +        public BoundingBoxRow() { }
 +
 +        public BoundingBoxRow(System.Windows.Controls.TextBox txtUpperLeftPoint,​ System.Windows.Controls.TextBox txtLowerRightPoint,​ System.Windows.Controls.ComboBox cmbStartZoomLevel,​ System.Windows.Controls.ComboBox cmbEndZoomLevel,​ System.Windows.Controls.CheckBox chkRowEnabled)
 +        {
 +            this.txtUpperLeftPoint = txtUpperLeftPoint;​
 +            this.txtLowerRightPoint = txtLowerRightPoint;​
 +            this.cmbStartZoomLevel = cmbStartZoomLevel;​
 +            this.cmbEndZoomLevel = cmbEndZoomLevel;​
 +            this.chkRowEnabled = chkRowEnabled;​
 +        }
 +    }
 +}
 +</​code>​
 +
 +====BoundingBoxWithZoomLevels.cs====
 +<code csharp>
 +using ThinkGeo.MapSuite.Core;​
 +
 +namespace WorldMapKitDataExtractor.Model
 +{
 +    public struct BoundingBoxWithZoomLevels
 +    {
 +        public RectangleShape BoundingBox { get; }
 +        ​
 +        public int StartingZoomLevel { get; }
 +        ​
 +        public int EndingZoomLevel { get; } 
 +
 +        public BoundingBoxWithZoomLevels(RectangleShape boundingBox,​ int startingZoomLevel,​ int endingZoomLevel)
 +        {
 +            this.BoundingBox = boundingBox;​
 +            this.StartingZoomLevel = startingZoomLevel;​
 +            this.EndingZoomLevel = endingZoomLevel;​
 +        }
 +    }
 +}
 +
 +</​code>​
 +
 +
 ====AssemblyInfo.cs==== ====AssemblyInfo.cs====
 <code csharp> <code csharp>
source_code_osmworldmapkitextractor.zip.1467831409.txt.gz · Last modified: 2016/07/06 18:56 by ryanduan