/// <summary> /// Renders the layer /// </summary> /// <param name="g">Graphics object reference</param> /// <param name="map">Map which is rendered</param> public override void Render(Graphics g, IMapViewPort map) { if (map.Center == null) { throw (new ApplicationException("Cannot render map. View center not specified")); } if (_image == null) { throw new Exception("Image not set"); } // View to render var mapView = map.Envelope; // Layer view var lyrView = _envelope; // Get the view intersection var vi = mapView.Intersection(lyrView); if (!vi.IsNull) { // Image part // ReSharper disable InconsistentNaming var imgLT = Clip(_worldFile.ToRaster(new Coordinate(vi.MinX, vi.MaxY))); var imgRB = Clip(_worldFile.ToRaster(new Coordinate(vi.MaxX, vi.MinY))); var imgRect = new Rectangle(imgLT, PointDiff(imgLT, imgRB, 1)); // Map Part var mapLT = Point.Truncate(map.WorldToImage(new Coordinate(vi.MinX, vi.MaxY))); var mapRB = Point.Ceiling(map.WorldToImage(new Coordinate(vi.MaxX, vi.MinY))); var mapRect = new Rectangle(mapLT, PointDiff(mapLT, mapRB, 1)); // ReSharper restore InconsistentNaming // Set the interpolation mode var tmpInterpolationMode = g.InterpolationMode; g.InterpolationMode = InterpolationMode; // Render the image using (var ia = new ImageAttributes()) { ia.SetColorMatrix(new ColorMatrix { Matrix44 = 1 - Transparency }, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); g.DrawImage(_image, mapRect, imgRect.X, imgRect.Y, imgRect.Width, imgRect.Height, GraphicsUnit.Pixel, ia); } // reset the interpolation mode g.InterpolationMode = tmpInterpolationMode; } base.Render(g, map); }
//private static LineString ReverseLineString(LineString clippedLineString) //{ // var coords = new Stack<Point>(clippedLineString.Vertices); // return new LineString(coords.ToArray()); //} ///// <summary> ///// Function to transform a linestring to a graphics path for further processing ///// </summary> ///// <param name="multiLineString">The Linestring</param> ///// <param name="map">The map</param> ///// <param name="useClipping">A value indicating whether clipping should be applied or not</param> ///// <returns>A GraphicsPath</returns> //public static GraphicsPath MultiLineStringToPath(MultiLineString multiLineString, Map map, bool useClipping) //{ // var gp = new GraphicsPath(FillMode.Alternate); // foreach (var lineString in multiLineString.LineStrings) // gp.AddPath(LineStringToPath(lineString, map, useClipping), false); // return gp; //} //private static GraphicsPath LineToGraphicsPath(LineString line, Map map) //{ // GraphicsPath path = new GraphicsPath(); // path.AddLines(line.TransformToImage(map)); // return path; //} private static void CalculateLabelOnLinestring(ILineString line, ref BaseLabel baseLabel, IMapViewPort map) { double dx, dy; var label = baseLabel as Label; // first find the middle segment of the line var vertices = line.Coordinates; var midPoint = (vertices.Length - 1) / 2; if (vertices.Length > 2) { dx = vertices[midPoint + 1].X - vertices[midPoint].X; dy = vertices[midPoint + 1].Y - vertices[midPoint].Y; } else { midPoint = 0; dx = vertices[1].X - vertices[0].X; dy = vertices[1].Y - vertices[0].Y; } if (dy == 0) { label.Rotation = 0; } else if (dx == 0) { label.Rotation = 90; } else { // calculate angle of line var angle = -Math.Atan(dy / dx) + Math.PI * 0.5; angle *= (180d / Math.PI); // convert radians to degrees label.Rotation = (float)angle - 90; // -90 text orientation } var tmpx = vertices[midPoint].X + (dx * 0.5); var tmpy = vertices[midPoint].Y + (dy * 0.5); label.Location = map.WorldToImage(new Coordinate(tmpx, tmpy)); }
/// <summary> /// Renders the layer /// </summary> /// <param name="graphics">Graphics object reference</param> /// <param name="map">Map which is rendered</param> public override void Render(Graphics graphics, IMapViewPort map) { if (!map.Size.IsEmpty && map.Size.Width > 0 && map.Size.Height > 0) { var bmp = new Bitmap(map.Size.Width, map.Size.Height, PixelFormat.Format32bppArgb); using (var g = Graphics.FromImage(bmp)) { g.InterpolationMode = InterpolationMode; g.Transform = graphics.Transform; var extent = new Extent(map.Envelope.MinX, map.Envelope.MinY, map.Envelope.MaxX, map.Envelope.MaxY); var level = BruTile.Utilities.GetNearestLevel(_source.Schema.Resolutions, map.PixelSize); var tiles = new List <TileInfo>(_source.Schema.GetTileInfos(extent, level)); var tileWidth = _source.Schema.GetTileWidth(level); var tileHeight = _source.Schema.GetTileWidth(level); IList <WaitHandle> waitHandles = new List <WaitHandle>(); var toRender = new ConcurrentDictionary <TileIndex, Stream>(); var takenFromCache = new ConcurrentDictionary <TileIndex, bool>(); foreach (var info in tiles) { var image = _bitmaps.Find(info.Index); if (image != null) { toRender.TryAdd(info.Index, image); takenFromCache.TryAdd(info.Index, true); continue; } if (_fileCache != null && _fileCache.Exists(info.Index)) { var tileBitmap = GetImageFromFileCache(info) as byte[]; var stream = new MemoryStream(tileBitmap); _bitmaps.Add(info.Index, stream); toRender.TryAdd(info.Index, stream); takenFromCache.TryAdd(info.Index, true); continue; } var waitHandle = new AutoResetEvent(false); waitHandles.Add(waitHandle); ThreadPool.QueueUserWorkItem(GetTileOnThread, new object[] { _source, info, toRender, waitHandle, true, takenFromCache }); } foreach (var handle in waitHandles) { handle.WaitOne(); } using (var ia = new ImageAttributes()) { if (!_transparentColor.IsEmpty) { ia.SetColorKey(_transparentColor, _transparentColor); } #if !PocketPC ia.SetWrapMode(WrapMode.TileFlipXY); #endif if (Opacity < 1.0f) { var matrix = new ColorMatrix { Matrix33 = Math.Max(Math.Min(1f, Opacity), 0f) }; ia.SetColorMatrix(matrix); } foreach (var info in tiles) { if (!toRender.ContainsKey(info.Index)) { continue; } var stream = toRender[info.Index]; //_bitmaps.Find(info.Index); if (stream == null) { continue; } //using (var stream = new MemoryStream(buffer)) { stream.Position = 0; using (var bitmap = new Bitmap(stream)) { var min = map.WorldToImage(new Coordinate(info.Extent.MinX, info.Extent.MinY)); var max = map.WorldToImage(new Coordinate(info.Extent.MaxX, info.Extent.MaxY)); min = new PointF((float)Math.Round(min.X), (float)Math.Round(min.Y)); max = new PointF((float)Math.Round(max.X), (float)Math.Round(max.Y)); try { g.DrawImage(bitmap, new Rectangle((int)min.X, (int)max.Y, (int)(max.X - min.X), (int)(min.Y - max.Y)), 0, 0, tileWidth, tileHeight, GraphicsUnit.Pixel, ia); } catch (Exception ee) { Logger.Error(ee.Message); } } } } //Add rendered tiles to cache foreach ( var kvp in toRender.Where(kvp => takenFromCache.ContainsKey(kvp.Key) && !takenFromCache[kvp.Key])) { _bitmaps.Add(kvp.Key, kvp.Value); } using (var transform = new Matrix()) { graphics.Transform = transform; graphics.DrawImageUnscaled(bmp, 0, 0); graphics.Transform = g.Transform; } } } } }
/// <summary> /// Renders the layer /// </summary> /// <param name="graphics">Graphics object reference</param> /// <param name="map">Map which is rendered</param> public override void Render(Graphics graphics, IMapViewPort map) { if (map.Size.IsEmpty || map.Size.Width <= 0 || map.Size.Height <= 0) { return; } var bbox = map.Envelope; var extent = new Extent(bbox.MinX, bbox.MinY, bbox.MaxX, bbox.MaxY); UpdateMemoryCacheMinAndMax(); var schema = _source.Schema; var dictionary = new Dictionary <TileIndex, Tuple <TileInfo, Stream> >(); var levelId = BruTile.Utilities.GetNearestLevel(schema.Resolutions, map.PixelSize); GetTilesWanted(dictionary, schema, _bitmaps, _fileCache, extent, levelId); var sortedFeatures = dictionary.OrderByDescending(t => schema.Resolutions[t.Key.Level].UnitsPerPixel); var tiles = sortedFeatures.ToDictionary(pair => pair.Key, pair => pair.Value).Values.ToList(); using (var imageAttributes = new ImageAttributes()) { if (!_transparentColor.IsEmpty) { imageAttributes.SetColorKey(_transparentColor, _transparentColor); } #if !PocketPC imageAttributes.SetWrapMode(WrapMode.TileFlipXY); #endif if (Opacity < 1.0f) { var matrix = new ColorMatrix { Matrix33 = Math.Max(Math.Min(1f, Opacity), 0f) }; imageAttributes.SetColorMatrix(matrix); } var tileWidth = schema.GetTileWidth(levelId); var tileHeight = schema.GetTileHeight(levelId); foreach (var tile in tiles) { var bmp = tile.Item2; if (bmp != null && bmp.CanRead && bmp.CanSeek) { //draws directly the bitmap var box = new Envelope(new Coordinate(tile.Item1.Extent.MinX, tile.Item1.Extent.MinY), new Coordinate(tile.Item1.Extent.MaxX, tile.Item1.Extent.MaxY)); var min = map.WorldToImage(box.Min()); var max = map.WorldToImage(box.Max()); min = new PointF((float)Math.Round(min.X), (float)Math.Round(min.Y)); max = new PointF((float)Math.Round(max.X), (float)Math.Round(max.Y)); try { bmp.Position = 0; using (var bitmap = new Bitmap(bmp)) { graphics.DrawImage(bitmap, new Rectangle((int)min.X, (int)max.Y, (int)(max.X - min.X), (int)(min.Y - max.Y)), 0, 0, tileWidth, tileHeight, GraphicsUnit.Pixel, imageAttributes); } } catch (Exception ex) { Logger.Warn(ex.Message, ex); //this can be a GDI+ Hell Exception... } } } } }
private static void CalculateLabelAroundOnLineString(ILineString line, ref BaseLabel label, IMapViewPort map, System.Drawing.Graphics g, System.Drawing.SizeF textSize) { var sPoints = line.Coordinates; // only get point in enverlop of map var colPoint = new Collection <PointF>(); var bCheckStarted = false; //var testEnvelope = map.Envelope.Grow(map.PixelSize*10); for (var j = 0; j < sPoints.Length; j++) { if (map.Envelope.Contains(sPoints[j])) { //points[j] = map.WorldToImage(sPoints[j]); colPoint.Add(map.WorldToImage(sPoints[j])); bCheckStarted = true; } else if (bCheckStarted) { // fix bug curved line out of map in center segment of line break; } } if (colPoint.Count > 1) { label.TextOnPathLabel = new TextOnPath(); switch (label.Style.HorizontalAlignment) { case LabelStyle.HorizontalAlignmentEnum.Left: label.TextOnPathLabel.TextPathAlignTop = TextPathAlign.Left; break; case LabelStyle.HorizontalAlignmentEnum.Right: label.TextOnPathLabel.TextPathAlignTop = TextPathAlign.Right; break; case LabelStyle.HorizontalAlignmentEnum.Center: label.TextOnPathLabel.TextPathAlignTop = TextPathAlign.Center; break; default: label.TextOnPathLabel.TextPathAlignTop = TextPathAlign.Center; break; } switch (label.Style.VerticalAlignment) { case LabelStyle.VerticalAlignmentEnum.Bottom: label.TextOnPathLabel.TextPathPathPosition = TextPathPosition.UnderPath; break; case LabelStyle.VerticalAlignmentEnum.Top: label.TextOnPathLabel.TextPathPathPosition = TextPathPosition.OverPath; break; case LabelStyle.VerticalAlignmentEnum.Middle: label.TextOnPathLabel.TextPathPathPosition = TextPathPosition.CenterPath; break; default: label.TextOnPathLabel.TextPathPathPosition = TextPathPosition.CenterPath; break; } var idxStartPath = 0; var numberPoint = colPoint.Count; // start Optimzes Path points var step = 100; if (colPoint.Count >= step * 2) { numberPoint = step * 2;; switch (label.Style.HorizontalAlignment) { case LabelStyle.HorizontalAlignmentEnum.Left: //label.TextOnPathLabel.TextPathAlignTop = SharpMap.Rendering.TextPathAlign.Left; idxStartPath = 0; break; case LabelStyle.HorizontalAlignmentEnum.Right: //label.TextOnPathLabel.TextPathAlignTop = SharpMap.Rendering.TextPathAlign.Right; idxStartPath = colPoint.Count - step; break; case LabelStyle.HorizontalAlignmentEnum.Center: //label.TextOnPathLabel.TextPathAlignTop = SharpMap.Rendering.TextPathAlign.Center; idxStartPath = (int)colPoint.Count / 2 - step; break; default: //label.TextOnPathLabel.TextPathAlignTop = SharpMap.Rendering.TextPathAlign.Center; idxStartPath = (int)colPoint.Count / 2 - step; break; } } // end optimize path point var points = new PointF[numberPoint]; var count = 0; if (colPoint[0].X <= colPoint[colPoint.Count - 1].X) { for (var l = idxStartPath; l < numberPoint + idxStartPath; l++) { points[count] = colPoint[l]; count++; } } else { //reverse the path for (var k = numberPoint - 1 + idxStartPath; k >= idxStartPath; k--) { points[count] = colPoint[k]; count++; } } /* * //get text size in page units ie pixels * float textheight = label.Style.Font.Size; * switch (label.Style.Font.Unit) * { * case GraphicsUnit.Display: * textheight = textheight * g.DpiY / 75; * break; * case GraphicsUnit.Document: * textheight = textheight * g.DpiY / 300; * break; * case GraphicsUnit.Inch: * textheight = textheight * g.DpiY; * break; * case GraphicsUnit.Millimeter: * textheight = (float)(textheight / 25.4 * g.DpiY); * break; * case GraphicsUnit.Pixel: * //do nothing * break; * case GraphicsUnit.Point: * textheight = textheight * g.DpiY / 72; * break; * } * var topFont = new Font(label.Style.Font.FontFamily, textheight, label.Style.Font.Style, GraphicsUnit.Pixel); */ var topFont = label.Style.GetFontForGraphics(g); // using (var path = new GraphicsPath()) { path.AddLines(points); label.TextOnPathLabel.PathColorTop = System.Drawing.Color.Transparent; label.TextOnPathLabel.Text = label.Text; label.TextOnPathLabel.LetterSpacePercentage = 90; label.TextOnPathLabel.FillColorTop = new System.Drawing.SolidBrush(label.Style.ForeColor); label.TextOnPathLabel.Font = topFont; label.TextOnPathLabel.PathDataTop = path.PathData; label.TextOnPathLabel.Graphics = g; //label.TextOnPathLabel.ShowPath=true; //label.TextOnPathLabel.PathColorTop = System.Drawing.Color.YellowGreen; if (label.Style.Halo != null) { label.TextOnPathLabel.ColorHalo = label.Style.Halo; } else { label.TextOnPathLabel.ColorHalo = null;// new System.Drawing.Pen(label.Style.ForeColor, (float)0.5); } } // MeasureString to get region label.TextOnPathLabel.MeasureString = true; label.TextOnPathLabel.DrawTextOnPath(); label.TextOnPathLabel.MeasureString = false; // Get Region label for CollissionDetection here. using (var pathRegion = new GraphicsPath()) { if (label.TextOnPathLabel.RegionList.Count > 0) { //int idxCenter = (int)label.TextOnPathLabel.PointsText.Count / 2; //System.Drawing.Drawing2D.Matrix rotationMatrix = g.Transform.Clone();// new Matrix(); //rotationMatrix.RotateAt(label.TextOnPathLabel.Angles[idxCenter], label.TextOnPathLabel.PointsText[idxCenter]); //if (label.TextOnPathLabel.PointsTextUp.Count > 0) //{ // for (int up = label.TextOnPathLabel.PointsTextUp.Count - 1; up >= 0; up--) // { // label.TextOnPathLabel.PointsText.Add(label.TextOnPathLabel.PointsTextUp[up]); // } //} pathRegion.AddRectangles(label.TextOnPathLabel.RegionList.ToArray()); // get box for detect colission here label.Box = new LabelBox(pathRegion.GetBounds()); //g.FillRectangle(System.Drawing.Brushes.YellowGreen, label.Box); } } } }
private static BaseLabel CreateLabel(FeatureDataRow fdr, IGeometry feature, string text, float rotation, int priority, LabelStyle style, IMapViewPort map, Graphics g, GetLocationMethod _getLocationMethod) { if (feature == null) { return(null); } BaseLabel lbl = null; var font = style.GetFontForGraphics(g); var size = VectorRenderer.SizeOfString(g, text, font); if (feature is ILineal) { var line = feature as ILineString; if (line != null) { if (style.IsTextOnPath == false) { if (size.Width < 0.95 * line.Length / map.PixelWidth || style.IgnoreLength) { var positiveLineString = PositiveLineString(line, false); var lineStringPath = LineStringToPath(positiveLineString, map /*, false*/); var rect = lineStringPath.GetBounds(); if (style.CollisionDetection && !style.CollisionBuffer.IsEmpty) { var cbx = style.CollisionBuffer.Width; var cby = style.CollisionBuffer.Height; rect.Inflate(2 * cbx, 2 * cby); rect.Offset(-cbx, -cby); } var labelBox = new LabelBox(rect); lbl = new PathLabel(text, lineStringPath, 0, priority, labelBox, style); } } else { //get centriod var position2 = map.WorldToImage(feature.EnvelopeInternal.Centre); lbl = new Label(text, position2, rotation, priority, style); if (size.Width < 0.95 * line.Length / map.PixelWidth || !style.IgnoreLength) { CalculateLabelAroundOnLineString(line, ref lbl, map, g, size); } } } return(lbl); } var worldPosition = _getLocationMethod == null ? feature.EnvelopeInternal.Centre : _getLocationMethod(fdr); if (worldPosition == null) { return(null); } var position = Transform.WorldtoMap(worldPosition, map); var location = new PointF( position.X - size.Width * (short)style.HorizontalAlignment * 0.5f, position.Y - size.Height * (short)(2 - (int)style.VerticalAlignment) * 0.5f); if (location.X - size.Width > map.Size.Width || location.X + size.Width < 0 || location.Y - size.Height > map.Size.Height || location.Y + size.Height < 0) { return(null); } if (!style.CollisionDetection) { lbl = new Label(text, location, rotation, priority, null, style) { LabelPoint = position } } ; else { //Collision detection is enabled so we need to measure the size of the string lbl = new Label(text, location, rotation, priority, new LabelBox(location.X - style.CollisionBuffer.Width, location.Y - style.CollisionBuffer.Height, size.Width + 2f * style.CollisionBuffer.Width, size.Height + 2f * style.CollisionBuffer.Height), style) { LabelPoint = position }; } /* * if (feature is LineString) * { * var line = feature as LineString; * * //Only label feature if it is long enough, or it is definately wanted * if (line.Length / map.PixelSize > size.Width || style.IgnoreLength) * { * CalculateLabelOnLinestring(line, ref lbl, map); * } * else * return null; * } */ return(lbl); }