Ejemplo n.º 1
0
        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;
                }
            }
        }
Ejemplo n.º 2
0
        private async static Task Process(ShapeFileFeatureLayer shapeFile, string targetMbtiles, CancellationToken cancellationToken, int minZoom, int maxZoom, int tileSize, List <string> includedAttributes = null)
        {
            Console.Out.WriteLine("Processing tiles. StartZoom:{0}, EndZoom:{1}", minZoom, maxZoom);

            RectangleShape shapeFileBounds = shapeFile.GetBoundingBox();

            shapeFile.Close();

            ThinkGeoMBTilesLayer.CreateDatabase(targetMbtiles);
            var targetDBConnection = new SqliteConnection($"Data Source={targetMbtiles}");

            targetDBConnection.Open();

            // Meta Table
            var targetMetadata = new MetadataTable(targetDBConnection);

            PointShape centerPoint = shapeFileBounds.GetCenterPoint();
            string     center      = $"{centerPoint.X},{centerPoint.Y},{maxZoom}";
            string     bounds      = $"{shapeFileBounds.UpperLeftPoint.X},{shapeFileBounds.UpperLeftPoint.Y},{shapeFileBounds.LowerRightPoint.X},{shapeFileBounds.LowerRightPoint.Y}";

            List <MetadataEntry> Entries = new List <MetadataEntry>();

            Entries.Add(new MetadataEntry()
            {
                Name = "name", Value = "ThinkGeo World Streets"
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "format", Value = "pbf"
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "bounds", Value = bounds
            });                                                                   //"-96.85310250357627,33.10809235525063,-96.85260897712004,33.107616047247156"
            Entries.Add(new MetadataEntry()
            {
                Name = "center", Value = center
            });                                                                   // "-96.85285574034816,33.1078542012489,14"
            Entries.Add(new MetadataEntry()
            {
                Name = "minzoom", Value = $"{minZoom}"
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "maxzoom", Value = $"{maxZoom}"
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "attribution", Value = "Copyright @2020 ThinkGeo LLC.All rights reserved."
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "description", Value = "ThinkGeo World Street Vector Tile Data in EPSG:3857"
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "version", Value = "2.0"
            });
            Entries.Add(new MetadataEntry()
            {
                Name = "json", Value = ""
            });
            targetMetadata.Insert(Entries);

            // Tile Table
            var targetMap             = new TilesTable(targetDBConnection);
            List <TilesEntry> entries = new List <TilesEntry>();

            string targetFolder = Path.Combine(Path.GetDirectoryName(targetMbtiles), Path.GetFileNameWithoutExtension(targetMbtiles), "-tmp");

            if (!Directory.Exists(targetFolder))
            {
                Directory.CreateDirectory(targetFolder);
            }

            SphericalMercatorZoomLevelSet zoomLevelSet = new SphericalMercatorZoomLevelSet();
            double      currentScale = GetZoomLevelIndex(zoomLevelSet, minZoom);
            var         tileMatrix   = TileMatrix.GetDefaultMatrix(currentScale, tileSize, tileSize, GeographyUnit.Meter);
            var         tileRange    = tileMatrix.GetIntersectingRowColumnRange(shapeFileBounds);
            List <Task> tasks        = new List <Task>();

            for (long tileY = tileRange.MinRowIndex; tileY <= tileRange.MaxRowIndex && !cancellationToken.IsCancellationRequested; ++tileY)
            {
                for (long tileX = tileRange.MinColumnIndex; tileX <= tileRange.MaxColumnIndex && !cancellationToken.IsCancellationRequested; ++tileX)
                {
                    Task task = ProcessTileRecursive(shapeFile, (int)tileY, (int)tileX, minZoom, maxZoom, cancellationToken, targetFolder, includedAttributes);
                    tasks.Add(task);
                }
            }

            foreach (var task in tasks)
            {
                await task;
            }

            await Task.Run(() =>
            {
                long index = 0;

                string[] files = Directory.GetFiles(targetFolder, "*.mvt");
                foreach (string file in files)
                {
                    string fileName     = Path.GetFileNameWithoutExtension(file);
                    string[] NameValues = fileName.Split('_');

                    byte[] bytes = File.ReadAllBytes(file);

                    TilesEntry newEntry = new TilesEntry();
                    int zoomLevel       = int.Parse(NameValues[0]);
                    newEntry.ZoomLevel  = zoomLevel;
                    long row            = long.Parse(NameValues[1]);
                    row = (long)Math.Pow(2, zoomLevel) - row - 1;
                    newEntry.TileRow    = row;
                    newEntry.TileColumn = long.Parse(NameValues[2]);
                    newEntry.TileId     = index++;
                    newEntry.TileData   = bytes;
                    File.Delete(file);

                    entries.Add(newEntry);

                    if (index % 1000 == 0)
                    {
                        targetMap.Insert(entries);
                        entries.Clear();
                        continue;
                    }
                }
                targetMap.Insert(entries);
            });

            targetDBConnection.Close();
        }