private static void TestLinesAreDrawnCorrectly(double zoom) { using (var bmp = new Bitmap(200, 200)) { using (var g = Graphics.FromImage(bmp)) { var map = new Map(new Size(200, 200)) { Center = new Coordinate(1, -0.2) }; var line = new LineString(new[] { new Coordinate(0, 0.2), new Coordinate(1, -0.2), new Coordinate(1, 1) }); map.Zoom = zoom; VectorRenderingHelper.DrawLineString(g, line, Pens.Black, map); Assert.IsTrue(ColorEquals(Color.Black, bmp.GetPixel(0, 60)), "Visual glitch detected"); Assert.IsTrue(ColorEquals(Color.Black, bmp.GetPixel(100, 50)), "Visual glitch detected"); } } }
public void RenderManyLinesShouldBeFast() { using (var bmp = new Bitmap(200, 200)) { using (var g = Graphics.FromImage(bmp)) { var map = new Map(new Size(200, 200)) { Center = new Coordinate(1, 0) }; var line = new LineString(new[] { new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(1, 1) }); map.Zoom = 0.000001; //difficult zoom level to make sure limiting kicks in TestHelper.AssertIsFasterThan( 200, () => { for (int i = 0; i < 5000; i++) { //orig (without limiting): 75 ms for 5000 lines on W510 i7 VectorRenderingHelper.DrawLineString(g, line, Pens.Black, map); } }); } } }
public override void OnRender(Graphics g, Map map) { if (!RenderRequired) { return; } if (map.Center == null) { throw (new ApplicationException("Cannot render map. View center not specified")); } if (g == null) { return; } // configure graphics to maximum speed g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; if (updateTheme) { RefreshValuesAndCoordinates(); updateTheme = false; } if (coverage.IsTimeDependent) { if (curentTimeChanged) { RefreshValuesAndCoordinates(); curentTimeChanged = false; } } if (ShowFaces) { Pen pen = null; if (ShowLines) { pen = new Pen(Color.DarkGray, 0.05f); } var brush = new SolidBrush(Color.White); var values2D = GetCoverageValuesVariable().GetValues <double>(); for (var i = 0; i < coverage.Size1 - 1; i++) { for (var j = 0; j < coverage.Size2 - 1; j++) { brush.Color = Theme.GetFillColor(values2D[i, j]); var face = coverage.Faces[i, j]; VectorRenderingHelper.DrawPolygon(g, (IPolygon)face.Geometry, brush, pen, false, map); } } brush.Dispose(); if (pen != null) { pen.Dispose(); } } else if (ShowLines) { var xValues = coverage.X.Values; var yValues = coverage.Y.Values; using (pen = new Pen(Color.DarkGray, 0.05f)) { for (var i = 0; i < coverage.Size1; i++) { for (var j = 0; j < coverage.Size2; j++) { if (i != coverage.Size1 - 1) { var line = new LineString(new ICoordinate[] { new Coordinate(xValues[i, j], yValues[i, j]), new Coordinate(xValues[i + 1, j], yValues[i + 1, j]), }); VectorRenderingHelper.DrawLineString(g, line, pen, map); } if (j != coverage.Size2 - 1) { var line = new LineString(new ICoordinate[] { new Coordinate(xValues[i, j], yValues[i, j]), new Coordinate(xValues[i, j + 1], yValues[i, j + 1]), }); VectorRenderingHelper.DrawLineString(g, line, pen, map); } } } } } if (ShowVertices) { RenderPointsAndValues(g, envelope, map); } }
private void RenderFeatures(Graphics g, Envelope envelope, IMap map) { bool customRendererUsed = false; bool themeOn = Theme != null; lastRenderedCoordinatesCount = 0; int featureCount = 0; var startRenderingTime = DateTime.Now; VectorRenderingHelper.SimplifyGeometryDuringRendering = SimplifyGeometryDuringRendering; // TODO: pass as argument to make parallel render possible var features = GetFeatures(envelope); foreach (IFeature feature in features) { // TODO: improve performance by first decimating geometry and then transforming) // get geometry IGeometry currentGeometry = CoordinateTransformation != null ? GeometryTransform.TransformGeometry(feature.Geometry, CoordinateTransformation.MathTransform) : feature.Geometry; VectorStyle currentVectorStyle = themeOn ? Theme.GetStyle(feature) as VectorStyle : Style; // TODO: make it render only one time foreach (IFeatureRenderer r in CustomRenderers) { customRendererUsed = r.Render(feature, g, this); } if (!customRendererUsed) { //Linestring outlines is drawn by drawing the layer once with a thicker line //before drawing the "inline" on top. if (Style.EnableOutline) { //Draw background of all line-outlines first if (!themeOn || (currentVectorStyle != null && currentVectorStyle.Enabled && currentVectorStyle.EnableOutline)) { switch (currentGeometry.OgcGeometryType) { case OgcGeometryType.LineString: VectorRenderingHelper.DrawLineString(g, currentGeometry as ILineString, currentVectorStyle.Outline, map); break; case OgcGeometryType.MultiLineString: VectorRenderingHelper.DrawMultiLineString(g, currentGeometry as IMultiLineString, currentVectorStyle.Outline, map); break; default: break; } } } VectorRenderingHelper.RenderGeometry(g, map, currentGeometry, currentVectorStyle, DefaultPointSymbol, clippingEnabled); lastRenderedCoordinatesCount += currentGeometry.Coordinates.Length; } featureCount++; } lastRenderedFeaturesCount = featureCount; lastRenderDuration = (DateTime.Now - startRenderingTime).TotalMilliseconds; }
/// <summary> /// Renders the layer /// </summary> /// <param name="g">Graphics object reference</param> /// <param name="map">Map which is rendered</param> public override void OnRender(System.Drawing.Graphics g, IMap map) { if (Style.Enabled && Style.MaxVisible >= map.Zoom && Style.MinVisible < map.Zoom) { if (DataSource == null) { throw (new ApplicationException("DataSource property not set on layer '" + Name + "'")); } g.TextRenderingHint = TextRenderingHint; g.SmoothingMode = SmoothingMode; var features = Parent?.GetFeatures(map.Envelope) ?? GetFeatures(map.Envelope); if (!features.Any()) { return; } //Initialize label collection var labels = new List <Rendering.Label>(); //List<System.Drawing.Rectangle> LabelBoxes; //Used for collision detection //Render labels IGeometry geometry; foreach (var feature in features) { if (CoordinateTransformation != null) { geometry = GeometryTransform.TransformGeometry(feature.Geometry, this.CoordinateTransformation.MathTransform); } else { geometry = feature.Geometry; } ILabelStyle style; if (Theme != null) //If thematics is enabled, lets override the style { style = Theme.GetStyle(feature) as LabelStyle; } else { style = Style; } if (!style.Enabled || (map.Zoom < style.MinVisible || map.Zoom > style.MaxVisible)) { continue; } string text = GetText(feature); if (!string.IsNullOrEmpty(text)) { float rotation = 0; if (!String.IsNullOrEmpty(RotationColumn)) { rotation = FeatureAttributeAccessorHelper.GetAttributeValue <float>(feature, RotationColumn, 0f); } // TODO: Add feature based //int priority = 0; //if (!String.IsNullOrEmpty(RotationColumn)) // rotation = FeatureAttributeAccessorHelper.GetAttributeValue<int>(feature, Priority, 0f); if (geometry is IGeometryCollection) { if (MultipartGeometryBehaviour == MultipartGeometryBehaviourEnum.All) { foreach (IGeometry geom in (geometry as IGeometryCollection)) { Label lbl = CreateLabel(geom, text, rotation, style, map, g); if (lbl != null) { labels.Add(lbl); } } } else if (MultipartGeometryBehaviour == MultipartGeometryBehaviourEnum.CommonCenter) { Label lbl = CreateLabel(geometry, text, rotation, style, map, g); if (lbl != null) { labels.Add(lbl); } } else if (MultipartGeometryBehaviour == MultipartGeometryBehaviourEnum.First) { if ((geometry as IGeometryCollection).Geometries.Length > 0) { Label lbl = CreateLabel((geometry as IGeometryCollection).Geometries[0], text, rotation, style, map, g); if (lbl != null) { labels.Add(lbl); } } } else if (MultipartGeometryBehaviour == MultipartGeometryBehaviourEnum.Largest) { var coll = (geometry as IGeometryCollection); if (coll.NumGeometries > 0) { double largestVal = 0; int idxOfLargest = 0; for (int j = 0; j < coll.NumGeometries; j++) { IGeometry geom = coll.Geometries[j]; if (geom is ILineString && ((ILineString)geom).Length > largestVal) { largestVal = ((ILineString)geom).Length; idxOfLargest = j; } if (geom is IMultiLineString && ((IMultiLineString)geom).Length > largestVal) { largestVal = ((ILineString)geom).Length; idxOfLargest = j; } if (geom is IPolygon && ((IPolygon)geom).Area > largestVal) { largestVal = ((IPolygon)geom).Area; idxOfLargest = j; } if (geom is IMultiPolygon && ((IMultiPolygon)geom).Area > largestVal) { largestVal = ((IMultiPolygon)geom).Area; idxOfLargest = j; } } Label lbl = CreateLabel(coll.Geometries[idxOfLargest], text, rotation, style, map, g); if (lbl != null) { labels.Add(lbl); } } } } else { var lbl = CreateLabel(geometry, text, rotation, style, map, g); if (lbl != null) { labels.Add(lbl); } } } } if (labels.Count > 0) //We have labels to render... { if (this.Style.CollisionDetection && this.labelFilter != null) { this.labelFilter(labels); } for (int i = 0; i < labels.Count; i++) { VectorRenderingHelper.DrawLabel(g, labels[i].LabelPoint, labels[i].Style.Offset, labels[i].Style.Font, labels[i].Style.ForeColor, labels[i].Style.BackColor, Style.Halo, labels[i].Rotation, labels[i].Text, map); } } labels = null; } }
private void RenderFeatures(Graphics g, IEnvelope envelope, Map map) { bool customRendererUsed = false; bool themeOn = Theme != null; IList features = DataSource.GetFeatures(envelope); int featureCount = features.Count; //optimization DateTime startRenderingTime = DateTime.Now; for (int i = 0; i < featureCount; i++) { IFeature currentFeature = (IFeature)features[i]; // get geometry IGeometry currentGeometry = CoordinateTransformation != null ? GeometryTransform.TransformGeometry(currentFeature.Geometry, CoordinateTransformation.MathTransform) : currentFeature.Geometry; VectorStyle currentVectorStyle = themeOn ? Theme.GetStyle(currentFeature) as VectorStyle : Style; // TODO: make it render only one time foreach (IFeatureRenderer renderer in CustomRenderers) { customRendererUsed = renderer.Render(currentFeature, g, this); } if (!customRendererUsed) { //Linestring outlines is drawn by drawing the layer once with a thicker line //before drawing the "inline" on top. if (Style.EnableOutline) { //Draw background of all line-outlines first if (!themeOn || (currentVectorStyle != null && currentVectorStyle.Enabled && currentVectorStyle.EnableOutline)) { switch (currentGeometry.GeometryType) { case "LineString": VectorRenderingHelper.DrawLineString(g, currentGeometry as ILineString, currentVectorStyle.Outline, map); break; case "MultiLineString": VectorRenderingHelper.DrawMultiLineString(g, currentGeometry as IMultiLineString, currentVectorStyle.Outline, map); break; default: break; } } } VectorRenderingHelper.RenderGeometry(g, map, currentGeometry, currentVectorStyle, DefaultPointSymbol, _ClippingEnabled); lastRenderedCoordinatesCount += currentGeometry.Coordinates.Length; } } lastRenderedFeaturesCount = featureCount; lastRenderDuration = (DateTime.Now - startRenderingTime).TotalMilliseconds; }