Skip to content

Commit e3c42f7

Browse files
authored
Make minimum segment lengths more consistent and configurable (#1854)
* Make minimum segment lengths more consistent and configurable * Add fractal examples for PolygonAnnotation and PolylineAnnotations (#1853)
1 parent 79a5004 commit e3c42f7

9 files changed

Lines changed: 148 additions & 20 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ All notable changes to this project will be documented in this file.
55

66
### Added
77
- Add LineThickness property to TrackerControl (#1831)
8+
- Add properties for `MinimumSegmentLength` to series and annotations (#1853)
9+
- Add fractal examples for PolygonAnnotation and PolylineAnnotations (#1853)
810

911
### Changed
1012
- Update net40 and net45 to net452 (#1835)
13+
- Change default `MinimumSegmentLength` to `2` and remove limits for series and annotations with simple geometry (#1853)
1114

1215
### Removed
1316

‎Source/Examples/ExampleLibrary/Annotations/PolygonAnnotationExamples.cs‎

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,83 @@ public static PlotModel AnnotationLayerProperty()
7676
model.Series.Add(new FunctionSeries(Math.Sin, -20, 30, 400));
7777
return model;
7878
}
79+
80+
[Example("Koch Snowflakes")]
81+
public static PlotModel KockSnowflakes()
82+
{
83+
DataPoint[] triangle(DataPoint centre)
84+
{
85+
return new[]
86+
{
87+
new DataPoint(centre.X, centre.Y + 1),
88+
new DataPoint(centre.X + Math.Sin(Math.PI * 2 / 3), centre.Y + Math.Cos(Math.PI * 2 / 3)),
89+
new DataPoint(centre.X + Math.Sin(Math.PI * 4 / 3), centre.Y + Math.Cos(Math.PI * 4 / 3)),
90+
};
91+
}
92+
93+
var model = new PlotModel { Title = "PolygonAnnotation", PlotType = PlotType.Cartesian };
94+
model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Minimum = -4, Maximum = 4 });
95+
model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Minimum = -2, Maximum = 2 });
96+
97+
var a1 = new PolygonAnnotation { Text = "MSL = 4", MinimumSegmentLength = 4 };
98+
a1.Points.AddRange(KochFractal(triangle(new DataPoint(-2, 0)), 8, true, true));
99+
model.Annotations.Add(a1);
100+
101+
var a2 = new PolygonAnnotation { Text = "MSL = 2", MinimumSegmentLength = 2 };
102+
a2.Points.AddRange(KochFractal(triangle(new DataPoint(0, 0)), 8, true, true));
103+
model.Annotations.Add(a2);
104+
105+
var a3 = new PolygonAnnotation { Text = "MSL = 1", MinimumSegmentLength = 1 };
106+
a3.Points.AddRange(KochFractal(triangle(new DataPoint(2, 0)), 8, true, true));
107+
model.Annotations.Add(a3);
108+
109+
return model;
110+
}
111+
112+
public static DataPoint[] KochFractal(DataPoint[] seed, int n, bool clockwise, bool closed)
113+
{
114+
var cos60 = Math.Cos(Math.PI / 3);
115+
var sin60 = Math.Sin(Math.PI / 3);
116+
var cur = seed;
117+
118+
for (int i = 0; i < n; i++)
119+
{
120+
var next = new DataPoint[closed ? cur.Length * 4 : cur.Length * 4 - 3];
121+
for (int j = 0; j < (closed ? cur.Length : cur.Length - 1); j++)
122+
{
123+
var p0 = cur[j];
124+
var p1 = cur[(j + 1) % cur.Length];
125+
126+
var dx = (p1.X - p0.X) / 3;
127+
var dy = (p1.Y - p0.Y) / 3;
128+
129+
double dx2, dy2;
130+
if (clockwise)
131+
{
132+
dx2 = cos60 * dx - sin60 * dy;
133+
dy2 = cos60 * dy + sin60 * dx;
134+
}
135+
else
136+
{
137+
dx2 = cos60 * dx - sin60 * dy;
138+
dy2 = cos60 * dy + sin60 * dx;
139+
}
140+
141+
next[j * 4] = p0;
142+
next[j * 4 + 1] = new DataPoint(p0.X + dx, p0.Y + dy);
143+
next[j * 4 + 2] = new DataPoint(p0.X + dx + dx2, p0.Y + dy + dy2);
144+
next[j * 4 + 3] = new DataPoint(p0.X + dx * 2, p0.Y + dy * 2);
145+
}
146+
147+
if (!closed)
148+
{
149+
next[next.Length - 1] = cur[cur.Length - 1];
150+
}
151+
152+
cur = next;
153+
}
154+
155+
return cur;
156+
}
79157
}
80-
}
158+
}

