private void DrawTile(MapArgs args, TileInfo info, Resolution resolution, byte[] buffer, TileReprojector tr = null) { if (buffer == null || buffer.Length == 0) return; tr = tr ?? new TileReprojector(args, _projection, _targetProjection); using (var bitmap = (Bitmap)Image.FromStream(new MemoryStream(buffer))) { var inWorldFile = new Reprojection.WorldFile(resolution.UnitsPerPixel, 0, 0, -resolution.UnitsPerPixel, info.Extent.MinX, info.Extent.MaxY); Reprojection.WorldFile outWorldFile; Bitmap outBitmap; tr.Reproject(inWorldFile, bitmap, out outWorldFile, out outBitmap); if (outWorldFile == null) return; var lt = args.ProjToPixel(outWorldFile.ToGround(0, 0)); var rb = args.ProjToPixel(outWorldFile.ToGround(outBitmap.Width, outBitmap.Height)); var rect = new Rectangle(lt, Size.Subtract(new Size(rb), new Size(lt))); args.Device.DrawImage(outBitmap, rect, 0, 0, outBitmap.Width, outBitmap.Height, GraphicsUnit.Pixel, _imageAttributes); if (outBitmap != bitmap) outBitmap.Dispose(); if (FrameTile) { if (FramePen != null) args.Device.DrawRectangle(FramePen, rect); } } }
/// <summary> /// This draws content from the specified geographic regions onto the specified graphics /// object specified by MapArgs. /// </summary> public void DrawRegions(MapArgs args, List<Extent> regions) { // If this layer is not marked visible, exit if (!IsVisible) return; _stopwatch.Reset(); var region = regions.FirstOrDefault() ?? args.GeographicExtents; if (!Monitor.TryEnter(_drawLock)) return; LogManager.DefaultLogManager.LogMessage("MAP : " + region, DialogResult.OK); // If we have a target projection, so project extent to providers extent var geoExtent = _targetProjection == null ? region : region.Intersection(Extent).Reproject(_targetProjection, _projectionInfo); LogManager.DefaultLogManager.LogMessage("SOURCE: " + geoExtent, DialogResult.OK); if (geoExtent.IsEmpty()) { LogManager.DefaultLogManager.LogMessage("Skipping because extent is empty!", DialogResult.OK); Monitor.Exit(_drawLock); return; } BruTile.Extent extent; try { extent = ToBrutileExtent(geoExtent); } catch (Exception ex) { LogManager.DefaultLogManager.Exception(ex); Monitor.Exit(_drawLock); return; } if (double.IsNaN(extent.Area)) { LogManager.DefaultLogManager.LogMessage("Skipping because extent is empty!", DialogResult.OK); Monitor.Exit(_drawLock); return; } var pixelSize = extent.Width/args.ImageRectangle.Width; var tileSource = _configuration.TileSource; var schema = tileSource.Schema; var level = _level = Utilities.GetNearestLevel(schema.Resolutions, pixelSize); _tileFetcher.Clear(); var tiles = new List<TileInfo>(Sort(schema.GetTileInfos(extent, level), geoExtent.Center)); var waitHandles = new List<WaitHandle>(); var tilesNotImmediatelyDrawn = new List<TileInfo>(); LogManager.DefaultLogManager.LogMessage(string.Format("Trying to get #{0} tiles: ", tiles.Count), DialogResult.OK); // Set up Tile reprojector var tr = new TileReprojector(args, _projectionInfo, _targetProjection); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); // Store the current transformation var transform = args.Device.Transform; var resolution = schema.Resolutions[level]; foreach (var info in tiles) { var are = _tileFetcher.AsyncMode ? null : new AutoResetEvent(false); var imageData = _tileFetcher.GetTile(info, are); if (imageData != null) { //DrawTile DrawTile(args, info, resolution, imageData, tr); continue; } if (are == null) continue; waitHandles.Add(are); tilesNotImmediatelyDrawn.Add(info); } //Wait for tiles foreach (var handle in waitHandles) handle.WaitOne(); //Draw the tiles that were not present at the moment requested foreach (var tileInfo in tilesNotImmediatelyDrawn) DrawTile(args, tileInfo, resolution, _tileFetcher.GetTile(tileInfo, null), tr); //Restore the transform args.Device.Transform = transform; sw.Stop(); System.Diagnostics.Debug.WriteLine("{0} ms", sw.ElapsedMilliseconds); System.Diagnostics.Debug.Write(string.Format("Trying to render #{0} tiles: ", tiles.Count)); LogManager.DefaultLogManager.LogMessage(string.Format("{0} ms", sw.ElapsedMilliseconds), DialogResult.OK); //if (InvalidRegion != null) // Invalidate(); //_stopwatch.Restart(); Monitor.Exit(_drawLock); }