@@ -36,6 +36,9 @@ public sealed class PolygonStroker
3636 private const double Pi = Math . PI ;
3737 private const double PiMul2 = Math . PI * 2D ;
3838
39+ // The inner miter limit used to clamp joins on acute interior angles.
40+ private const double InnerMiterLimit = 1.01D ;
41+
3942 // Keep at most 2 warm instances per option-set (one active shape and one spare)
4043 // to reduce churn without retaining many rarely reused configurations.
4144 private const int MaxPooledStrokersPerOptions = 2 ;
@@ -79,10 +82,8 @@ public PolygonStroker(StrokeOptions options)
7982 ArgumentNullException . ThrowIfNull ( options ) ;
8083 this . NormalizeOutput = options . NormalizeOutput ;
8184 this . LineJoin = options . LineJoin ;
82- this . InnerJoin = options . InnerJoin ;
8385 this . LineCap = options . LineCap ;
8486 this . MiterLimit = options . MiterLimit ;
85- this . InnerMiterLimit = options . InnerMiterLimit ;
8687 this . ArcDetailScale = options . ArcDetailScale ;
8788 }
8889
@@ -131,34 +132,26 @@ public StrokeOptionsKey(StrokeOptions options)
131132 {
132133 this . NormalizeOutput = options . NormalizeOutput ;
133134 this . LineJoin = options . LineJoin ;
134- this . InnerJoin = options . InnerJoin ;
135135 this . LineCap = options . LineCap ;
136136 this . MiterLimit = options . MiterLimit ;
137- this . InnerMiterLimit = options . InnerMiterLimit ;
138137 this . ArcDetailScale = options . ArcDetailScale ;
139138 }
140139
141140 public bool NormalizeOutput { get ; }
142141
143142 public LineJoin LineJoin { get ; }
144143
145- public InnerJoin InnerJoin { get ; }
146-
147144 public LineCap LineCap { get ; }
148145
149146 public double MiterLimit { get ; }
150147
151- public double InnerMiterLimit { get ; }
152-
153148 public double ArcDetailScale { get ; }
154149
155150 public bool Equals ( StrokeOptionsKey other )
156151 => this . NormalizeOutput == other . NormalizeOutput &&
157152 this . LineJoin == other . LineJoin &&
158- this . InnerJoin == other . InnerJoin &&
159153 this . LineCap == other . LineCap &&
160154 this . MiterLimit == other . MiterLimit &&
161- this . InnerMiterLimit == other . InnerMiterLimit &&
162155 this . ArcDetailScale == other . ArcDetailScale ;
163156
164157 public override bool Equals ( object ? obj ) => obj is StrokeOptionsKey other && this . Equals ( other ) ;
@@ -167,10 +160,8 @@ public override int GetHashCode()
167160 => HashCode . Combine (
168161 this . NormalizeOutput ,
169162 this . LineJoin ,
170- this . InnerJoin ,
171163 this . LineCap ,
172164 this . MiterLimit ,
173- this . InnerMiterLimit ,
174165 this . ArcDetailScale ) ;
175166 }
176167
@@ -266,11 +257,6 @@ public Polygon Stroke(Polygon polygon, double width)
266257 /// </summary>
267258 public double MiterLimit { get ; }
268259
269- /// <summary>
270- /// Gets the inner miter limit used to clamp joins on acute interior angles.
271- /// </summary>
272- public double InnerMiterLimit { get ; }
273-
274260 /// <summary>
275261 /// Gets the tessellation detail scale used for round joins and round caps.
276262 /// Higher values produce more vertices and smoother curves.
@@ -287,11 +273,6 @@ public Polygon Stroke(Polygon polygon, double width)
287273 /// </summary>
288274 public LineCap LineCap { get ; }
289275
290- /// <summary>
291- /// Gets the join style used for sharp interior angles.
292- /// </summary>
293- public InnerJoin InnerJoin { get ; }
294-
295276 /// <summary>
296277 /// Gets a value indicating whether generated contours should be normalized by resolving
297278 /// self-intersections and overlaps.
@@ -1123,52 +1104,12 @@ private void CalcJoin(ref StrokeVertexDistance v0, ref StrokeVertexDistance v1,
11231104 if ( Math . Abs ( cp ) > double . Epsilon && ( cp > 0D ) == ( strokeWidth > 0D ) )
11241105 {
11251106 double limit = Math . Min ( len1 , len2 ) / widthAbs ;
1126- if ( limit < this . InnerMiterLimit )
1107+ if ( limit < InnerMiterLimit )
11271108 {
1128- limit = this . InnerMiterLimit ;
1109+ limit = InnerMiterLimit ;
11291110 }
11301111
1131- switch ( this . InnerJoin )
1132- {
1133- default :
1134- // Bevel-like fallback for inner corners.
1135- this . AddPoint ( v1 . X + dx1 , v1 . Y - dy1 ) ;
1136- this . AddPoint ( v1 . X + dx2 , v1 . Y - dy2 ) ;
1137- break ;
1138-
1139- case InnerJoin . Miter :
1140- this . CalcMiter ( ref v0 , ref v1 , ref v2 , dx1 , dy1 , dx2 , dy2 , LineJoin . MiterRevert , limit , 0D ) ;
1141- break ;
1142-
1143- case InnerJoin . Jag :
1144- case InnerJoin . Round :
1145- // If offsets are close enough, miter produces cleaner inner-corner output.
1146- Vertex offset1 = new ( dx1 , dy1 ) ;
1147- Vertex offset2 = new ( dx2 , dy2 ) ;
1148- double offsetDeltaSquared = Vertex . DistanceSquared ( offset1 , offset2 ) ;
1149- if ( offsetDeltaSquared < len1 * len1 && offsetDeltaSquared < len2 * len2 )
1150- {
1151- this . CalcMiter ( ref v0 , ref v1 , ref v2 , dx1 , dy1 , dx2 , dy2 , LineJoin . MiterRevert , limit , 0D ) ;
1152- }
1153- else if ( this . InnerJoin == InnerJoin . Jag )
1154- {
1155- // Jagged inner join inserts center vertex to preserve cusp.
1156- this . AddPoint ( v1 . X + dx1 , v1 . Y - dy1 ) ;
1157- this . AddPoint ( v1 . X , v1 . Y ) ;
1158- this . AddPoint ( v1 . X + dx2 , v1 . Y - dy2 ) ;
1159- }
1160- else
1161- {
1162- // Rounded inner join bridges via arc passing through the corner.
1163- this . AddPoint ( v1 . X + dx1 , v1 . Y - dy1 ) ;
1164- this . AddPoint ( v1 . X , v1 . Y ) ;
1165- this . CalcArc ( v1 . X , v1 . Y , dx2 , - dy2 , dx1 , - dy1 ) ;
1166- this . AddPoint ( v1 . X , v1 . Y ) ;
1167- this . AddPoint ( v1 . X + dx2 , v1 . Y - dy2 ) ;
1168- }
1169-
1170- break ;
1171- }
1112+ this . CalcMiter ( ref v0 , ref v1 , ref v2 , dx1 , dy1 , dx2 , dy2 , LineJoin . MiterRevert , limit , 0D ) ;
11721113 }
11731114 else
11741115 {
0 commit comments