‎Source/Examples/ExampleLibrary/Annotations/PolylineAnnotationExamples.cs‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,36 @@ public static PlotModel PolylineAnnotations()
3131
model.Annotations.Add(a2);
3232
return model;
3333
}
34+
35+
[Example("Koch Surfaces")]
36+
public static PlotModel KochSurface()
37+
{
38+
DataPoint[] plane(DataPoint centre)
39+
{
40+
return new[]
41+
{
42+
new DataPoint(centre.X - 1, centre.Y),
43+
new DataPoint(centre.X + 1, centre.Y),
44+
};
45+
}
46+
47+
var model = new PlotModel { Title = "PolygonAnnotation", PlotType = PlotType.Cartesian };
48+
model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Minimum = -2, Maximum = 2 });
49+
model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Minimum = -2, Maximum = 2 });
50+
51+
var a1 = new PolylineAnnotation { Text = "MSL = 4", MinimumSegmentLength = 4, LineStyle = LineStyle.Solid, TextPosition = new DataPoint(0, 1) };
52+
a1.Points.AddRange(PolygonAnnotationExamples.KochFractal(plane(new DataPoint(0, 1)), 8, true, false));
53+
model.Annotations.Add(a1);
54+
55+
var a2 = new PolylineAnnotation { Text = "MSL = 2", MinimumSegmentLength = 2, LineStyle = LineStyle.Solid, TextPosition = new DataPoint(0, 0) };
56+
a2.Points.AddRange(PolygonAnnotationExamples.KochFractal(plane(new DataPoint(0, 0)), 8, true, false));
57+
model.Annotations.Add(a2);
58+
59+
var a3 = new PolylineAnnotation { Text = "MSL = 1", MinimumSegmentLength = 1, LineStyle = LineStyle.Solid, TextPosition = new DataPoint(0, -1) };
60+
a3.Points.AddRange(PolygonAnnotationExamples.KochFractal(plane(new DataPoint(0, -1)), 8, true, false));
61+
model.Annotations.Add(a3);
62+
63+
return model;
64+
}
3465
}
35-
}
66+
}

‎Source/Examples/ExampleLibrary/CustomSeries/ErrorSeries.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public override void Render(IRenderContext rc)
114114
{
115115
rc.DrawReducedLine(
116116
new[] { segments[i], segments[i + 1] },
117-
2,
117+
0,
118118
this.GetSelectableColor(this.Color),
119119
this.StrokeThickness,
120120
this.EdgeRenderingMode,

‎Source/OxyPlot/Annotations/ArrowAnnotation.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public override void Render(IRenderContext rc)
122122
var p3 = p1 - (n * this.HeadWidth * this.StrokeThickness);
123123
var p4 = p1 + (d * this.Veeness * this.StrokeThickness);
124124

125-
const double MinimumSegmentLength = 4;
125+
const double MinimumSegmentLength = 0;
126126

127127
var dashArray = this.LineStyle.GetDashArray();
128128

‎Source/OxyPlot/Annotations/PathAnnotation.cs‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ protected PathAnnotation()
4242
this.TextMargin = 12;
4343
this.TextHorizontalAlignment = HorizontalAlignment.Right;
4444
this.TextVerticalAlignment = VerticalAlignment.Top;
45+
this.MinimumSegmentLength = 2;
4546
}
4647

4748
/// <summary>
@@ -114,6 +115,14 @@ protected PathAnnotation()
114115
/// Other positions are center aligned at the specified position</remarks>
115116
public double TextLinePosition { get; set; }
116117

118+
/// <summary>
119+
/// Gets or sets the minimum length of the segment.
120+
/// Increasing this number will increase performance,
121+
/// but make curves less accurate. The default is <c>2</c>.
122+
/// </summary>
123+
/// <value>The minimum length of the segment.</value>
124+
public double MinimumSegmentLength { get; set; }
125+
117126
/// <summary>
118127
/// Gets or sets the actual minimum value on the x axis.
119128
/// </summary>
@@ -152,16 +161,14 @@ public override void Render(IRenderContext rc)
152161

153162
this.screenPoints = this.GetScreenPoints();
154163

155-
const double MinimumSegmentLength = 4;
156-
157164
var clippedPoints = new List<ScreenPoint>();
158165
var dashArray = this.LineStyle.GetDashArray();
159166

160167
if (this.StrokeThickness > 0 && this.LineStyle != LineStyle.None)
161168
{
162169
rc.DrawReducedLine(
163170
this.screenPoints,
164-
MinimumSegmentLength * MinimumSegmentLength,
171+
this.MinimumSegmentLength * this.MinimumSegmentLength,
165172
this.GetSelectableColor(this.Color),
166173
this.StrokeThickness,
167174
this.EdgeRenderingMode,

‎Source/OxyPlot/Annotations/PolyLineAnnotation.cs‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,6 @@ public List<DataPoint> Points
3434
}
3535
}
3636

37-
/// <summary>
38-
/// Gets or sets the minimum length of the segment.
39-
/// Increasing this number will increase performance,
40-
/// but make the curve less accurate.
41-
/// </summary>
42-
/// <value>The minimum length of the segment.</value>
43-
public double MinimumSegmentLength { get; set; }
44-
4537
/// <summary>
4638
/// Gets or sets the interpolation algorithm.
4739
/// </summary>
@@ -65,4 +57,4 @@ protected override IList<ScreenPoint> GetScreenPoints()
6557
return this.Points.Select(this.Transform).ToList();
6658
}
6759
}
68-
}
60+
}

