2
2
3
3
(* ******************************************************************************
4
4
* Author : Angus Johnson *
5
- * Date : 14 February 2024 *
5
+ * Date : 3 May 2024 *
6
6
* Website : http://www.angusj.com *
7
7
* Copyright : Angus Johnson 2010-2024 *
8
8
* Purpose : Core Clipper Library module *
@@ -154,7 +154,8 @@ function IsPositive(const path: TPath64): Boolean; overload;
154
154
function IsPositive (const path: TPathD): Boolean; overload;
155
155
{ $IFDEF INLINING} inline; { $ENDIF}
156
156
157
- function __Trunc (val: double): Int64; { $IFDEF INLINE} inline; { $ENDIF}
157
+ function IsCollinear (const pt1, pt2, pt3: TPoint64): Boolean;
158
+ { $IFDEF INLINING} inline; { $ENDIF}
158
159
159
160
function CrossProduct (const pt1, pt2, pt3: TPoint64): double; overload;
160
161
{ $IFDEF INLINING} inline; { $ENDIF}
@@ -829,6 +830,9 @@ function ScalePath(const path: TPath64; sx, sy: double): TPath64;
829
830
begin
830
831
result[i].X := Round(path[i].X * sx);
831
832
result[i].Y := Round(path[i].Y * sy);
833
+ { $IFDEF USINGZ}
834
+ result[i].Z := path[i].Z;
835
+ { $ENDIF}
832
836
end ;
833
837
end ;
834
838
// ------------------------------------------------------------------------------
@@ -845,10 +849,16 @@ function ScalePath(const path: TPathD; sx, sy: double): TPath64;
845
849
j := 1 ;
846
850
result[0 ].X := Round(path[0 ].X * sx);
847
851
result[0 ].Y := Round(path[0 ].Y * sy);
852
+ { $IFDEF USINGZ}
853
+ result[0 ].Z := path[0 ].Z;
854
+ { $ENDIF}
848
855
for i := 1 to len -1 do
849
856
begin
850
857
result[j].X := Round(path[i].X * sx);
851
858
result[j].Y := Round(path[i].Y * sy);
859
+ { $IFDEF USINGZ}
860
+ result[j].Z := path[i].Z;
861
+ { $ENDIF}
852
862
if (result[j].X <> result[j-1 ].X) or
853
863
(result[j].Y <> result[j-1 ].Y) then inc(j);
854
864
end ;
@@ -866,10 +876,16 @@ function ScalePath(const path: TPath64; scale: double): TPath64;
866
876
j := 1 ;
867
877
result[0 ].X := Round(path[0 ].X * scale);
868
878
result[0 ].Y := Round(path[0 ].Y * scale);
879
+ { $IFDEF USINGZ}
880
+ result[0 ].Z := path[0 ].Z;
881
+ { $ENDIF}
869
882
for i := 1 to len -1 do
870
883
begin
871
884
result[j].X := Round(path[i].X * scale);
872
885
result[j].Y := Round(path[i].Y * scale);
886
+ { $IFDEF USINGZ}
887
+ result[j].Z := path[i].Z;
888
+ { $ENDIF}
873
889
if (result[j].X <> result[j-1 ].X) or
874
890
(result[j].Y <> result[j-1 ].Y) then inc(j);
875
891
end ;
@@ -887,6 +903,9 @@ function ScalePath(const path: TPathD; scale: double): TPath64;
887
903
begin
888
904
result[i].X := Round(path[i].X * scale);
889
905
result[i].Y := Round(path[i].Y * scale);
906
+ { $IFDEF USINGZ}
907
+ result[i].Z := path[i].Z;
908
+ { $ENDIF}
890
909
end ;
891
910
end ;
892
911
// ------------------------------------------------------------------------------
@@ -926,6 +945,9 @@ function ScalePathD(const path: TPath64; sx, sy: double): TPathD;
926
945
begin
927
946
result[i].X := path[i].X * sx;
928
947
result[i].Y := path[i].Y * sy;
948
+ { $IFDEF USINGZ}
949
+ result[i].Z := path[i].Z;
950
+ { $ENDIF}
929
951
end ;
930
952
end ;
931
953
// ------------------------------------------------------------------------------
@@ -939,6 +961,9 @@ function ScalePathD(const path: TPathD; sx, sy: double): TPathD;
939
961
begin
940
962
result[i].X := path[i].X * sx;
941
963
result[i].Y := path[i].Y * sy;
964
+ { $IFDEF USINGZ}
965
+ result[i].Z := path[i].Z;
966
+ { $ENDIF}
942
967
end ;
943
968
end ;
944
969
// ------------------------------------------------------------------------------
@@ -989,6 +1014,9 @@ function ScalePathsD(const paths: TPaths64; sx, sy: double): TPathsD;
989
1014
begin
990
1015
result[i][j].X := (paths[i][j].X * sx);
991
1016
result[i][j].Y := (paths[i][j].Y * sy);
1017
+ { $IFDEF USINGZ}
1018
+ result[i][j].Z := paths[i][j].Z;
1019
+ { $ENDIF}
992
1020
end ;
993
1021
end ;
994
1022
end ;
@@ -1008,6 +1036,9 @@ function ScalePathsD(const paths: TPathsD; sx, sy: double): TPathsD;
1008
1036
begin
1009
1037
result[i][j].X := paths[i][j].X * sx;
1010
1038
result[i][j].Y := paths[i][j].Y * sy;
1039
+ { $IFDEF USINGZ}
1040
+ result[i][j].Z := paths[i][j].Z;
1041
+ { $ENDIF}
1011
1042
end ;
1012
1043
end ;
1013
1044
end ;
@@ -1103,6 +1134,9 @@ function Path64(const pathD: TPathD): TPath64;
1103
1134
begin
1104
1135
Result[i].X := Round(pathD[i].X);
1105
1136
Result[i].Y := Round(pathD[i].Y);
1137
+ { $IFDEF USINGZ}
1138
+ Result[i].Z := pathD[i].Z;
1139
+ { $ENDIF}
1106
1140
end ;
1107
1141
end ;
1108
1142
// ------------------------------------------------------------------------------
@@ -1117,6 +1151,9 @@ function PathD(const path: TPath64): TPathD;
1117
1151
begin
1118
1152
Result[i].X := path[i].X;
1119
1153
Result[i].Y := path[i].Y;
1154
+ { $IFDEF USINGZ}
1155
+ Result[i].Z := path[i].Z;
1156
+ { $ENDIF}
1120
1157
end ;
1121
1158
end ;
1122
1159
// ------------------------------------------------------------------------------
@@ -1827,6 +1864,18 @@ function IsPositive(const path: TPathD): Boolean;
1827
1864
end ;
1828
1865
// ------------------------------------------------------------------------------
1829
1866
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
+
1830
1879
function CrossProduct (const pt1, pt2, pt3: TPoint64): double;
1831
1880
begin
1832
1881
result := CrossProduct(
@@ -1925,14 +1974,14 @@ function CleanPath(const path: TPath64): TPath64;
1925
1974
Result := nil ;
1926
1975
len := Length(path);
1927
1976
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);
1929
1978
SetLength(Result, len);
1930
1979
if (len < 2 ) then Exit;
1931
1980
prev := path[len -1 ];
1932
1981
j := 0 ;
1933
1982
for i := 0 to len -2 do
1934
1983
begin
1935
- if CrossProduct (prev, path[i], path[i+1 ]) = 0 then Continue;
1984
+ if IsCollinear (prev, path[i], path[i+1 ]) then Continue;
1936
1985
Result[j] := path[i];
1937
1986
inc(j);
1938
1987
prev := path[i];
@@ -1942,6 +1991,14 @@ function CleanPath(const path: TPath64): TPath64;
1942
1991
end ;
1943
1992
// ------------------------------------------------------------------------------
1944
1993
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
+
1945
2002
function SegmentsIntersect (const s1a, s1b, s2a, s2b: TPoint64;
1946
2003
inclusive: Boolean): boolean;
1947
2004
var
@@ -1961,38 +2018,14 @@ function SegmentsIntersect(const s1a, s1b, s2a, s2b: TPoint64;
1961
2018
(res3 <> 0 ) or (res4 <> 0 ); // ensures not collinear
1962
2019
end else
1963
2020
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 );
1966
2025
end ;
1967
2026
end ;
1968
2027
// ------------------------------------------------------------------------------
1969
2028
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
-
1996
2029
function GetSegmentIntersectPt (const ln1a, ln1b, ln2a, ln2b: TPoint64;
1997
2030
out ip: TPoint64): Boolean;
1998
2031
var
@@ -2011,6 +2044,9 @@ function GetSegmentIntersectPt(const ln1a, ln1b, ln2a, ln2b: TPoint64;
2011
2044
else if t >= 1.0 then ip := ln1b;
2012
2045
ip.X := Trunc(ln1a.X + t * dx1);
2013
2046
ip.Y := Trunc(ln1a.Y + t * dy1);
2047
+ { $IFDEF USINGZ}
2048
+ ip.Z := 0 ;
2049
+ { $ENDIF}
2014
2050
end ;
2015
2051
// ------------------------------------------------------------------------------
2016
2052
0 commit comments