public static Canvas RenderStackedLabelLayer(IViewport viewport, LabelLayer layer) { var canvas = new Canvas(); canvas.Opacity = layer.Opacity; //todo: take into account the priority var features = layer.GetFeaturesInView(viewport.Extent, viewport.Resolution); var margin = viewport.Resolution * 50; foreach (var layerStyle in layer.Styles) { var style = layerStyle; var clusters = new List <Cluster>(); //todo: repeat until there are no more merges ClusterFeatures(clusters, features, margin, layerStyle, viewport.Resolution); foreach (var cluster in clusters) { Offset stackOffset = null; foreach (var feature in cluster.Features.OrderBy(f => f.Geometry.GetBoundingBox().GetCentroid().Y)) { if (layerStyle is IThemeStyle) { style = (layerStyle as IThemeStyle).GetStyle(feature); } if ((style == null) || (style.Enabled == false) || (style.MinVisible > viewport.Resolution) || (style.MaxVisible < viewport.Resolution)) { continue; } if (stackOffset == null) //first time { stackOffset = new Offset(); if (cluster.Features.Count > 1) { canvas.Children.Add(RenderBox(cluster.Box, viewport)); } } else { stackOffset.Y += 18; //todo: get size from text, (or just pass stack nr) } if (!(style is LabelStyle)) { throw new Exception("Style of label is not a LabelStyle"); } var labelStyle = style as LabelStyle; string labelText = layer.GetLabel(feature); var position = new Mapsui.Geometries.Point(cluster.Box.GetCentroid().X, cluster.Box.Bottom); canvas.Children.Add(RenderLabel(position, stackOffset, labelStyle, viewport, labelText)); } } } return(canvas); }
public static Canvas RenderLabelLayer(IViewport viewport, LabelLayer layer) { var canvas = new Canvas { Opacity = layer.Opacity }; // todo: take into account the priority var features = layer.GetFeaturesInView(viewport.Extent, viewport.Resolution).ToList(); var layerStyles = BaseLayer.GetLayerStyles(layer); foreach (var layerStyle in layerStyles) { foreach (var feature in features) { var style = (layerStyle is IThemeStyle) ? (layerStyle as IThemeStyle).GetStyle(feature) : layerStyle; if ((style == null) || (style.Enabled == false) || (style.MinVisible > viewport.Resolution) || (style.MaxVisible < viewport.Resolution)) { continue; } if (!(style is LabelStyle)) { throw new Exception("Style of label is not a LabelStyle"); } var labelStyle = style as LabelStyle; labelStyle.Text = layer.GetLabelText(feature); var postion = feature.Geometry.GetBoundingBox().GetCentroid(); var labelText = labelStyle.GetLabelText(feature); canvas.Children.Add(SingleLabelRenderer.RenderLabel(postion, labelStyle, viewport, labelText)); } } return(canvas); }
public static void Render(Graphics graphics, IViewport viewport, LabelLayer labelLayer) { var layerStyles = BaseLayer.GetLayerStyles(labelLayer); foreach (var layerStyle in layerStyles) { if (layerStyle.Enabled && labelLayer.MaxVisible >= viewport.Resolution && labelLayer.MinVisible < viewport.Resolution) { if (labelLayer.DataSource == null) { throw (new ApplicationException("DataSource property not set")); } graphics.SmoothingMode = SmoothingMode.AntiAlias; var features = labelLayer.GetFeaturesInView(viewport.Extent, viewport.Resolution); //Initialize label collection var labels = new List <Label>(); var style = layerStyle as LabelStyle; //List<System.Drawing.Rectangle> LabelBoxes; //Used for collision detection //Render labels foreach (IFeature feature in features) { if (layerStyle is IThemeStyle) { style = (layerStyle as IThemeStyle).GetStyle(feature) as LabelStyle; } float rotation = 0; if (!String.IsNullOrEmpty(labelLayer.RotationColumn)) { rotation = float.Parse(feature[labelLayer.RotationColumn].ToString(), NumberStyles.Any, CultureInfo.InvariantCulture); } int priority = labelLayer.Priority; if (labelLayer.PriorityDelegate != null) { priority = labelLayer.PriorityDelegate(feature); } else if (!String.IsNullOrEmpty(labelLayer.PriorityColumn)) { priority = int.Parse(feature[labelLayer.PriorityColumn].ToString(), NumberStyles.Any, CultureInfo.InvariantCulture); } string text; if (labelLayer.LabelStringDelegate != null) { text = labelLayer.LabelStringDelegate(feature); } else { text = feature[labelLayer.LabelColumn].ToString(); } if (!string.IsNullOrEmpty(text)) { if (feature.Geometry is GeometryCollection) { var geometryCollection = feature.Geometry as GeometryCollection; if (labelLayer.MultipartGeometryBehaviour == LabelLayer.MultipartGeometryBehaviourEnum.All) { foreach (var geometry in geometryCollection) { var label = CreateLabel(geometry, text, rotation, priority, style, viewport, graphics); if (label != null) { labels.Add(label); } } } else if (labelLayer.MultipartGeometryBehaviour == LabelLayer.MultipartGeometryBehaviourEnum.CommonCenter) { var label = CreateLabel(feature.Geometry, text, rotation, priority, style, viewport, graphics); if (label != null) { labels.Add(label); } } else if (labelLayer.MultipartGeometryBehaviour == LabelLayer.MultipartGeometryBehaviourEnum.First) { if ((feature.Geometry as GeometryCollection).Collection.Count > 0) { Label label = CreateLabel(geometryCollection.Collection[0], text, rotation, 0, style, viewport, graphics); if (label != null) { labels.Add(label); } } } else if (labelLayer.MultipartGeometryBehaviour == LabelLayer.MultipartGeometryBehaviourEnum.Largest) { var coll = (feature.Geometry as GeometryCollection); if (coll.NumGeometries > 0) { double largestVal = 0; int idxOfLargest = 0; for (var j = 0; j < coll.NumGeometries; j++) { Geometry geom = coll.Geometry(j); if (geom is LineString && ((LineString)geom).Length > largestVal) { largestVal = ((LineString)geom).Length; idxOfLargest = j; } if (geom is MultiLineString && ((MultiLineString)geom).Length > largestVal) { largestVal = ((MultiLineString)geom).Length; idxOfLargest = j; } if (geom is Polygon && ((Polygon)geom).Area > largestVal) { largestVal = ((Polygon)geom).Area; idxOfLargest = j; } if (geom is MultiPolygon && ((MultiPolygon)geom).Area > largestVal) { largestVal = ((MultiPolygon)geom).Area; idxOfLargest = j; } } var label = CreateLabel(coll.Geometry(idxOfLargest), text, rotation, priority, style, viewport, graphics); if (label != null) { labels.Add(label); } } } } else { var label = CreateLabel(feature.Geometry, text, rotation, priority, style, viewport, graphics); if (label != null) { labels.Add(label); } } } } if (labels.Count > 0) //We have labels to render... { if ((layerStyle is LabelStyle) && (layerStyle as LabelStyle).CollisionDetection && labelLayer.LabelFilter != null) { labelLayer.LabelFilter(labels); } foreach (Label label in labels) { if (!label.Show) { continue; } LabelRenderer.DrawLabel(graphics, label.LabelPoint, label.Style.Offset, label.Style.Font, label.Style.ForeColor, label.Style.BackColor, label.Halo, label.Rotation, label.Text, viewport); } } } } }
public static List <IFeature> RenderStackedLabelLayer(IViewport viewport, LabelLayer layer) { var renderedFeatures = new List <IFeature> (); var canvas = new CALayer(); canvas.Opacity = (float)layer.Opacity; //todo: take into account the priority var features = layer.GetFeaturesInView(viewport.Extent, viewport.Resolution); var margin = viewport.Resolution * 50; if (layer.Style != null) { var clusters = new List <Cluster>(); //todo: repeat until there are no more merges ClusterFeatures(clusters, features, margin, layer.Style, viewport.Resolution); foreach (var cluster in clusters) { var feature = cluster.Features.OrderBy(f => f.Geometry.GetBoundingBox().GetCentroid().Y).FirstOrDefault(); //SetFeatureOutline (feature, layer.Name, cluster.Features.Count); //var bb = RenderBox(cluster.Box, viewport); //Zorg dat dit ALTIJD decimal zelfde ISet als ViewChanged is //var feature = cluster.Features.FirstOrDefault (); var styles = feature.Styles ?? Enumerable.Empty <IStyle>(); foreach (var style in styles) { if (feature.Styles != null && style.Enabled) { var styleKey = layer.Name; //feature.GetHashCode ().ToString (); var renderedGeometry = (feature[styleKey] != null) ? (CALayer)feature[styleKey] : null; var labelText = layer.GetLabelText(feature); if (renderedGeometry == null) { //Mapsui.Geometries.Point point, Offset stackOffset, LabelStyle style, IFeature feature, IViewport viewport, string text) renderedGeometry = RenderLabel(feature.Geometry as Mapsui.Geometries.Point, style as LabelStyle, feature, viewport, labelText); feature [styleKey] = renderedGeometry; feature ["first"] = true; } else { feature ["first"] = false; } } } renderedFeatures.Add(feature); /* * Offset stackOffset = null; * * foreach (var feature in cluster.Features.OrderBy(f => f.Geometry.GetBoundingBox().GetCentroid().Y)) * { * if (layerStyle is IThemeStyle) style = (layerStyle as IThemeStyle).GetStyle(feature); * if ((style == null) || (style.Enabled == false) || (style.MinVisible > viewport.Resolution) || (style.MaxVisible < viewport.Resolution)) continue; * * if (stackOffset == null) //first time * { * stackOffset = new Offset(); * if (cluster.Features.Count > 1) * canvas.AddSublayer (RenderBox(cluster.Box, viewport)); * } * else stackOffset.Y += 18; //todo: get size from text, (or just pass stack nr) * * if (!(style is LabelStyle)) throw new Exception("Style of label is not a LabelStyle"); * var labelStyle = style as LabelStyle; * string labelText = layer.GetLabel(feature); * var position = new Mapsui.Geometries.Point(cluster.Box.GetCentroid().X, cluster.Box.Bottom); * canvas.AddSublayer(RenderLabel(position, stackOffset, labelStyle, feature, viewport, labelText)); * } */ } } return(renderedFeatures); }
public static Canvas Render(IViewport viewport, LabelLayer layer) { // todo: Move stack functionality to Mapsui core. // step 1) Split RenderStackedLabelLayer into a method // GetFeaturesInViewStacked en a RenderStackedLabel // which can later be replace by normal label rendering. // The method GetFeaturesInViewStacked // returns a style with an offset determined by the stackoffset // and a position determined by CenterX en Cluster.Box.Bottom. // step 2) Move GetFeaturesInViewStacked to a GetFeaturesInView // method of a new StackedLabelLayed. var canvas = new Canvas { Opacity = layer.Opacity }; // todo: take into account the priority var features = layer.GetFeaturesInView(viewport.Extent, viewport.Resolution).ToArray(); var margin = viewport.Resolution * 50; const int symbolSize = 32; // todo: determine margin by symbol size const int boxMargin = symbolSize / 2; var clusters = new List <Cluster>(); //todo: repeat until there are no more merges ClusterFeatures(clusters, features, margin, layer.Style, viewport.Resolution); const int textHeight = 18; foreach (var cluster in clusters) { var stackOffsetY = double.NaN; var orderedFeatures = cluster.Features.OrderBy(f => f.Geometry.GetBoundingBox().GetCentroid().Y); if (cluster.Features.Count > 1) { canvas.Children.Add(RenderBox(cluster.Box, viewport)); } foreach (var feature in orderedFeatures) { if (double.IsNaN(stackOffsetY)) // first time { stackOffsetY = textHeight * 0.5 + boxMargin; } else { stackOffsetY += textHeight; //todo: get size from text (or just pass stack nr) } LabelStyle style; if (layer.Style is IThemeStyle) { style = (LabelStyle)((IThemeStyle)layer.Style).GetStyle(feature); } else { style = (LabelStyle)layer.Style; } var labelStyle = new LabelStyle(style) { Text = layer.GetLabelText(feature) //we only use the layer for the text, this should be returned by style }; labelStyle.Offset.Y += stackOffsetY; // Since the box can be rotated, find the minimal Y value of all 4 corners var rotatedBox = cluster.Box.Rotate(-viewport.Rotation); var minY = rotatedBox.Vertices.Select(v => v.Y).Min(); var position = new Point(cluster.Box.GetCentroid().X, minY); var labelText = labelStyle.GetLabelText(feature); canvas.Children.Add(SingleLabelRenderer.RenderLabel(position, labelStyle, viewport, labelText)); } } return(canvas); }