Fixed a bug in ClipperBase::FixSelfIntersects (#1067)
Fixed a bug in Clipper.pas (Delphi only) re. left to right evaluation of if statements (#1061) Replaced throw statements with DoError function. (C++ only; #1068)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 5 November 2025 *
|
||||
* Date : 21 February 2026 *
|
||||
* Website : https://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2025 *
|
||||
* Copyright : Angus Johnson 2010-2026 *
|
||||
* Purpose : This is the main polygon clipping module *
|
||||
* License : https://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
@@ -617,7 +617,7 @@ namespace Clipper2Lib {
|
||||
{return a + path.size(); });
|
||||
if (total_vertex_count == 0) return;
|
||||
|
||||
Vertex* vertices = new Vertex[total_vertex_count], * v = vertices;
|
||||
Vertex* allVertices = new Vertex[total_vertex_count], * v = allVertices;
|
||||
for (const Path64& path : paths)
|
||||
{
|
||||
//for each path create a circular double linked list of vertices
|
||||
@@ -709,7 +709,7 @@ namespace Clipper2Lib {
|
||||
}
|
||||
} // end processing current path
|
||||
|
||||
vertexLists.emplace_back(vertices);
|
||||
vertexLists.emplace_back(allVertices);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -1653,25 +1653,14 @@ namespace Clipper2Lib {
|
||||
if (SegmentsIntersect(op2->prev->pt,
|
||||
op2->pt, op2->next->pt, op2->next->next->pt))
|
||||
{
|
||||
if (SegmentsIntersect(op2->prev->pt,
|
||||
op2->pt, op2->next->next->pt, op2->next->next->next->pt))
|
||||
{
|
||||
// adjacent intersections (ie a micro self-intersections)
|
||||
op2 = DuplicateOp(op2, false);
|
||||
op2->pt = op2->next->next->next->pt;
|
||||
op2 = op2->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op2 == outrec->pts || op2->next == outrec->pts)
|
||||
outrec->pts = outrec->pts->prev;
|
||||
DoSplitOp(outrec, op2);
|
||||
if (!outrec->pts) break;
|
||||
op2 = outrec->pts;
|
||||
if (op2->prev == op2->next->next)
|
||||
break; // again, because triangles can't self-intersect
|
||||
continue;
|
||||
}
|
||||
if (op2 == outrec->pts || op2->next == outrec->pts)
|
||||
outrec->pts = outrec->pts->prev;
|
||||
DoSplitOp(outrec, op2);
|
||||
if (!outrec->pts) break;
|
||||
op2 = outrec->pts;
|
||||
if (op2->prev == op2->next->next)
|
||||
break; // again, because triangles can't self-intersect
|
||||
continue;
|
||||
}
|
||||
else
|
||||
op2 = op2->next;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 13 December 2025 *
|
||||
* Date : 21 February 2026 *
|
||||
* Release : BETA RELEASE *
|
||||
* Website : https://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2025 *
|
||||
* Copyright : Angus Johnson 2010-2026 *
|
||||
* Purpose : Constrained Delaunay Triangulation *
|
||||
* License : https://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
@@ -196,7 +196,7 @@ namespace Clipper2Lib
|
||||
static void RemoveEdgeFromVertex(Vertex2* vert, Edge* edge)
|
||||
{
|
||||
auto it = std::find(vert->edges.begin(), vert->edges.end(), edge);
|
||||
if (it == vert->edges.end()) throw "oops!";
|
||||
if (it == vert->edges.end()) DoError(undefined_error_i);
|
||||
vert->edges.erase(it);
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ namespace Clipper2Lib
|
||||
for (int i = 1; i < 3; ++i)
|
||||
{
|
||||
edge->triA->edges[i] = edgesA[i];
|
||||
if (!edgesA[i]) throw "oops"; // stops compiler warnings
|
||||
if (!edgesA[i]) DoError(undefined_error_i);
|
||||
if (IsLooseEdge(*edgesA[i]))
|
||||
pendingDelaunayStack.push(edgesA[i]);
|
||||
// since each edge has its own triangleA and triangleB, we have to be careful
|
||||
@@ -447,14 +447,14 @@ namespace Clipper2Lib
|
||||
edgesA[i]->triA = edge->triA;
|
||||
else if (edgesA[i]->triB == edge->triB)
|
||||
edgesA[i]->triB = edge->triA;
|
||||
else throw "oops";
|
||||
else DoError(undefined_error_i);
|
||||
}
|
||||
|
||||
edge->triB->edges[0] = edge;
|
||||
for (int i = 1; i < 3; ++i)
|
||||
{
|
||||
edge->triB->edges[i] = edgesB[i];
|
||||
if (!edgesB[i]) throw "oops"; // stops compiler warnings
|
||||
if (!edgesB[i]) DoError(undefined_error_i);
|
||||
if (IsLooseEdge(*edgesB[i]))
|
||||
pendingDelaunayStack.push(edgesB[i]);
|
||||
// since each edge has its own triangleA and triangleB, we have to be careful
|
||||
@@ -465,7 +465,7 @@ namespace Clipper2Lib
|
||||
edgesB[i]->triA = edge->triB;
|
||||
else if (edgesB[i]->triB == edge->triA)
|
||||
edgesB[i]->triB = edge->triB;
|
||||
else throw "oops";
|
||||
else DoError(undefined_error_i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 5 November 2025 *
|
||||
* Date : 21 February 2026 *
|
||||
* Website : https://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2025 *
|
||||
* Copyright : Angus Johnson 2010-2026 *
|
||||
* Purpose : This is the main polygon clipping module *
|
||||
* Thanks : Special thanks to Thong Nguyen, Guus Kuiper, Phil Stopford, *
|
||||
* : and Daniel Gosnell for their invaluable assistance with C#. *
|
||||
@@ -2970,25 +2970,14 @@ private void DoHorizontal(Active horz)
|
||||
if (InternalClipper.SegsIntersect(op2!.prev.pt,
|
||||
op2.pt, op2.next!.pt, op2.next.next!.pt))
|
||||
{
|
||||
if (InternalClipper.SegsIntersect(op2.prev.pt,
|
||||
op2.pt, op2.next.next!.pt, op2.next.next.next!.pt))
|
||||
{
|
||||
// adjacent intersections (ie a micro self-intersection)
|
||||
op2 = DuplicateOp(op2, false);
|
||||
op2.pt = op2.next!.next!.next!.pt;
|
||||
op2 = op2.next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op2 == outrec.pts || op2.next == outrec.pts)
|
||||
outrec.pts = outrec.pts.prev;
|
||||
DoSplitOp(outrec, op2);
|
||||
if (outrec.pts == null) return;
|
||||
op2 = outrec.pts;
|
||||
// triangles can't self-intersect
|
||||
if (op2.prev == op2.next!.next) break;
|
||||
continue;
|
||||
}
|
||||
if (op2 == outrec.pts || op2.next == outrec.pts)
|
||||
outrec.pts = outrec.pts.prev;
|
||||
DoSplitOp(outrec, op2);
|
||||
if (outrec.pts == null) return;
|
||||
op2 = outrec.pts;
|
||||
// triangles can't self-intersect
|
||||
if (op2.prev == op2.next!.next) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
op2 = op2.next!;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<ApplicationIcon>Clipper2.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<ApplicationIcon>Clipper2.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<ApplicationIcon>Clipper2.ico</ApplicationIcon>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<ApplicationIcon>Clipper2.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2,9 +2,9 @@ unit Clipper.Engine;
|
||||
|
||||
(*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 5 November 2025 *
|
||||
* Date : 21 February 2026 *
|
||||
* Website : https://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2025 *
|
||||
* Copyright : Angus Johnson 2010-2026 *
|
||||
* Purpose : This is the main polygon clipping module *
|
||||
* License : https://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************)
|
||||
@@ -1945,7 +1945,8 @@ begin
|
||||
begin
|
||||
if IsHeadingLeftHorz(rightB) then SwapActives(leftB, rightB);
|
||||
end
|
||||
else if (leftB.dx < rightB.dx) then SwapActives(leftB, rightB);
|
||||
else if (leftB.dx < rightB.dx) then
|
||||
SwapActives(leftB, rightB);
|
||||
//so when leftB has windDx == 1, the polygon will be oriented
|
||||
//counter-clockwise in Cartesian coords (clockwise with inverted Y).
|
||||
end
|
||||
@@ -1987,7 +1988,7 @@ begin
|
||||
begin
|
||||
rbn := rightB.nextInAEL;
|
||||
IntersectEdges(rightB, rbn, rightB.bot);
|
||||
SwapPositionsInAEL(rightB, rightB.nextInAEL);
|
||||
SwapPositionsInAEL(rightB, rbn);
|
||||
end;
|
||||
|
||||
if IsHorizontal(rightB) then
|
||||
@@ -2229,25 +2230,15 @@ begin
|
||||
if SegmentsIntersect(op2.prev.pt, op2.pt,
|
||||
op2.next.pt, op2.next.next.pt) then
|
||||
begin
|
||||
if SegmentsIntersect(op2.prev.pt, op2.pt,
|
||||
op2.next.next.pt, op2.next.next.next.pt) then
|
||||
begin
|
||||
// adjacent intersections (ie a micro self-intersection)
|
||||
op2 := DuplicateOp(op2, false);
|
||||
op2.pt := op2.next.next.next.pt;
|
||||
op2 := op2.next;
|
||||
end else
|
||||
begin
|
||||
if (op2 = outrec.pts) or (op2.next = outrec.pts) then
|
||||
outrec.pts := outrec.pts.prev;
|
||||
// split required
|
||||
DoSplitOp(outrec, op2);
|
||||
if not assigned(outrec.pts) then Break;
|
||||
op2 := outrec.pts;
|
||||
if (op2.prev = op2.next.next) then
|
||||
Break; // because triangles can't self-intersect
|
||||
Continue;
|
||||
end;
|
||||
// split required.
|
||||
if (op2 = outrec.pts) or (op2.next = outrec.pts) then
|
||||
outrec.pts := outrec.pts.prev;
|
||||
DoSplitOp(outrec, op2);
|
||||
if not assigned(outrec.pts) then Break;
|
||||
op2 := outrec.pts;
|
||||
if (op2.prev = op2.next.next) then
|
||||
Break; // because triangles can't self-intersect
|
||||
Continue;
|
||||
end else
|
||||
op2 := op2.next;
|
||||
if (op2 = outrec.pts) then Break;
|
||||
@@ -2919,14 +2910,14 @@ function HorzontalsOverlap(const horz1a, horz1b, horz2a, horz2b: TPoint64): bool
|
||||
begin
|
||||
if horz1a.X < horz1b.X then
|
||||
begin
|
||||
Result := Iif(horz2a.X < horz2b.X,
|
||||
HorzOverlapWithLRSet(horz1a, horz1b, horz2a, horz2b),
|
||||
HorzOverlapWithLRSet(horz1a, horz1b, horz2b, horz2a));
|
||||
if (horz2a.X < horz2b.X) then
|
||||
Result := HorzOverlapWithLRSet(horz1a, horz1b, horz2a, horz2b) else
|
||||
Result := HorzOverlapWithLRSet(horz1a, horz1b, horz2b, horz2a);
|
||||
end else
|
||||
begin
|
||||
Result := Iif(horz2a.X < horz2b.X,
|
||||
HorzOverlapWithLRSet(horz1b, horz1a, horz2a, horz2b),
|
||||
HorzOverlapWithLRSet(horz1b, horz1a, horz2b, horz2a));
|
||||
if (horz2a.X < horz2b.X) then
|
||||
Result := HorzOverlapWithLRSet(horz1b, horz1a, horz2a, horz2b) else
|
||||
Result := HorzOverlapWithLRSet(horz1b, horz1a, horz2b, horz2a);
|
||||
end;
|
||||
end;
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -3188,7 +3179,9 @@ begin
|
||||
else
|
||||
begin
|
||||
ip.Y := Iif(ip.Y < topY, topY , fBotY);
|
||||
ip.X := Iif(absDx1 < absDx2, TopX(e1, ip.Y), TopX(e2, ip.Y));
|
||||
if absDx1 < absDx2 then
|
||||
ip.X := TopX(e1, ip.Y) else
|
||||
ip.X := TopX(e2, ip.Y);
|
||||
end;
|
||||
end;
|
||||
new(node);
|
||||
|
||||
Reference in New Issue
Block a user