private void ExtractTiles(PolygonShape polygonShape, string targetFilePath) { RectangleShape bbox = polygonShape.GetBoundingBox(); List <VectorTileRange> tileRanges = new List <VectorTileRange>(); for (int zoomLevel = 0; zoomLevel <= maxZoom; zoomLevel++) { VectorTileRange tileRange = GetTileRange(zoomLevel, bbox); tileRanges.Add(tileRange); } ThinkGeoMBTilesLayer.CreateDatabase(targetFilePath); var targetDBConnection = new SqliteConnection($"Data Source={targetFilePath}"); targetDBConnection.Open(); var targetMap = new TilesTable(targetDBConnection); var targetMetadata = new MetadataTable(targetDBConnection); var sourceDBConnection = new SqliteConnection($"Data Source={mbtilesPathFilename}"); sourceDBConnection.Open(); var sourceMap = new TilesTable(sourceDBConnection); var sourceMetadata = new MetadataTable(sourceDBConnection); sourceMetadata.ReadAllEntries(); ProjectionConverter projection = new ProjectionConverter(3857, 4326); projection.Open(); var wgs84BBox = projection.ConvertToExternalProjection(bbox); foreach (MetadataEntry entry in sourceMetadata.Entries) { if (entry.Name.Equals("center")) { PointShape centerPoint = wgs84BBox.GetCenterPoint(); entry.Value = $"{centerPoint.X},{centerPoint.Y},{maxZoom}"; } else if (entry.Name.Equals("bounds")) { entry.Value = $"{wgs84BBox.UpperLeftPoint.X},{wgs84BBox.UpperLeftPoint.Y},{wgs84BBox.LowerRightPoint.X},{wgs84BBox.LowerRightPoint.Y}"; } } targetMetadata.Insert(sourceMetadata.Entries); int recordLimit = 1000; foreach (var tileRange in tileRanges) { long offset = 0; bool isEnd = false; while (!isEnd) { string querySql = $"SELECT * FROM {sourceMap.TableName} WHERE " + ConvetToSqlString(tileRange) + $" LIMIT {offset},{recordLimit}"; var entries = sourceMap.Query(querySql); for (int i = entries.Count - 1; i >= 0; i--) { RectangleShape pbfExtent = GetPbfTileExent((int)entries[i].ZoomLevel, entries[i].TileColumn, entries[i].TileRow); if (polygonShape.IsDisjointed(pbfExtent)) { entries.RemoveAt(i); } } targetMap.Insert(entries); if (entries.Count < recordLimit) { isEnd = true; } offset = offset + recordLimit; } } }