예제 #1
0
        /// <summary>
        /// Gets a tile at a higher zoom level and scales part of it for the requested tile
        /// </summary>
        /// <param name="topLeftTile">The top left tile coordinates</param>
        /// <param name="zoomLevel">The requested zoom level</param>
        /// <param name="path">The file path</param>
        /// <param name="generatedName">The name of the DXF file (for design and alignment files it is generated)</param>
        /// <param name="filespaceId">The filespace ID</param>
        /// <param name="maxZoomLevel">The maximum zoom level for which tiles have been generated</param>
        /// <param name="numTiles">The number of tiles for the requested zoom level</param>
        /// <returns>A scaled tile</returns>
        private async Task <byte[]> GetTileAtHigherZoom(Point topLeftTile, int zoomLevel, string path,
                                                        string generatedName, string filespaceId, int maxZoomLevel, int numTiles)
        {
            int zoomLevelFound = maxZoomLevel;

            // Calculate the tile coords of the higher zoom level tile that covers the requested tile
            Point ptRequestedTile  = new Point(topLeftTile.y, topLeftTile.x);
            Point ptRequestedPixel = WebMercatorProjection.TileToPixel(ptRequestedTile);

            int   numTilesAtRequestedZoomLevel = numTiles;
            Point ptRequestedWorld             =
                WebMercatorProjection.PixelToWorld(ptRequestedPixel, numTilesAtRequestedZoomLevel);

            int   numTilesAtFoundZoomLevel = TileServiceUtils.NumberOfTiles(maxZoomLevel);
            Point ptHigherPixel            = WebMercatorProjection.WorldToPixel(ptRequestedWorld, numTilesAtFoundZoomLevel);

            Point ptHigherTile = WebMercatorProjection.PixelToTile(ptHigherPixel);
            //Note PixelToTile uses Math.Floor so this tile coordinate will be the top left of the tile

            // With the new tile coords of the higher zoom level tile, see if it exists on TCC
            string fullHigherTileName =
                $"{FileUtils.ZoomPath(FileUtils.TilePath(path, generatedName), zoomLevelFound)}/{ptHigherTile.y}/{ptHigherTile.x}.png";

            log.LogDebug("DxfTileExecutor: looking for higher tile {0}", fullHigherTileName);

            byte[] tileData = await DownloadTile(filespaceId, fullHigherTileName, "higher");

            if (tileData != null)
            {
                tileData = ScaleTile(tileData, zoomLevel - zoomLevelFound, ptHigherTile, ptRequestedWorld,
                                     numTilesAtFoundZoomLevel);
            }
            return(tileData);
        }
예제 #2
0
        /// <summary>
        /// Scales a tile
        /// </summary>
        /// <param name="tileData">The tile to scale</param>
        /// <param name="zoomLevelDifference">The difference between the downloaded tile and the rqeuested tile zoom levels</param>
        /// <param name="ptHigherTile"></param>
        /// <param name="ptRequestedWorld"></param>
        /// <param name="numTilesAtFoundZoomLevel">The number of tiles for the higher zoom level</param>
        /// <returns>A scaled tile</returns>
        private byte[] ScaleTile(byte[] tileData, int zoomLevelDifference, Point ptHigherTile, Point ptRequestedWorld,
                                 int numTilesAtFoundZoomLevel)
        {
            // Calculate the tile coords of the BR corner of the higher zoom level tile
            // so that we can identify which sub-part of it to crop and scale
            Point ptHigherTileTopLeft  = ptHigherTile;
            Point ptHigherTileBotRight = new Point(ptHigherTile.y + 1, ptHigherTile.x + 1);

            // Calculate the sub-tile rectangle that we need to crop out of the  higher tile
            // using a simple proportion calculation based on which part of the higher tile
            // covers the original requested tile in world coordinates
            Point ptHigherWorldTopLeft =
                WebMercatorProjection.PixelToWorld(WebMercatorProjection.TileToPixel(ptHigherTileTopLeft),
                                                   numTilesAtFoundZoomLevel);
            Point ptHigherWorldBotRight =
                WebMercatorProjection.PixelToWorld(WebMercatorProjection.TileToPixel(ptHigherTileBotRight),
                                                   numTilesAtFoundZoomLevel);

            double ratioX = (ptRequestedWorld.x - ptHigherWorldTopLeft.x) /
                            (ptHigherWorldBotRight.x - ptHigherWorldTopLeft.x);
            double ratioY = (ptRequestedWorld.y - ptHigherWorldTopLeft.y) /
                            (ptHigherWorldBotRight.y - ptHigherWorldTopLeft.y);

            int startX = (int)Math.Floor(WebMercatorProjection.TILE_SIZE * ratioX);
            int startY = (int)Math.Floor(WebMercatorProjection.TILE_SIZE * ratioY);

            // Calculate how much up-scaling of higher level zoom tile we need to do
            // based on the difference between the requested and higher zoom levels
            int croppedTileSize = WebMercatorProjection.TILE_SIZE / (1 << zoomLevelDifference);

            // Set the crop rectangle and draw it into a new bitmap, scaling it up to the standard tile size
            Rectangle cropRect = new Rectangle(startX, startY, croppedTileSize, croppedTileSize);

            log.LogDebug("DxfTileExecutor: crop rectangle x = {0}, y = {1}, size = {2}", startX, startY,
                         croppedTileSize);

            //source bitmap
            using (var tileStream = new MemoryStream(tileData))
                using (Bitmap higherBitmap = new Bitmap(tileStream))
                    //destination bitmap
                    using (Bitmap target = new Bitmap(WebMercatorProjection.TILE_SIZE, WebMercatorProjection.TILE_SIZE))
                        using (Graphics g = Graphics.FromImage(target))
                        {
                            g.CompositingMode    = CompositingMode.SourceCopy;
                            g.CompositingQuality = CompositingQuality.HighQuality;
                            g.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                            g.SmoothingMode      = SmoothingMode.HighQuality;
                            g.PixelOffsetMode    = PixelOffsetMode.HighQuality;
                            g.DrawImage(higherBitmap, new Rectangle(0, 0, target.Width, target.Height), cropRect,
                                        GraphicsUnit.Pixel);
                            g.Flush();
                            return(target.BitmapToByteArray());
                        }
        }