private static void DrawWebMercatorTilesToRasterCanvas( SKCanvas outputCanvas, int width, int height, Models.Bounds boundingBox, IList <Models.TileDataset> sourceTiles, uint backgroundColor, int tileSize) { var zoom = sourceTiles[0].Z; var tileMinX = sourceTiles.Min(t => t.X); var tileMinY = sourceTiles.Min(t => t.Y); var tilesCountX = sourceTiles.Max(t => t.X) - tileMinX + 1; var tilesCountY = sourceTiles.Max(t => t.Y) - tileMinY + 1; var canvasWidth = tilesCountX * tileSize; var canvasHeight = tilesCountY * tileSize; var imageInfo = new SKImageInfo( width: canvasWidth, height: canvasHeight, colorType: SKColorType.Rgba8888, alphaType: SKAlphaType.Premul); using var surface = SKSurface.Create(imageInfo); using var canvas = surface.Canvas; canvas.Clear(new SKColor(backgroundColor)); // Draw all tiles foreach (var sourceTile in sourceTiles) { var offsetX = (sourceTile.X - tileMinX) * tileSize; var offsetY = (sourceTile.Y - tileMinY) * tileSize; using var sourceImage = SKImage.FromEncodedData(sourceTile.ImageData); canvas.DrawImage(sourceImage, SKRect.Create(offsetX, offsetY, tileSize, tileSize)); // Source tile scaled to dest rectangle, if needed } // Clip and scale to requested size of output image var geoBBox = EntitiesConverter.MapRectangleToGeographicalBounds(boundingBox); var pixelOffsetX = WebMercator.LongitudeToPixelXAtZoom(geoBBox.MinLongitude, zoom) - tileSize * tileMinX; var pixelOffsetY = WebMercator.LatitudeToPixelYAtZoom(geoBBox.MaxLatitude, zoom) - tileSize * tileMinY; var pixelWidth = WebMercator.LongitudeToPixelXAtZoom(geoBBox.MaxLongitude, zoom) - WebMercator.LongitudeToPixelXAtZoom(geoBBox.MinLongitude, zoom); var pixelHeight = WebMercator.LatitudeToPixelYAtZoom(geoBBox.MinLatitude, zoom) - WebMercator.LatitudeToPixelYAtZoom(geoBBox.MaxLatitude, zoom); var sourceRectangle = SKRect.Create((float)pixelOffsetX, (float)pixelOffsetY, (float)pixelWidth, (float)pixelHeight); var destRectangle = SKRect.Create(0, 0, width, height); using SKImage canvasImage = surface.Snapshot(); outputCanvas.DrawImage(canvasImage, sourceRectangle, destRectangle, new SKPaint { FilterQuality = SKFilterQuality.High, }); }
public static List <Models.TileCoordinates> BuildTileCoordinatesList(Models.Bounds boundingBox, int width) { var geoBBox = EntitiesConverter.MapRectangleToGeographicalBounds(boundingBox); var zoomLevel = FindOptimalTileZoomLevel(width, geoBBox); var tileCoordMin = GetTileCoordinatesAtPoint(geoBBox.MinLongitude, geoBBox.MinLatitude, zoomLevel); var tileCoordMax = GetTileCoordinatesAtPoint(geoBBox.MaxLongitude, geoBBox.MaxLatitude, zoomLevel); var tileCoordinates = new List <Models.TileCoordinates>(); for (var tileX = tileCoordMin.X; tileX <= tileCoordMax.X; tileX++) { for (var tileY = tileCoordMax.Y; tileY <= tileCoordMin.Y; tileY++) { tileCoordinates.Add(new Models.TileCoordinates(tileX, tileY, zoomLevel)); } } return(tileCoordinates); }