Skip to content

Commit c5fc0b0

Browse files
committed
Clipper.Core -
* fixed a (Delphi only) bug in CrossProductSign function. * fixed a buggy (but currently unused) SegmentsIntersect function.
1 parent 0846cb8 commit c5fc0b0

File tree

3 files changed

+116
-43
lines changed

3 files changed

+116
-43
lines changed

CPP/Clipper2Lib/include/clipper2/clipper.core.h

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*******************************************************************************
22
* Author : Angus Johnson *
3-
* Date : 7 October 2025 *
3+
* Date : 11 October 2025 *
44
* Website : https://www.angusj.com *
55
* Copyright : Angus Johnson 2010-2025 *
66
* Purpose : Core Clipper Library structures and functions *
@@ -995,21 +995,44 @@ namespace Clipper2Lib
995995
inline bool SegmentsIntersect(const Point64& seg1a, const Point64& seg1b,
996996
const Point64& seg2a, const Point64& seg2b, bool inclusive = false)
997997
{
998+
double dy1 = static_cast<double>(seg1b.y - seg1a.y);
999+
double dx1 = static_cast<double>(seg1b.x - seg1a.x);
1000+
double dy2 = static_cast<double>(seg2b.y - seg2a.y);
1001+
double dx2 = static_cast<double>(seg2b.x - seg2a.x);
1002+
double cp = dy1 * dx2 - dy2 * dx1;
1003+
if (cp == 0) return false; // ie parallel segments
1004+
9981005
if (inclusive)
9991006
{
1000-
int res1 = CrossProductSign(seg1a, seg2a, seg2b);
1001-
int res2 = CrossProductSign(seg1b, seg2a, seg2b);
1002-
if (res1 * res2 > 0) return false;
1003-
int res3 = CrossProductSign(seg2a, seg1a, seg1b);
1004-
int res4 = CrossProductSign(seg2b, seg1a, seg1b);
1005-
if (res3 * res4 > 0) return false;
1006-
return (res1 || res2 || res3 || res4); // ensures not collinear
1007+
//result **includes** segments that touch at an end point
1008+
double t = ((seg1a.x - seg2a.x) * dy2 - (seg1a.y - seg2a.y) * dx2);
1009+
if (t == 0) return true;
1010+
if (t > 0)
1011+
{
1012+
if (cp < 0 || t > cp) return false;
1013+
}
1014+
else if (cp > 0 || t < cp) return false; // false when t more neg. than cp
1015+
1016+
t = ((seg1a.x - seg2a.x) * dy1 - (seg1a.y - seg2a.y) * dx1);
1017+
if (t == 0) return true;
1018+
if (t > 0) return (cp > 0 && t <= cp);
1019+
else return (cp < 0 && t >= cp); // true when t less neg. than cp
10071020
}
1008-
else {
1009-
return (CrossProductSign(seg1a, seg2a, seg2b) *
1010-
CrossProductSign(seg1b, seg2a, seg2b) < 0) &&
1011-
(CrossProductSign(seg2a, seg1a, seg1b) *
1012-
CrossProductSign(seg2b, seg1a, seg1b) < 0);
1021+
else
1022+
{
1023+
//result **excludes** segments that touch at an end point
1024+
double t = ((seg1a.x - seg2a.x) * dy2 - (seg1a.y - seg2a.y) * dx2);
1025+
if (t == 0) return false;
1026+
if (t > 0)
1027+
{
1028+
if (cp < 0 || t >= cp) return false;
1029+
}
1030+
else if (cp > 0 || t <= cp ) return false; // false when t more neg. than cp
1031+
1032+
t = ((seg1a.x - seg2a.x) * dy1 - (seg1a.y - seg2a.y) * dx1);
1033+
if (t == 0) return false;
1034+
if (t > 0) return (cp > 0 && t < cp);
1035+
else return (cp < 0 && t > cp); // true when t less neg. than cp
10131036
}
10141037
}
10151038

CSharp/Clipper2Lib/Clipper.Core.cs

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*******************************************************************************
22
* Author : Angus Johnson *
3-
* Date : 7 October 2025 *
3+
* Date : 11 October 2025 *
44
* Website : https://www.angusj.com *
55
* Copyright : Angus Johnson 2010-2025 *
66
* Purpose : Core structures and functions for the Clipper Library *
@@ -702,19 +702,45 @@ public static bool GetSegmentIntersectPt(Point64 ln1a,
702702
internal static bool SegsIntersect(Point64 seg1a,
703703
Point64 seg1b, Point64 seg2a, Point64 seg2b, bool inclusive = false)
704704
{
705-
if (!inclusive)
706-
return (CrossProductSign(seg1a, seg2a, seg2b) *
707-
CrossProductSign(seg1b, seg2a, seg2b) < 0) &&
708-
(CrossProductSign(seg2a, seg1a, seg1b) *
709-
CrossProductSign(seg2b, seg1a, seg1b) < 0);
710-
int res1 = CrossProductSign(seg1a, seg2a, seg2b);
711-
int res2 = CrossProductSign(seg1b, seg2a, seg2b);
712-
if (res1 * res2 > 0) return false;
713-
int res3 = CrossProductSign(seg2a, seg1a, seg1b);
714-
int res4 = CrossProductSign(seg2b, seg1a, seg1b);
715-
if (res3 * res4 > 0) return false;
716-
// ensure NOT collinear
717-
return (res1 != 0 || res2 != 0 || res3 != 0 || res4 != 0);
705+
double dy1 = (seg1b.Y - seg1a.Y);
706+
double dx1 = (seg1b.X - seg1a.X);
707+
double dy2 = (seg2b.Y - seg2a.Y);
708+
double dx2 = (seg2b.X - seg2a.X);
709+
double cp = dy1 * dx2 - dy2 * dx1;
710+
if (cp == 0) return false; // ie parallel segments
711+
712+
if (inclusive)
713+
{
714+
//result **includes** segments that touch at an end point
715+
double t = ((seg1a.X - seg2a.X) * dy2 - (seg1a.Y - seg2a.Y) * dx2);
716+
if (t == 0) return true;
717+
if (t > 0)
718+
{
719+
if (cp < 0 || t > cp) return false;
720+
}
721+
else if (cp > 0 || t < cp) return false; // false when t more neg. than cp
722+
723+
t = ((seg1a.X - seg2a.X) * dy1 - (seg1a.Y - seg2a.Y) * dx1);
724+
if (t == 0) return true;
725+
if (t > 0) return (cp > 0 && t <= cp);
726+
else return (cp < 0 && t >= cp); // true when t less neg. than cp
727+
}
728+
else
729+
{
730+
//result **excludes** segments that touch at an end point
731+
double t = ((seg1a.X - seg2a.X) * dy2 - (seg1a.Y - seg2a.Y) * dx2);
732+
if (t == 0) return false;
733+
if (t > 0)
734+
{
735+
if (cp < 0 || t >= cp) return false;
736+
}
737+
else if (cp > 0 || t <= cp) return false; // false when t more neg. than cp
738+
739+
t = ((seg1a.X - seg2a.X) * dy1 - (seg1a.Y - seg2a.Y) * dx1);
740+
if (t == 0) return false;
741+
if (t > 0) return (cp > 0 && t < cp);
742+
else return (cp < 0 && t > cp); // true when t less neg. than cp
743+
}
718744
}
719745

720746
public static Rect64 GetBounds(Path64 path)

Delphi/Clipper2Lib/Clipper.Core.pas

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,7 +2110,7 @@ function CrossProductSign(const pt1, pt2, pt3: TPoint64): integer;
21102110
end;
21112111
if (ab.lo64 > cd.lo64) then Result := 1
21122112
else Result := -1;
2113-
if (signAB > 0) then Result := -Result;
2113+
if (signAB < 0) then Result := -Result;
21142114
end
21152115
else if (ab.hi64 > cd.hi64) then Result := 1
21162116
else Result := -1;
@@ -2212,24 +2212,48 @@ function GetSign(const val: double): integer; {$IFDEF INLINING} inline; {$ENDIF}
22122212
function SegmentsIntersect(const s1a, s1b, s2a, s2b: TPoint64;
22132213
inclusive: Boolean): boolean;
22142214
var
2215-
res1, res2, res3, res4: integer;
2215+
dx1,dy1, dx2,dy2, t, cp: double;
22162216
begin
2217-
if inclusive then
2217+
dy1 := (s1b.y - s1a.y);
2218+
dx1 := (s1b.x - s1a.x);
2219+
dy2 := (s2b.y - s2a.y);
2220+
dx2 := (s2b.x - s2a.x);
2221+
cp := dy1 * dx2 - dy2 * dx1;
2222+
if cp = 0 then
2223+
Result := false
2224+
else if inclusive then
22182225
begin
2219-
//result can include segments that only touch
2220-
Result := false;
2221-
res1 := CrossProductSign(s1a, s2a, s2b);
2222-
res2 := CrossProductSign(s1b, s2a, s2b);
2223-
if (res1 * res2 > 0) then Exit;
2224-
res3 := CrossProductSign(s2a, s1a, s1b);
2225-
res4 := CrossProductSign(s2b, s1a, s1b);
2226-
if (res3 * res4 > 0) then Exit;
2227-
Result := (res1 <> 0) or (res2 <> 0) or
2228-
(res3 <> 0) or (res4 <> 0); // ensures not collinear
2226+
//result **includes** segments that touch at an end point
2227+
t := ((s1a.x-s2a.x) * dy2 - (s1a.y-s2a.y) * dx2);
2228+
if (t = 0) then Result := true
2229+
else if (t > 0) then
2230+
Result := (cp > 0) and (t <= cp)
2231+
else
2232+
Result := (cp < 0) and (t >= cp);
2233+
if not Result then Exit;
2234+
t := ((s1a.x-s2a.x) * dy1 - (s1a.y-s2a.y) * dx1);
2235+
if (t = 0) then Result := true
2236+
else if (t > 0) then
2237+
Result := (cp > 0) and (t <= cp)
2238+
else
2239+
Result := (cp < 0) and (t >= cp);
22292240
end else
2230-
result :=
2231-
((CrossProductSign(s1a, s2a, s2b) * CrossProductSign(s1b, s2a, s2b)) < 0) and
2232-
((CrossProductSign(s2a, s1a, s1b) * CrossProductSign(s2b, s1a, s1b)) < 0);
2241+
begin
2242+
//result **excludes** segments that touch at an end point
2243+
t := ((s1a.x-s2a.x) * dy2 - (s1a.y-s2a.y) * dx2);
2244+
if (t = 0) then Result := false
2245+
else if (t > 0) then
2246+
Result := (cp > 0) and (t < cp)
2247+
else
2248+
Result := (cp < 0) and (t > cp);
2249+
if not Result then Exit;
2250+
t := ((s1a.x-s2a.x) * dy1 - (s1a.y-s2a.y) * dx1) / cp;
2251+
if (t = 0) then Result := false
2252+
else if (t > 0) then
2253+
Result := (cp > 0) and (t < cp)
2254+
else
2255+
Result := (cp < 0) and (t > cp);
2256+
end;
22332257
end;
22342258
//------------------------------------------------------------------------------
22352259

0 commit comments

Comments
 (0)