Пример #1
0
        public TileRange DownloadTiles(BoundingBox bbox, ImageryProvider provider, int minTilesPerImage = 4)
        {
            TileRange   tiles       = new TileRange(provider);
            BoundingBox mapBbox     = null;
            PointInt    topLeft     = new PointInt();
            PointInt    bottomRight = new PointInt();

            // optimal zoom calculation (maybe there's a direct way)
            // calculate the size of the full bbox at increasing zoom levels
            // until the full image would be greater than a tile
            int zoom = 0;

            do
            {
                zoom++;

                // coords are pixels in global map image (see TileUtils.MapSize(zoom))
                topLeft     = TileUtils.LatLongToPixelXY(bbox.yMax, bbox.xMin, zoom);
                bottomRight = TileUtils.LatLongToPixelXY(bbox.yMin, bbox.xMax, zoom);
                mapBbox     = new BoundingBox(topLeft.X, bottomRight.X, topLeft.Y, bottomRight.Y);
            }while (zoom < provider.MaxZoom &&
                    (mapBbox.Width < provider.TileSize * minTilesPerImage && mapBbox.Height < provider.TileSize * minTilesPerImage));

            // now we have the minimum zoom without image
            // we can know which tiles are needed
            tiles.Start          = new MapTileInfo(TileUtils.PixelXYToTileXY(topLeft.X, topLeft.Y), zoom);
            tiles.End            = new MapTileInfo(TileUtils.PixelXYToTileXY(bottomRight.X, bottomRight.Y), zoom);
            tiles.AreaOfInterest = mapBbox;

            // downdload tiles
            Stopwatch swDownload = Stopwatch.StartNew();

            _logger?.LogTrace("Starting images download");


            // 2 max download threads
            var options = new ParallelOptions()
            {
                MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
            };
            var range = tiles.EnumerateRange().ToList();

            _logger.LogInformation($"Downloading {range.Count} tiles...");

            Parallel.ForEach(range, options, tileInfo =>
            {
                Uri tileUri = BuildUri(provider, tileInfo.X, tileInfo.Y, tileInfo.Zoom);
                _logger?.LogInformation($"Downloading {tileUri}");

                var contentbytes = _httpClient.GetByteArrayAsync(tileUri).Result;
                tiles.Add(new MapTile(contentbytes, provider.TileSize, tileUri, tileInfo));
            }
                             );

            swDownload.Stop();
            _logger?.LogInformation($"DownloadImages done in : {swDownload.Elapsed:g}");


            return(tiles);
        }
Пример #2
0
        public TileRange ComputeBoundingBoxTileRange(BoundingBox bbox, ImageryProvider provider, int minTilesPerImage = 4)
        {
            TileRange   tiles = new TileRange(provider);
            BoundingBox mapBbox;
            PointInt    topLeft;
            PointInt    bottomRight;

            // optimal zoom calculation (maybe there's a direct way)
            // calculate the size of the full bbox at increasing zoom levels
            // until the full image would be greater than a tile
            int zoom    = 0;
            int maxSize = provider.TileSize * minTilesPerImage;

            do
            {
                zoom++;

                // coords are pixels in global map image (see TileUtils.MapSize(zoom))
                topLeft     = TileUtils.LatLongToPixelXY(bbox.yMax, bbox.xMin, zoom);
                bottomRight = TileUtils.LatLongToPixelXY(bbox.yMin, bbox.xMax, zoom);
                mapBbox     = new BoundingBox(topLeft.X, bottomRight.X, topLeft.Y, bottomRight.Y);
            }while (zoom < provider.MaxZoom &&
                    (mapBbox.Width < maxSize || mapBbox.Height < maxSize));

            // now we have the minimum zoom without image
            // we can know which tiles are needed
            tiles.Start          = new MapTileInfo(TileUtils.PixelXYToTileXY(topLeft.X, topLeft.Y), zoom);
            tiles.End            = new MapTileInfo(TileUtils.PixelXYToTileXY(bottomRight.X, bottomRight.Y), zoom);
            tiles.AreaOfInterest = mapBbox;

            return(tiles);
        }
Пример #3
0
        public byte[] GenerateTile(int x, int y, int zoom)
        {
            byte[] tileBytes = null;
            var    font      = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12);

            var corner        = TileUtils.TileXYToPixelXY(x, y);
            var latLong       = TileUtils.PixelXYToLatLong(corner.X, corner.Y, zoom);
            var latLongOffset = TileUtils.PixelXYToLatLong(corner.X + TileSize, corner.Y + TileSize, zoom);



            var graticules = graticuleService.DrawCore(latLong, latLongOffset);


            using (Image <Rgba32> outputImage = new Image <Rgba32>(this.TileSize, this.TileSize))
            {
                string tileText = $"{x}/{y}/{zoom}{Environment.NewLine}";
                outputImage.Mutate(o => o
                                   .Fill(Rgba32.White)
                                   .DrawText(tileText, font, Rgba32.Black, new PointF(10, 10))
                                   );
                outputImage.Mutate(o => DrawGraticules(o, graticules, corner, zoom));



                // Test
                if (DebugPoint != null)
                {
                    var testPixel = TileUtils.LatLongToPixelXY(DebugPoint.Latitude, DebugPoint.Longitude, zoom);
                    var testTile  = TileUtils.PixelXYToTileXY(testPixel.X, testPixel.Y);

                    // Draw test pixel
                    if (testTile.X == x && testTile.Y == y)
                    {
                        var basex = TileUtils.TileXYToPixelXY(x, y);
                        var ptLoc = new PointF(testPixel.X - basex.X, testPixel.Y - basex.Y);
                        outputImage.Mutate(o =>
                                           o.DrawLines(Rgba32.Blue, 1f,
                                                       new PointF[] { new PointF(ptLoc.X - 10, ptLoc.Y - 10), new PointF(ptLoc.X + 10, ptLoc.Y + 10) })
                                           .DrawLines(Rgba32.Blue, 1f,
                                                      new PointF[] { new PointF(ptLoc.X - 10, ptLoc.Y + 10), new PointF(ptLoc.X + 10, ptLoc.Y - 10) }));
                    }
                }

                using (MemoryStream ms = new MemoryStream())
                {
                    outputImage.SaveAsPng(ms);
                    tileBytes = ms.ToArray();
                }
            }

            return(tileBytes);
        }