private void HandleTileResponse(IAsyncResult result) { TileRequestState state = result.AsyncState as TileRequestState; using (var response = state.request.EndGetResponse(result) as HttpWebResponse) { lock (canvasLock) { using (var image = Image.FromStream(response.GetResponseStream())) { state.canvas.DrawImage(image, state.dst, state.src, GraphicsUnit.Pixel); state.canvas.Save(); mapView.SetPropertyThreadSafe("Image", bitmap); mapView.Invalidate(); } planningLabel.SetPropertyThreadSafe("Text", $"Loading {numTilesLeft} tiles . . ."); if (--numTilesLeft <= 0) { state.canvas.Dispose(); planningLabel.SetPropertyThreadSafe("Visible", false); editButton.SetPropertyThreadSafe("Enabled", true); } } } }
private void LoadTiles() { // Only load the tiles encapsulating the map coordinates. double numTilesAcross = Math.Pow(2, TileZoom); int tileX0 = (int)Math.Floor(mapX0 * numTilesAcross); int tileY0 = (int)Math.Floor(mapY0 * numTilesAcross); int tileX1 = (int)Math.Floor(mapX1 * numTilesAcross); int tileY1 = (int)Math.Floor(mapY1 * numTilesAcross); int widthInTiles = (tileX1 - tileX0 + 1); int heightInTiles = (tileY1 - tileY0 + 1); numTilesLeft = widthInTiles * heightInTiles; int mapPixelWidth = (int)((mapX1 - mapX0) * numTilesAcross * TileWidth); int mapPixelHeight = (int)((mapY1 - mapY0) * numTilesAcross * TileWidth); int imageWidth = Math.Max(mapPixelWidth, mapPixelHeight); planningLabel.SetPropertyThreadSafe("Text", $"Loading {numTilesLeft} tiles for {mapName} . . ."); bitmap = new Bitmap(mapPixelWidth, mapPixelHeight); var canvas = Graphics.FromImage(bitmap); int dstX0 = 0; int dstY0 = 0; int dstX1 = 0; int dstY1 = 0; for (int j = tileY0; j <= tileY1; ++j) { dstX0 = 0; for (int i = tileX0; i <= tileX1; ++i) { HttpWebRequest req = (HttpWebRequest)WebRequest.Create($"https://tiles.guildwars2.com/1/1/{TileZoom}/{i}/{j}.jpg"); int srcX0 = (int)Math.Max(0, numTilesAcross * TileWidth * mapX0 - i * TileWidth); int srcY0 = (int)Math.Max(0, numTilesAcross * TileWidth * mapY0 - j * TileWidth); int srcX1 = (int)Math.Min(TileWidth, numTilesAcross * TileWidth * mapX1 - i * TileWidth); int srcY1 = (int)Math.Min(TileWidth, numTilesAcross * TileWidth * mapY1 - j * TileWidth); int srcWidth = srcX1 - srcX0; int srcHeight = srcY1 - srcY0; int dstWidth = srcWidth; int dstHeight = srcHeight; dstX1 = dstX0 + dstWidth; dstY1 = dstY0 + dstHeight; var state = new TileRequestState() { request = req, canvas = canvas, src = new Rectangle(srcX0, srcY0, srcWidth, srcHeight), dst = new Rectangle(dstX0, dstY0, dstWidth, dstHeight) }; req.BeginGetResponse(HandleTileResponse, state); dstX0 = dstX1; } dstY0 = dstY1; } }