Skip to content

Commit

Permalink
Clipper.Engine - minor tweak to IntersectEdges function (#798)
Browse files Browse the repository at this point in the history
  • Loading branch information
AngusJohnson committed Apr 17, 2024
1 parent fdd312b commit 7714d94
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 75 deletions.
6 changes: 3 additions & 3 deletions CPP/Clipper2Lib/include/clipper2/clipper.engine.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 13 December 2023 *
* Date : 17 April 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : This is the main polygon clipping module *
* License : http://www.boost.org/LICENSE_1_0.txt *
*******************************************************************************/
Expand Down Expand Up @@ -230,7 +230,7 @@ namespace Clipper2Lib {
inline bool PopHorz(Active *&e);
inline OutPt* StartOpenPath(Active &e, const Point64& pt);
inline void UpdateEdgeIntoAEL(Active *e);
OutPt* IntersectEdges(Active &e1, Active &e2, const Point64& pt);
void IntersectEdges(Active &e1, Active &e2, const Point64& pt);
inline void DeleteFromAEL(Active &e);
inline void AdjustCurrXAndCopyToSEL(const int64_t top_y);
void DoIntersections(const int64_t top_y);
Expand Down
37 changes: 20 additions & 17 deletions CPP/Clipper2Lib/src/clipper.engine.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 25 March 2024 *
* Date : 17 April 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : This is the main polygon clipping module *
Expand Down Expand Up @@ -1121,7 +1121,7 @@ namespace Clipper2Lib {
inline bool IsCollinear(const Point64& pt1,
const Point64& sharedPt, const Point64& pt2) // #777
{
#ifdef __APPLE__
#ifdef __aarch64__
double cp = CrossProduct(pt1, sharedPt, pt2);
return std::fabs(cp) < 0.00000001;
#else
Expand Down Expand Up @@ -1782,12 +1782,12 @@ namespace Clipper2Lib {
}


OutPt* ClipperBase::IntersectEdges(Active& e1, Active& e2, const Point64& pt)
void ClipperBase::IntersectEdges(Active& e1, Active& e2, const Point64& pt)
{
//MANAGE OPEN PATH INTERSECTIONS SEPARATELY ...
if (has_open_paths_ && (IsOpen(e1) || IsOpen(e2)))
{
if (IsOpen(e1) && IsOpen(e2)) return nullptr;
if (IsOpen(e1) && IsOpen(e2)) return;
Active* edge_o, * edge_c;
if (IsOpen(e1))
{
Expand All @@ -1801,22 +1801,27 @@ namespace Clipper2Lib {
}
if (IsJoined(*edge_c)) Split(*edge_c, pt); // needed for safety

if (abs(edge_c->wind_cnt) != 1) return nullptr;
if (abs(edge_c->wind_cnt) != 1) return;
switch (cliptype_)
{
case ClipType::Union:
if (!IsHotEdge(*edge_c)) return nullptr;
if (!IsHotEdge(*edge_c)) return;
break;
default:
if (edge_c->local_min->polytype == PathType::Subject)
return nullptr;
return;
}

switch (fillrule_)
{
case FillRule::Positive: if (edge_c->wind_cnt != 1) return nullptr; break;
case FillRule::Negative: if (edge_c->wind_cnt != -1) return nullptr; break;
default: if (std::abs(edge_c->wind_cnt) != 1) return nullptr; break;
case FillRule::Positive:
if (edge_c->wind_cnt != 1) return;
break;
case FillRule::Negative:
if (edge_c->wind_cnt != -1) return;
break;
default:
if (std::abs(edge_c->wind_cnt) != 1) return;
}

OutPt* resultOp;
Expand All @@ -1843,7 +1848,7 @@ namespace Clipper2Lib {
SetSides(*e3->outrec, *edge_o, *e3);
else
SetSides(*e3->outrec, *e3, *edge_o);
return e3->outrec->pts;
return;
}
else
resultOp = StartOpenPath(*edge_o, pt);
Expand All @@ -1854,7 +1859,7 @@ namespace Clipper2Lib {
#ifdef USINGZ
if (zCallback_) SetZ(*edge_o, *edge_c, resultOp->pt);
#endif
return resultOp;
return;
} // end of an open path intersection

//MANAGING CLOSED PATHS FROM HERE ON
Expand Down Expand Up @@ -1923,10 +1928,9 @@ namespace Clipper2Lib {
const bool e1_windcnt_in_01 = old_e1_windcnt == 0 || old_e1_windcnt == 1;
const bool e2_windcnt_in_01 = old_e2_windcnt == 0 || old_e2_windcnt == 1;

if ((!IsHotEdge(e1) && !e1_windcnt_in_01) || (!IsHotEdge(e2) && !e2_windcnt_in_01))
{
return nullptr;
}
if ((!IsHotEdge(e1) && !e1_windcnt_in_01) ||
(!IsHotEdge(e2) && !e2_windcnt_in_01))
return;

//NOW PROCESS THE INTERSECTION ...
OutPt* resultOp = nullptr;
Expand Down Expand Up @@ -2048,7 +2052,6 @@ namespace Clipper2Lib {
#endif
}
}
return resultOp;
}

inline void ClipperBase::DeleteFromAEL(Active& e)
Expand Down
13 changes: 8 additions & 5 deletions CPP/Clipper2Lib/src/clipper.offset.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 24 March 2024 *
* Date : 17 April 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -315,15 +315,18 @@ void ClipperOffset::OffsetPoint(Group& group, const Path64& path, size_t j, size

if (cos_a > -0.999 && (sin_a * group_delta_ < 0)) // test for concavity first (#593)
{
// is concave
// is concave (so insert 3 points that will create a negative region)
#ifdef USINGZ
path_out.push_back(Point64(GetPerpendic(path[j], norms[k], group_delta_), path[j].z));
#else
path_out.push_back(GetPerpendic(path[j], norms[k], group_delta_));
#endif
// this extra point is the only (simple) way to ensure that
// path reversals are fully cleaned with the trailing clipper
path_out.push_back(path[j]); // (#405)

// this extra point is the only simple way to ensure that path reversals
// (ie over-shrunk paths) are fully cleaned out with the trailing union op.
// However it's probably safe to skip this whenever an angle is almost flat.
if (cos_a < 0.99) path_out.push_back(path[j]); // (#405)

#ifdef USINGZ
path_out.push_back(Point64(GetPerpendic(path[j], norms[j], group_delta_), path[j].z));
#else
Expand Down
36 changes: 18 additions & 18 deletions CSharp/Clipper2Lib/Clipper.Engine.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 28 February 2024 *
* Date : 17 April 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : This is the main polygon clipping module *
Expand Down Expand Up @@ -1548,33 +1548,34 @@ private void UpdateEdgeIntoAEL(Active ae)
return result;
}

private OutPt? IntersectEdges(Active ae1, Active ae2, Point64 pt)
private void IntersectEdges(Active ae1, Active ae2, Point64 pt)
{
OutPt? resultOp = null;

// MANAGE OPEN PATH INTERSECTIONS SEPARATELY ...
if (_hasOpenPaths && (IsOpen(ae1) || IsOpen(ae2)))
{
if (IsOpen(ae1) && IsOpen(ae2)) return null;
if (IsOpen(ae1) && IsOpen(ae2)) return;
// the following line avoids duplicating quite a bit of code
if (IsOpen(ae2)) SwapActives(ref ae1, ref ae2);
if (IsJoined(ae2)) Split(ae2, pt); // needed for safety

if (_cliptype == ClipType.Union)
{
if (!IsHotEdge(ae2)) return null;
if (!IsHotEdge(ae2)) return;
}
else if (ae2.localMin.polytype == PathType.Subject)
return null;
else if (ae2.localMin.polytype == PathType.Subject) return;

switch (_fillrule)
{
case FillRule.Positive:
if (ae2.windCount != 1) return null; break;
if (ae2.windCount != 1) return;
break;
case FillRule.Negative:
if (ae2.windCount != -1) return null; break;
if (ae2.windCount != -1) return;
break;
default:
if (Math.Abs(ae2.windCount) != 1) return null; break;
if (Math.Abs(ae2.windCount) != 1) return;
break;
}

// toggle contribution ...
Expand Down Expand Up @@ -1605,7 +1606,7 @@ private void UpdateEdgeIntoAEL(Active ae)
SetSides(ae3.outrec!, ae1, ae3);
else
SetSides(ae3.outrec!, ae3, ae1);
return ae3.outrec!.pts;
return;
}

resultOp = StartOpenPath(ae1, pt);
Expand All @@ -1616,7 +1617,7 @@ private void UpdateEdgeIntoAEL(Active ae)
#if USINGZ
SetZ(ae1, ae2, ref resultOp.pt);
#endif
return resultOp;
return;
}

// MANAGING CLOSED PATHS FROM HERE ON
Expand Down Expand Up @@ -1677,7 +1678,8 @@ private void UpdateEdgeIntoAEL(Active ae)
bool e1WindCountIs0or1 = oldE1WindCount == 0 || oldE1WindCount == 1;
bool e2WindCountIs0or1 = oldE2WindCount == 0 || oldE2WindCount == 1;

if ((!IsHotEdge(ae1) && !e1WindCountIs0or1) || (!IsHotEdge(ae2) && !e2WindCountIs0or1)) return null;
if ((!IsHotEdge(ae1) && !e1WindCountIs0or1) ||
(!IsHotEdge(ae2) && !e2WindCountIs0or1)) return;

// NOW PROCESS THE INTERSECTION ...

Expand Down Expand Up @@ -1770,11 +1772,11 @@ private void UpdateEdgeIntoAEL(Active ae)
}
else if (oldE1WindCount == 1 && oldE2WindCount == 1)
{
resultOp = null;
resultOp = null;
switch (_cliptype)
{
case ClipType.Union:
if (e1Wc2 > 0 && e2Wc2 > 0) return null;
if (e1Wc2 > 0 && e2Wc2 > 0) return;
resultOp = AddLocalMinPoly(ae1, ae2, pt);
break;

Expand All @@ -1792,7 +1794,7 @@ private void UpdateEdgeIntoAEL(Active ae)
break;

default: // ClipType.Intersection:
if (e1Wc2 <= 0 || e2Wc2 <= 0) return null;
if (e1Wc2 <= 0 || e2Wc2 <= 0) return;
resultOp = AddLocalMinPoly(ae1, ae2, pt);
break;
}
Expand All @@ -1801,8 +1803,6 @@ private void UpdateEdgeIntoAEL(Active ae)
#endif
}
}

return resultOp;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
9 changes: 5 additions & 4 deletions CSharp/Clipper2Lib/Clipper.Offset.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 24 March 2024 *
* Date : 17 April 2024 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -549,9 +549,10 @@ private void OffsetPoint(Group group, Path64 path, int j, ref int k)
{
// is concave
pathOut.Add(GetPerpendic(path[j], _normals[k]));
// this extra point is the only (simple) way to ensure that
// path reversals are fully cleaned with the trailing clipper
pathOut.Add(path[j]); // (#405)
// this extra point is the only simple way to ensure that path reversals
// (ie over-shrunk paths) are fully cleaned out with the trailing union op.
// However it's probably safe to skip this whenever an angle is almost flat.
if (cosA < 0.99) pathOut.Add(path[j]); // (#405)
pathOut.Add(GetPerpendic(path[j], _normals[j]));
}
else if ((cosA > 0.999) && (_joinType != JoinType.Round))
Expand Down
Loading

0 comments on commit 7714d94

Please sign in to comment.