Example #1
0
        public byte[] GenerateTile(int x, int y, int zoom)
        {
            byte[] tileBytes = null;
            var    font      = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12);

            var corner        = TileUtils.TileXYToGlobalPixel(x, y, TileSize);
            var latLong       = TileUtils.GlobalPixelToPosition(new Point <double>(corner.X, corner.Y), zoom, TileSize);
            var latLongOffset = TileUtils.GlobalPixelToPosition(new Point <double>(corner.X + TileSize, corner.Y + TileSize), zoom, TileSize);



            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.PositionToGlobalPixel(new LatLong(DebugPoint.Latitude, DebugPoint.Longitude), zoom, TileSize);
                    var testTile  = TileUtils.GlobalPixelToTileXY(testPixel.X, testPixel.Y, TileSize);

                    // Draw test pixel
                    if (testTile.X == x && testTile.Y == y)
                    {
                        var basex = TileUtils.TileXYToGlobalPixel(x, y, TileSize);
                        var ptLoc = new PointF((float)(testPixel.X - basex.X), (float)(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);
        }
Example #2
0
        public TileRange ComputeBoundingBoxTileRangeForZoomLevel(BoundingBox bbox, ImageryProvider provider, int zoom)
        {
            TileRange      tiles       = new TileRange(provider);
            Point <double> topLeft     = TileUtils.PositionToGlobalPixel(new LatLong(bbox.yMax, bbox.xMin), zoom, provider.TileSize);
            Point <double> bottomRight = TileUtils.PositionToGlobalPixel(new LatLong(bbox.yMin, bbox.xMax), zoom, provider.TileSize);
            BoundingBox    mapBbox     = new BoundingBox(topLeft.X, bottomRight.X, topLeft.Y, bottomRight.Y);

            tiles.Start          = new MapTileInfo(TileUtils.GlobalPixelToTileXY(topLeft.X, topLeft.Y, provider.TileSize), zoom, provider.TileSize);
            tiles.End            = new MapTileInfo(TileUtils.GlobalPixelToTileXY(bottomRight.X, bottomRight.Y, provider.TileSize), zoom, provider.TileSize);
            tiles.AreaOfInterest = mapBbox;

            return(tiles);
        }
Example #3
0
        public TileRange ComputeBoundingBoxTileRangeForTargetResolution(BoundingBox bbox, ImageryProvider imageryProvider, int width, int height)
        {
            TileRange tiles = new TileRange(imageryProvider);

            TileUtils.BestMapView(new double[] { bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax }, width, height, 0, imageryProvider.TileSize, out double _, out double _, out double zoom);
            zoom = Math.Round(zoom, 0);
            var topLeft     = TileUtils.PositionToGlobalPixel(new LatLong(bbox.yMax, bbox.xMin), (int)zoom, imageryProvider.TileSize);
            var bottomRight = TileUtils.PositionToGlobalPixel(new LatLong(bbox.yMin, bbox.xMax), (int)zoom, imageryProvider.TileSize);
            var mapBbox     = new BoundingBox(topLeft.X, bottomRight.X, topLeft.Y, bottomRight.Y);

            tiles.Start          = new MapTileInfo(TileUtils.GlobalPixelToTileXY(topLeft.X, topLeft.Y, imageryProvider.TileSize), (int)zoom, imageryProvider.TileSize);
            tiles.End            = new MapTileInfo(TileUtils.GlobalPixelToTileXY(bottomRight.X, bottomRight.Y, imageryProvider.TileSize), (int)zoom, imageryProvider.TileSize);
            tiles.AreaOfInterest = mapBbox;
            return(tiles);
        }
Example #4
0
        public TileRange ComputeBoundingBoxTileRange(BoundingBox bbox, ImageryProvider provider,
                                                     int minTilesPerImage = 4)
        {
            // TODO good one, to test
            // texture quality would be expressed in tex size
            //TileUtils.BestMapView(new double[] { bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax }, 16384, 16384, 0, provider.TileSize, out double centerLat, out double centerLon, out double zoomBestView);

            TileRange      tiles = new TileRange(provider);
            BoundingBox    mapBbox;
            Point <double> topLeft;
            Point <double> bottomRight;

            // optimal zoom calculation (maybe there's a direct way)
            // see : https://docs.microsoft.com/fr-fr/azure/azure-maps/zoom-levels-and-tile-grid?tabs=csharp#tile-math-source-code (prepare tissues for nose bleed, and don't go if you're allergic to trigo and/or magical constants)
            // 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 = 256 * minTilesPerImage; /* fixed to 256px to limit number of tiles */

            do
            {
                zoom++;

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

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

            return(tiles);
        }