@@ -21,6 +21,11 @@ namespace SixLabors.ImageSharp.Drawing.Shapes.PolygonGeometry;
2121/// </remarks>
2222internal sealed class PolygonClipper
2323{
24+ private const float MinimumDistanceThreshold = 1e-6f ;
25+ private const float MinimumAreaThreshold = 1e-6f ;
26+ private const float JoinYTolerance = 1e-6f ;
27+ private const float JoinDistanceSqrdThreshold = 1e-12f ;
28+
2429 private BooleanOperation clipType ;
2530 private ClipperFillRule fillRule ;
2631 private Active actives ; // Head of the active edge list
@@ -1062,7 +1067,8 @@ private void ProcessHorzJoins()
10621067 private static bool PtsReallyClose ( Vector2 pt1 , Vector2 pt2 )
10631068 {
10641069 Vector2 delta = Vector2 . Abs ( pt1 - pt2 ) ;
1065- return delta . X < 1e-6f && delta . Y < 1e-6f ;
1070+ return delta . X < MinimumDistanceThreshold &&
1071+ delta . Y < MinimumDistanceThreshold ;
10661072 }
10671073
10681074 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
@@ -1125,16 +1131,16 @@ private void DoSplitOp(OutRec outrec, OutPt splitOp)
11251131 prevOp . Point , splitOp . Point , splitOp . Next . Point , nextNextOp . Point , out Vector2 ip ) ;
11261132
11271133 float area1 = Area ( prevOp ) ;
1128- float absArea1 = Math . Abs ( area1 ) ;
1134+ float absArea1 = MathF . Abs ( area1 ) ;
11291135
1130- if ( absArea1 < 2 )
1136+ if ( absArea1 < MinimumAreaThreshold )
11311137 {
11321138 outrec . Pts = null ;
11331139 return ;
11341140 }
11351141
11361142 float area2 = AreaTriangle ( ip , splitOp . Point , splitOp . Next . Point ) ;
1137- float absArea2 = Math . Abs ( area2 ) ;
1143+ float absArea2 = MathF . Abs ( area2 ) ;
11381144
11391145 // de-link splitOp and splitOp.next from the path
11401146 // while inserting the intersection point
@@ -1160,7 +1166,7 @@ private void DoSplitOp(OutRec outrec, OutPt splitOp)
11601166 // So the only way for these areas to have the same sign is if
11611167 // the split triangle is larger than the path containing prevOp or
11621168 // if there's more than one self=intersection.
1163- if ( absArea2 > 1 && ( absArea2 > absArea1 || ( ( area2 > 0 ) == ( area1 > 0 ) ) ) )
1169+ if ( absArea2 > MinimumAreaThreshold && ( absArea2 > absArea1 || ( ( area2 > 0 ) == ( area1 > 0 ) ) ) )
11641170 {
11651171 OutRec newOutRec = this . NewOutRec ( ) ;
11661172 newOutRec . Owner = outrec . Owner ;
@@ -3022,15 +3028,15 @@ private void CheckJoinLeft(Active e, Vector2 pt, bool checkCurrX = false)
30223028 }
30233029
30243030 // Avoid trivial joins
3025- if ( ( pt . Y < e . Top . Y + 2 || pt . Y < prev . Top . Y + 2 )
3031+ if ( ( pt . Y < e . Top . Y + JoinYTolerance || pt . Y < prev . Top . Y + JoinYTolerance )
30263032 && ( ( e . Bot . Y > pt . Y ) || ( prev . Bot . Y > pt . Y ) ) )
30273033 {
30283034 return ;
30293035 }
30303036
30313037 if ( checkCurrX )
30323038 {
3033- if ( PolygonClipperUtilities . PerpendicDistFromLineSqrd ( pt , prev . Bot , prev . Top ) > 0.25 )
3039+ if ( PolygonClipperUtilities . PerpendicDistFromLineSqrd ( pt , prev . Bot , prev . Top ) > JoinDistanceSqrdThreshold )
30343040 {
30353041 return ;
30363042 }
@@ -3077,15 +3083,15 @@ private void CheckJoinRight(Active e, Vector2 pt, bool checkCurrX = false)
30773083 }
30783084
30793085 // Avoid trivial joins
3080- if ( ( pt . Y < e . Top . Y + 2 || pt . Y < next . Top . Y + 2 )
3086+ if ( ( pt . Y < e . Top . Y + JoinYTolerance || pt . Y < next . Top . Y + JoinYTolerance )
30813087 && ( ( e . Bot . Y > pt . Y ) || ( next . Bot . Y > pt . Y ) ) )
30823088 {
30833089 return ;
30843090 }
30853091
30863092 if ( checkCurrX )
30873093 {
3088- if ( PolygonClipperUtilities . PerpendicDistFromLineSqrd ( pt , next . Bot , next . Top ) > 0.25 )
3094+ if ( PolygonClipperUtilities . PerpendicDistFromLineSqrd ( pt , next . Bot , next . Top ) > JoinDistanceSqrdThreshold )
30893095 {
30903096 return ;
30913097 }
0 commit comments