Skip to content

Commit 04cfe60

Browse files
Copy rust implementation
1 parent 56b43db commit 04cfe60

File tree

4 files changed

+43
-31
lines changed

4 files changed

+43
-31
lines changed

src/PolygonClipper/PolygonClipper.cs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ public Polygon Run()
137137
// Process all segments in the clipping polygon
138138
min = new Vertex(double.PositiveInfinity);
139139
max = new Vertex(double.NegativeInfinity);
140+
140141
for (int i = 0; i < clipping.ContourCount; i++)
141142
{
142143
Contour contour = clipping[i];
143-
bool exterior = operation != BooleanOperation.Difference;
144-
if (exterior)
144+
if (operation != BooleanOperation.Difference)
145145
{
146146
contourId++;
147147
}
@@ -153,8 +153,7 @@ public Polygon Run()
153153
}
154154

155155
Box2 clippingBB = new(min, max);
156-
if (TryTrivialOperationForNonOverlappingBoundingBoxes(subject, clipping, subjectBB, clippingBB, operation,
157-
out result))
156+
if (TryTrivialOperationForNonOverlappingBoundingBoxes(subject, clipping, subjectBB, clippingBB, operation, out result))
158157
{
159158
return result;
160159
}
@@ -393,6 +392,10 @@ private static void ComputeFields(SweepEvent le, SweepEvent? prev, BooleanOperat
393392
{
394393
le.InOut = false;
395394
le.OtherInOut = true;
395+
396+
// Clearing the previous result is necessary for recomputing the result.
397+
// if the first computation has set the result it is not valid anymore.
398+
le.PrevInResult = null;
396399
}
397400
else if (le.PolygonType == prev.PolygonType)
398401
{
@@ -404,15 +407,28 @@ private static void ComputeFields(SweepEvent le, SweepEvent? prev, BooleanOperat
404407
{
405408
// Previous line segment in sl belongs to a different polygon that "se" belongs to.
406409
le.InOut = !prev.OtherInOut;
407-
le.OtherInOut = prev.Vertical() ? !prev.InOut : prev.InOut;
410+
le.OtherInOut = prev.Vertical ? !prev.InOut : prev.InOut;
408411
}
409412

410-
// Compute PrevInResult field
413+
// Connect to previous in result: Only use the given `prev` if it is
414+
// part of the result and not a vertical segment. Otherwise connect
415+
// to its previous in result if any.
411416
if (prev != null)
412417
{
413-
le.PrevInResult = (!InResult(prev, operation) || prev.Vertical())
414-
? prev.PrevInResult
415-
: prev;
418+
if (prev.InResult && !prev.Vertical)
419+
{
420+
le.PrevInResult = prev;
421+
}
422+
else if (prev.PrevInResult != null)
423+
{
424+
le.PrevInResult = prev.PrevInResult;
425+
}
426+
else
427+
{
428+
// Clearing the previous result is necessary for recomputing the result.
429+
// if the first computation has set the result it is not valid anymore.
430+
le.PrevInResult = null;
431+
}
416432
}
417433

418434
// Check if the line segment belongs to the Boolean operation
@@ -742,11 +758,9 @@ private static Polygon ConnectEdges(List<SweepEvent> sortedEvents, SweepEventCom
742758
for (int i = 0; i < sortedEvents.Count; i++)
743759
{
744760
SweepEvent se = sortedEvents[i];
745-
if ((se.Left && se.InResult))
746-
{
747-
resultEvents.Add(se);
748-
}
749-
else if (!se.Left && se.OtherEvent.InResult)
761+
bool include = (se.Left && se.InResult) || (!se.Left && se.OtherEvent.InResult);
762+
763+
if (include)
750764
{
751765
resultEvents.Add(se);
752766
}
@@ -831,7 +845,6 @@ private static Polygon ConnectEdges(List<SweepEvent> sortedEvents, SweepEventCom
831845

832846
Polygon polygon = new();
833847

834-
835848
for (int i = 0; i < result.ContourCount; i++)
836849
{
837850
Contour contour = result[i];

src/PolygonClipper/ResultTransition.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ namespace PolygonClipper;
99
public enum ResultTransition
1010
{
1111
/// <summary>
12-
/// The event does not contribute to the result.
12+
/// The event transitions within the result.
1313
/// </summary>
14-
NonContributing = -1,
14+
Neutral = 0,
1515

1616
/// <summary>
17-
/// The event transitions within the result.
17+
/// The event does not contribute to the result.
1818
/// </summary>
19-
Neutral = 0,
19+
NonContributing = 1,
2020

2121
/// <summary>
2222
/// The event contributes to the result.
2323
/// </summary>
24-
Contributing = 1
24+
Contributing = 2
2525
}

src/PolygonClipper/SweepEvent.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ public SweepEvent(Vertex point, bool left, int contourId)
129129
/// </summary>
130130
public bool InResult => this.ResultTransition != ResultTransition.Neutral;
131131

132+
/// <summary>
133+
/// Gets a value indicating whether the line segment (point, otherEvent->point) is a vertical line segment.
134+
/// </summary>
135+
/// <returns>
136+
/// <see langword="true"/> if the line segment is vertical; otherwise <see langword="false"/>.
137+
/// </returns>
138+
public bool Vertical => this.Point.X == this.OtherEvent.Point.X;
139+
132140
/// <summary>
133141
/// Gets or sets the position of the event in the sorted events.
134142
/// </summary>
@@ -167,15 +175,6 @@ public bool Below(Vertex p)
167175
[MethodImpl(MethodImplOptions.AggressiveInlining)]
168176
public bool Above(Vertex p) => !this.Below(p);
169177

170-
/// <summary>
171-
/// Is the line segment (point, otherEvent->point) a vertical line segment.
172-
/// </summary>
173-
/// <returns>
174-
/// <see langword="true"/> if the line segment is vertical; otherwise <see langword="false"/>.
175-
/// </returns>
176-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
177-
public bool Vertical() => this.Point.X == this.OtherEvent.Point.X;
178-
179178
/// <summary>
180179
/// Returns the segment associated with the sweep event.
181180
/// </summary>

tests/PolygonClipper.Tests/SweepEventTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void IsAbove()
4949
public void IsVertical()
5050
{
5151
// Act & Assert
52-
Assert.True(new SweepEvent(new Vertex(0, 0), true, new SweepEvent(new Vertex(0, 1), false)).Vertical());
53-
Assert.False(new SweepEvent(new Vertex(0, 0), true, new SweepEvent(new Vertex(0.0001F, 1), false)).Vertical());
52+
Assert.True(new SweepEvent(new Vertex(0, 0), true, new SweepEvent(new Vertex(0, 1), false)).Vertical);
53+
Assert.False(new SweepEvent(new Vertex(0, 0), true, new SweepEvent(new Vertex(0.0001F, 1), false)).Vertical);
5454
}
5555
}

0 commit comments

Comments
 (0)