Skip to content

Commit 2ada13f

Browse files
committed
fixup rectclip
1 parent a45d874 commit 2ada13f

File tree

6 files changed

+737
-680
lines changed

6 files changed

+737
-680
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
# Clipper2-java
5-
A Java port of _[Clipper2](https://github.com/AngusJohnson/Clipper2)_.
5+
A Java port of _[Clipper2](https://github.com/AngusJohnson/Clipper2)_, an open source freeware software library that performs line and polygon clipping, and offsetting.
66

77
## Usage
88

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>micycle</groupId>
66
<artifactId>clipper2</artifactId>
7-
<version>1.3.0</version>
7+
<version>1.3.1</version>
88
<name>Clipper2</name>
99
<properties>
1010
<jmh.version>1.36</jmh.version>

src/main/java/clipper2/core/InternalClipper.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,75 @@ public static PointInPolygonResult PointInPolygon(Point64 pt, Path64 polygon) {
224224
return PointInPolygonResult.IsInside;
225225
}
226226

227+
/**
228+
* Given three points, returns true if they are collinear.
229+
*/
230+
public static boolean IsCollinear(Point64 pt1, Point64 sharedPt, Point64 pt2) {
231+
long a = sharedPt.x - pt1.x;
232+
long b = pt2.y - sharedPt.y;
233+
long c = sharedPt.y - pt1.y;
234+
long d = pt2.x - sharedPt.x;
235+
// use the exact‐arithmetic product test
236+
return productsAreEqual(a, b, c, d);
237+
}
238+
239+
/**
240+
* Holds the low‐ and high‐64 bits of a 128‐bit product.
241+
*/
242+
private static class MultiplyUInt64Result {
243+
public final long lo64;
244+
public final long hi64;
245+
246+
public MultiplyUInt64Result(long lo64, long hi64) {
247+
this.lo64 = lo64;
248+
this.hi64 = hi64;
249+
}
250+
}
251+
252+
/**
253+
* Multiply two unsigned 64‐bit quantities (given in signed longs) and return
254+
* the full 128‐bit result as hi/lo.
255+
*/
256+
private static MultiplyUInt64Result multiplyUInt64(long a, long b) {
257+
// mask to extract low 32 bits
258+
final long MASK_32 = 0xFFFFFFFFL;
259+
long aLow = a & MASK_32;
260+
long aHigh = a >>> 32;
261+
long bLow = b & MASK_32;
262+
long bHigh = b >>> 32;
263+
264+
long x1 = aLow * bLow;
265+
long x2 = aHigh * bLow + (x1 >>> 32);
266+
long x3 = aLow * bHigh + (x2 & MASK_32);
267+
268+
long lo64 = ((x3 & MASK_32) << 32) | (x1 & MASK_32);
269+
long hi64 = aHigh * bHigh + (x2 >>> 32) + (x3 >>> 32);
270+
271+
return new MultiplyUInt64Result(lo64, hi64);
272+
}
273+
274+
/**
275+
* Returns true iff a*b == c*d (as 128‐bit signed products). We compare both
276+
* magnitude (via unsigned 128‐bit) and sign.
277+
*/
278+
private static boolean productsAreEqual(long a, long b, long c, long d) {
279+
// unsigned absolute values; note: -Long.MIN_VALUE == Long.MIN_VALUE
280+
long absA = a < 0 ? -a : a;
281+
long absB = b < 0 ? -b : b;
282+
long absC = c < 0 ? -c : c;
283+
long absD = d < 0 ? -d : d;
284+
285+
MultiplyUInt64Result p1 = multiplyUInt64(absA, absB);
286+
MultiplyUInt64Result p2 = multiplyUInt64(absC, absD);
287+
288+
int signAB = triSign(a) * triSign(b);
289+
int signCD = triSign(c) * triSign(d);
290+
291+
return p1.lo64 == p2.lo64 && p1.hi64 == p2.hi64 && signAB == signCD;
292+
}
293+
294+
private static int triSign(long x) {
295+
return x > 0 ? 1 : (x < 0 ? -1 : 0);
296+
}
297+
227298
}

0 commit comments

Comments
 (0)