Skip to content

Commit 83eca10

Browse files
committed
Address line intersection edge cases from review
1 parent d3e8eb2 commit 83eca10

File tree

2 files changed

+41
-15
lines changed

2 files changed

+41
-15
lines changed

src/main/java/com/thealgorithms/geometry/LineIntersection.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,31 +62,43 @@ public static Optional<Point2D.Double> intersectionPoint(Point p1, Point p2, Poi
6262
return Optional.empty();
6363
}
6464

65-
double x1 = p1.x();
66-
double y1 = p1.y();
67-
double x2 = p2.x();
68-
double y2 = p2.y();
69-
double x3 = q1.x();
70-
double y3 = q1.y();
71-
double x4 = q2.x();
72-
double y4 = q2.y();
65+
long x1 = p1.x();
66+
long y1 = p1.y();
67+
long x2 = p2.x();
68+
long y2 = p2.y();
69+
long x3 = q1.x();
70+
long y3 = q1.y();
71+
long x4 = q2.x();
72+
long y4 = q2.y();
7373

74-
double denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
75-
if (denominator == 0.0) {
76-
return Optional.empty();
74+
long denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
75+
if (denominator == 0L) {
76+
return sharedEndpoint(p1, p2, q1, q2);
7777
}
7878

79-
double numeratorX = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
80-
double numeratorY = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
79+
long determinant1 = x1 * y2 - y1 * x2;
80+
long determinant2 = x3 * y4 - y3 * x4;
81+
long numeratorX = determinant1 * (x3 - x4) - (x1 - x2) * determinant2;
82+
long numeratorY = determinant1 * (y3 - y4) - (y1 - y2) * determinant2;
8183

82-
return Optional.of(new Point2D.Double(numeratorX / denominator, numeratorY / denominator));
84+
return Optional.of(new Point2D.Double(numeratorX / (double) denominator, numeratorY / (double) denominator));
8385
}
8486

8587
private static int orientation(Point a, Point b, Point c) {
86-
long cross = (long) (b.x() - a.x()) * (c.y() - a.y()) - (long) (b.y() - a.y()) * (c.x() - a.x());
88+
long cross = ((long) b.x() - a.x()) * ((long) c.y() - a.y()) - ((long) b.y() - a.y()) * ((long) c.x() - a.x());
8789
return Long.compare(cross, 0L);
8890
}
8991

92+
private static Optional<Point2D.Double> sharedEndpoint(Point p1, Point p2, Point q1, Point q2) {
93+
if (p1.equals(q1) || p1.equals(q2)) {
94+
return Optional.of(new Point2D.Double(p1.x(), p1.y()));
95+
}
96+
if (p2.equals(q1) || p2.equals(q2)) {
97+
return Optional.of(new Point2D.Double(p2.x(), p2.y()));
98+
}
99+
return Optional.empty();
100+
}
101+
90102
private static boolean onSegment(Point a, Point b, Point c) {
91103
return b.x() >= Math.min(a.x(), c.x()) && b.x() <= Math.max(a.x(), c.x())
92104
&& b.y() >= Math.min(a.y(), c.y()) && b.y() <= Math.max(a.y(), c.y());

src/test/java/com/thealgorithms/geometry/LineIntersectionTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ void testCollinearDisjointSegments() {
7171
assertTrue(LineIntersection.intersectionPoint(p1, p2, q1, q2).isEmpty());
7272
}
7373

74+
@Test
75+
void testCollinearSegmentsTouchingAtEndpointHaveUniquePoint() {
76+
Point p1 = new Point(0, 0);
77+
Point p2 = new Point(2, 2);
78+
Point q1 = new Point(2, 2);
79+
Point q2 = new Point(4, 4);
80+
81+
assertTrue(LineIntersection.intersects(p1, p2, q1, q2));
82+
Optional<Point2D.Double> intersection = LineIntersection.intersectionPoint(p1, p2, q1, q2);
83+
assertTrue(intersection.isPresent());
84+
assertEquals(2.0, intersection.orElseThrow().getX(), 1e-9);
85+
assertEquals(2.0, intersection.orElseThrow().getY(), 1e-9);
86+
}
87+
7488
@Test
7589
void testVerticalAndHorizontalCrossingSegments() {
7690
Point p1 = new Point(2, 0);

0 commit comments

Comments
 (0)