‎Source/OxyPlot/Annotations/PolygonAnnotation.cs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public PolygonAnnotation()
3030
{
3131
this.LineStyle = LineStyle.Solid;
3232
this.LineJoin = LineJoin.Miter;
33+
this.MinimumSegmentLength = 2;
34+
3335
this.Points = new List<DataPoint>();
3436
}
3537

@@ -45,6 +47,14 @@ public PolygonAnnotation()
4547
/// <value>The line style.</value>
4648
public LineStyle LineStyle { get; set; }
4749

50+
/// <summary>
51+
/// Gets or sets the minimum length of the segment.
52+
/// Increasing this number will increase performance,
53+
/// but make the polygon less accurate. The default is <c>2</c>.
54+
/// </summary>
55+
/// <value>The minimum length of the segment.</value>
56+
public double MinimumSegmentLength { get; set; }
57+
4858
/// <summary>
4959
/// Gets the points.
5060
/// </summary>
@@ -67,11 +77,9 @@ public override void Render(IRenderContext rc)
6777
return;
6878
}
6979

70-
const double MinimumSegmentLength = 4;
71-
7280
rc.DrawReducedPolygon(
7381
this.screenPoints,
74-
MinimumSegmentLength * MinimumSegmentLength,
82+
this.MinimumSegmentLength * this.MinimumSegmentLength,
7583
this.GetSelectableFillColor(this.Fill),
7684
this.GetSelectableColor(this.Stroke),
7785
this.StrokeThickness,

‎Source/OxyPlot/Series/ContourSeries.cs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public ContourSeries()
5454
this.Color = OxyColors.Automatic;
5555
this.StrokeThickness = 1.0;
5656
this.LineStyle = LineStyle.Solid;
57+
this.MinimumSegmentLength = 2;
5758

5859
this.TrackerFormatString = DefaultTrackerFormatString;
5960
}
@@ -153,6 +154,14 @@ public OxyColor ActualColor
153154
/// <value>The stroke thickness.</value>
154155
public double StrokeThickness { get; set; }
155156

157+
/// <summary>
158+
/// Gets or sets the minimum length of the segment.
159+
/// Increasing this number will increase performance,
160+
/// but make the curve less accurate. The default is <c>2</c>.
161+
/// </summary>
162+
/// <value>The minimum length of the segment.</value>
163+
public double MinimumSegmentLength { get; set; }
164+
156165
/// <summary>
157166
/// Calculates the contours.
158167
/// </summary>
@@ -292,7 +301,7 @@ public override void Render(IRenderContext rc)
292301

293302
rc.DrawReducedLine(
294303
transformedPoints,
295-
4,
304+
this.MinimumSegmentLength * this.MinimumSegmentLength,
296305
this.GetSelectableColor(strokeColor),
297306
this.StrokeThickness,
298307
this.EdgeRenderingMode,

0 commit comments

Comments
 (0)