22
33(* ******************************************************************************
44* Author : Angus Johnson *
5- * Date : 14 February 2024 *
5+ * Date : 3 May 2024 *
66* Website : http://www.angusj.com *
77* Copyright : Angus Johnson 2010-2024 *
88* Purpose : Core Clipper Library module *
@@ -154,7 +154,8 @@ function IsPositive(const path: TPath64): Boolean; overload;
154154function IsPositive (const path: TPathD): Boolean; overload;
155155 { $IFDEF INLINING} inline; { $ENDIF}
156156
157- function __Trunc (val: double): Int64; { $IFDEF INLINE} inline; { $ENDIF}
157+ function IsCollinear (const pt1, pt2, pt3: TPoint64): Boolean;
158+ { $IFDEF INLINING} inline; { $ENDIF}
158159
159160function CrossProduct (const pt1, pt2, pt3: TPoint64): double; overload;
160161 { $IFDEF INLINING} inline; { $ENDIF}
@@ -829,6 +830,9 @@ function ScalePath(const path: TPath64; sx, sy: double): TPath64;
829830 begin
830831 result[i].X := Round(path[i].X * sx);
831832 result[i].Y := Round(path[i].Y * sy);
833+ { $IFDEF USINGZ}
834+ result[i].Z := path[i].Z;
835+ { $ENDIF}
832836 end ;
833837end ;
834838// ------------------------------------------------------------------------------
@@ -845,10 +849,16 @@ function ScalePath(const path: TPathD; sx, sy: double): TPath64;
845849 j := 1 ;
846850 result[0 ].X := Round(path[0 ].X * sx);
847851 result[0 ].Y := Round(path[0 ].Y * sy);
852+ { $IFDEF USINGZ}
853+ result[0 ].Z := path[0 ].Z;
854+ { $ENDIF}
848855 for i := 1 to len -1 do
849856 begin
850857 result[j].X := Round(path[i].X * sx);
851858 result[j].Y := Round(path[i].Y * sy);
859+ { $IFDEF USINGZ}
860+ result[j].Z := path[i].Z;
861+ { $ENDIF}
852862 if (result[j].X <> result[j-1 ].X) or
853863 (result[j].Y <> result[j-1 ].Y) then inc(j);
854864 end ;
@@ -866,10 +876,16 @@ function ScalePath(const path: TPath64; scale: double): TPath64;
866876 j := 1 ;
867877 result[0 ].X := Round(path[0 ].X * scale);
868878 result[0 ].Y := Round(path[0 ].Y * scale);
879+ { $IFDEF USINGZ}
880+ result[0 ].Z := path[0 ].Z;
881+ { $ENDIF}
869882 for i := 1 to len -1 do
870883 begin
871884 result[j].X := Round(path[i].X * scale);
872885 result[j].Y := Round(path[i].Y * scale);
886+ { $IFDEF USINGZ}
887+ result[j].Z := path[i].Z;
888+ { $ENDIF}
873889 if (result[j].X <> result[j-1 ].X) or
874890 (result[j].Y <> result[j-1 ].Y) then inc(j);
875891 end ;
@@ -887,6 +903,9 @@ function ScalePath(const path: TPathD; scale: double): TPath64;
887903 begin
888904 result[i].X := Round(path[i].X * scale);
889905 result[i].Y := Round(path[i].Y * scale);
906+ { $IFDEF USINGZ}
907+ result[i].Z := path[i].Z;
908+ { $ENDIF}
890909 end ;
891910end ;
892911// ------------------------------------------------------------------------------
@@ -926,6 +945,9 @@ function ScalePathD(const path: TPath64; sx, sy: double): TPathD;
926945 begin
927946 result[i].X := path[i].X * sx;
928947 result[i].Y := path[i].Y * sy;
948+ { $IFDEF USINGZ}
949+ result[i].Z := path[i].Z;
950+ { $ENDIF}
929951 end ;
930952end ;
931953// ------------------------------------------------------------------------------
@@ -939,6 +961,9 @@ function ScalePathD(const path: TPathD; sx, sy: double): TPathD;
939961 begin
940962 result[i].X := path[i].X * sx;
941963 result[i].Y := path[i].Y * sy;
964+ { $IFDEF USINGZ}
965+ result[i].Z := path[i].Z;
966+ { $ENDIF}
942967 end ;
943968end ;
944969// ------------------------------------------------------------------------------
@@ -989,6 +1014,9 @@ function ScalePathsD(const paths: TPaths64; sx, sy: double): TPathsD;
9891014 begin
9901015 result[i][j].X := (paths[i][j].X * sx);
9911016 result[i][j].Y := (paths[i][j].Y * sy);
1017+ { $IFDEF USINGZ}
1018+ result[i][j].Z := paths[i][j].Z;
1019+ { $ENDIF}
9921020 end ;
9931021 end ;
9941022end ;
@@ -1008,6 +1036,9 @@ function ScalePathsD(const paths: TPathsD; sx, sy: double): TPathsD;
10081036 begin
10091037 result[i][j].X := paths[i][j].X * sx;
10101038 result[i][j].Y := paths[i][j].Y * sy;
1039+ { $IFDEF USINGZ}
1040+ result[i][j].Z := paths[i][j].Z;
1041+ { $ENDIF}
10111042 end ;
10121043 end ;
10131044end ;
@@ -1103,6 +1134,9 @@ function Path64(const pathD: TPathD): TPath64;
11031134 begin
11041135 Result[i].X := Round(pathD[i].X);
11051136 Result[i].Y := Round(pathD[i].Y);
1137+ { $IFDEF USINGZ}
1138+ Result[i].Z := pathD[i].Z;
1139+ { $ENDIF}
11061140 end ;
11071141end ;
11081142// ------------------------------------------------------------------------------
@@ -1117,6 +1151,9 @@ function PathD(const path: TPath64): TPathD;
11171151 begin
11181152 Result[i].X := path[i].X;
11191153 Result[i].Y := path[i].Y;
1154+ { $IFDEF USINGZ}
1155+ Result[i].Z := path[i].Z;
1156+ { $ENDIF}
11201157 end ;
11211158end ;
11221159// ------------------------------------------------------------------------------
@@ -1827,6 +1864,18 @@ function IsPositive(const path: TPathD): Boolean;
18271864end ;
18281865// ------------------------------------------------------------------------------
18291866
1867+ { $OVERFLOWCHECKS OFF}
1868+ function IsCollinear (const pt1, pt2, pt3: TPoint64): Boolean;
1869+ var
1870+ a,b: Int64;
1871+ begin
1872+ a := (pt2.X - pt1.X) * (pt3.Y - pt2.Y);
1873+ b := (pt2.Y - pt1.Y) * (pt3.X - pt2.X);
1874+ result := a = b;
1875+ end ;
1876+ { $OVERFLOWCHECKS ON}
1877+ // ------------------------------------------------------------------------------
1878+
18301879function CrossProduct (const pt1, pt2, pt3: TPoint64): double;
18311880begin
18321881 result := CrossProduct(
@@ -1925,14 +1974,14 @@ function CleanPath(const path: TPath64): TPath64;
19251974 Result := nil ;
19261975 len := Length(path);
19271976 while (len > 2 ) and
1928- (CrossProduct (path[len-2 ], path[len-1 ], path[0 ]) = 0 ) do dec(len);
1977+ (IsCollinear (path[len-2 ], path[len-1 ], path[0 ])) do dec(len);
19291978 SetLength(Result, len);
19301979 if (len < 2 ) then Exit;
19311980 prev := path[len -1 ];
19321981 j := 0 ;
19331982 for i := 0 to len -2 do
19341983 begin
1935- if CrossProduct (prev, path[i], path[i+1 ]) = 0 then Continue;
1984+ if IsCollinear (prev, path[i], path[i+1 ]) then Continue;
19361985 Result[j] := path[i];
19371986 inc(j);
19381987 prev := path[i];
@@ -1942,6 +1991,14 @@ function CleanPath(const path: TPath64): TPath64;
19421991end ;
19431992// ------------------------------------------------------------------------------
19441993
1994+ function GetSign (const val: double): integer; { $IFDEF INLINING} inline; { $ENDIF}
1995+ begin
1996+ if val = 0 then Result := 0
1997+ else if val < 0 then Result := -1
1998+ else Result := 1 ;
1999+ end ;
2000+ // ------------------------------------------------------------------------------
2001+
19452002function SegmentsIntersect (const s1a, s1b, s2a, s2b: TPoint64;
19462003 inclusive: Boolean): boolean;
19472004var
@@ -1961,38 +2018,14 @@ function SegmentsIntersect(const s1a, s1b, s2a, s2b: TPoint64;
19612018 (res3 <> 0 ) or (res4 <> 0 ); // ensures not collinear
19622019 end else
19632020 begin
1964- result := (CrossProduct(s1a, s2a, s2b) * CrossProduct(s1b, s2a, s2b) < 0 ) and
1965- (CrossProduct(s2a, s1a, s1b) * CrossProduct(s2b, s1a, s1b) < 0 );
2021+ result := (GetSign(CrossProduct(s1a, s2a, s2b)) *
2022+ GetSign(CrossProduct(s1b, s2a, s2b)) < 0 ) and
2023+ (GetSign(CrossProduct(s2a, s1a, s1b)) *
2024+ GetSign(CrossProduct(s2b, s1a, s1b)) < 0 );
19662025 end ;
19672026end ;
19682027// ------------------------------------------------------------------------------
19692028
1970- function __Trunc (val: double): Int64; { $IFDEF INLINE} inline; { $ENDIF}
1971- var
1972- exp: integer;
1973- i64: UInt64 absolute val;
1974- const
1975- shl51: UInt64 = UInt64(1 ) shl 51 ;
1976- begin
1977- Result := 0 ;
1978- if i64 = 0 then Exit;
1979- exp := Integer(Cardinal(i64 shr 52 ) and $7FF) - 1023 ;
1980- // nb: when exp == 1024 then val == INF or NAN.
1981- if exp < 0 then
1982- Exit
1983- else if exp > 52 then
1984- begin
1985- Result := ((i64 and $1FFFFFFFFFFFFF) shl (exp - 52 )) or (UInt64(1 ) shl exp)
1986- end else
1987- begin
1988- Result := ((i64 and $1FFFFFFFFFFFFF) shr (52 - exp)) or (UInt64(1 ) shl exp);
1989- // the following line will round
1990- // if (i64 and (shl51 shr (exp)) <> 0) then inc(Result);
1991- end ;
1992- if val < 0 then Result := -Result;
1993- end ;
1994- // ------------------------------------------------------------------------------
1995-
19962029function GetSegmentIntersectPt (const ln1a, ln1b, ln2a, ln2b: TPoint64;
19972030 out ip: TPoint64): Boolean;
19982031var
@@ -2011,6 +2044,9 @@ function GetSegmentIntersectPt(const ln1a, ln1b, ln2a, ln2b: TPoint64;
20112044 else if t >= 1.0 then ip := ln1b;
20122045 ip.X := Trunc(ln1a.X + t * dx1);
20132046 ip.Y := Trunc(ln1a.Y + t * dy1);
2047+ { $IFDEF USINGZ}
2048+ ip.Z := 0 ;
2049+ { $ENDIF}
20142050end ;
20152051// ------------------------------------------------------------------------------
20162052
0 commit comments