private static RectangleF RoundToPixel(Geometries.Point min, Geometries.Point max) { // To get seamless aligning you need to round the // corner coordinates to pixel. The new width and // height will be a result of that. var x = Math.Round(min.X); var y = Math.Round(min.Y); var width = Math.Round(max.X) - Math.Round(min.X); var height = Math.Round(max.Y) - Math.Round(min.Y); return(new RectangleF((float)x, (float)y, (float)width, (float)height)); }
public static RectangleF ConvertPointBoundingBox(SymbolStyle symbolStyle, BoundingBox boundingBox, IViewport viewport) { var screenMin = viewport.WorldToScreen(boundingBox.Min); var screenMax = viewport.WorldToScreen(boundingBox.Max); //boundingBox.Offset = symbolStyle.SymbolOffset; //var newMin = boundingBox.Min; //var newMax = boundingBox.Max; if (symbolStyle.SymbolOffset != null) { screenMin = new Geometries.Point( screenMin.X - symbolStyle.SymbolOffset.X, screenMin.Y - symbolStyle.SymbolOffset.Y); screenMax = new Geometries.Point( screenMax.X - symbolStyle.SymbolOffset.X, screenMax.Y - symbolStyle.SymbolOffset.Y); var w = viewport.ScreenToWorld(screenMin); boundingBox.Offset(new Geometries.Point(w.X - boundingBox.MinX, w.Y - boundingBox.MinY)); screenMin = viewport.WorldToScreen(boundingBox.Min); screenMax = viewport.WorldToScreen(boundingBox.Max); } var min = new Geometries.Point(screenMin.X - (32 / 2), screenMax.Y - (32 / 2)); //!!! var max = new Geometries.Point((min.X + 32), (min.Y + 32)); //!!! var frame = RoundToPixel(min, max); //if(symbolStyle.SymbolOffset != null) // frame.Offset ((float)symbolStyle.SymbolOffset.X, (float)symbolStyle.SymbolOffset.Y); return(frame); }
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 Geometries.Point(cluster.Box.GetCentroid().X, minY); var labelText = labelStyle.GetLabelText(feature); canvas.Children.Add(SingleLabelRenderer.RenderLabel(position, labelStyle, viewport, labelText)); } } return canvas; }
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 Geometries.Point(cluster.Box.GetCentroid().X, minY); var labelText = labelStyle.GetLabelText(feature); canvas.Children.Add(SingleLabelRenderer.RenderLabel(position, labelStyle, viewport, labelText)); } } return(canvas); }