Skip to content

Commit 29e5224

Browse files
committed
fix: correct import order in BentleyOttmann
1 parent 405647a commit 29e5224

File tree

2 files changed

+66
-72
lines changed

2 files changed

+66
-72
lines changed

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.thealgorithms.geometry;
22

33
import java.awt.geom.Point2D;
4+
import java.util.ArrayList;
45
import java.util.Comparator;
6+
import java.util.HashMap;
57
import java.util.HashSet;
6-
import java.util.Objects;
7-
import java.util.Set;
88
import java.util.List;
9+
import java.util.Map;
10+
import java.util.NavigableSet;
11+
import java.util.Objects;
912
import java.util.PriorityQueue;
13+
import java.util.Set;
14+
import java.util.SortedSet;
1015
import java.util.TreeSet;
11-
import java.util.Map;
12-
import java.util.HashMap;
13-
import java.util.ArrayList;
1416

1517
/**
1618
* Implementation of the Bentley–Ottmann algorithm for finding all intersection
@@ -283,15 +285,15 @@ private static void handleEvent(Event event, TreeSet<Segment> status, PriorityQu
283285
}
284286
}
285287

286-
private static Segment getNeighbor(TreeSet<Segment> status, Set<Segment> removed, boolean lower) {
288+
private static Segment getNeighbor(NavigableSet<Segment> status, Set<Segment> removed, boolean lower) {
287289
if (removed.isEmpty()) {
288290
return null;
289291
}
290292
Segment ref = removed.iterator().next();
291293
return lower ? status.lower(ref) : status.higher(ref);
292294
}
293295

294-
private static Segment getLeftmost(Set<Segment> segments, TreeSet<Segment> status) {
296+
private static Segment getLeftmost(Set<Segment> segments, SortedSet<Segment> status) {
295297
Segment leftmost = null;
296298
for (Segment s : segments) {
297299
if (leftmost == null || Objects.requireNonNull(status.comparator()).compare(s, leftmost) < 0) {
@@ -301,7 +303,7 @@ private static Segment getLeftmost(Set<Segment> segments, TreeSet<Segment> statu
301303
return leftmost;
302304
}
303305

304-
private static Segment getRightmost(Set<Segment> segments, TreeSet<Segment> status) {
306+
private static Segment getRightmost(Set<Segment> segments, SortedSet<Segment> status) {
305307
Segment rightmost = null;
306308
for (Segment s : segments) {
307309
if (status.comparator() != null && (rightmost == null || status.comparator().compare(s, rightmost) > 0)) {
@@ -318,10 +320,10 @@ private static void findNewEvent(Segment s1, Segment s2, Point2D.Double currentP
318320

319321
// Check if event already exists
320322
boolean exists = false;
321-
for (Point2D.Double p : eventMap.keySet()) {
322-
if (pointsEqual(p, intersection)) {
323+
for (Map.Entry<Point2D.Double, Event> entry : eventMap.entrySet()) {
324+
if (pointsEqual(entry.getKey(), intersection)) {
323325
exists = true;
324-
Event existingEvent = eventMap.get(p);
326+
Event existingEvent = entry.getValue();
325327
existingEvent.addSegment(s1);
326328
existingEvent.addSegment(s2);
327329
break;

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

Lines changed: 53 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,35 @@ public class BentleyOttmannTest {
2727

2828
@Test
2929
void testSingleIntersection() {
30-
List<Object> segments = List.of(newSegment(1, 1, 5, 5), newSegment(1, 5, 5, 1));
30+
List<BentleyOttmann.Segment> segments = List.of(newSegment(1, 1, 5, 5), newSegment(1, 5, 5, 1));
3131

32-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
32+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
3333
assertEquals(1, intersections.size());
3434
assertTrue(containsPoint(intersections, 3.0, 3.0));
3535
}
3636

3737
@Test
3838
void testVerticalIntersection() {
39-
List<Object> segments = List.of(newSegment(3, 0, 3, 6), newSegment(1, 1, 5, 5));
39+
List<BentleyOttmann.Segment> segments = List.of(newSegment(3, 0, 3, 6), newSegment(1, 1, 5, 5));
4040

41-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
41+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
4242
assertEquals(1, intersections.size());
4343
assertTrue(containsPoint(intersections, 3.0, 3.0));
4444
}
4545

4646
@Test
4747
void testNoIntersection() {
48-
List<Object> segments = List.of(newSegment(0, 0, 1, 1), newSegment(2, 2, 3, 3));
48+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 1, 1), newSegment(2, 2, 3, 3));
4949

50-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
50+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
5151
assertTrue(intersections.isEmpty());
5252
}
5353

5454
@Test
5555
void testCoincidentSegments() {
56-
List<Object> segments = List.of(newSegment(1, 1, 5, 5), newSegment(1, 1, 5, 5));
56+
List<BentleyOttmann.Segment> segments = List.of(newSegment(1, 1, 5, 5), newSegment(1, 1, 5, 5));
5757

58-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
58+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
5959

6060
assertEquals(2, intersections.size(), "Two identical segments should report 2 intersection points (both endpoints)");
6161
assertTrue(containsPoint(intersections, 1.0, 1.0));
@@ -64,23 +64,23 @@ void testCoincidentSegments() {
6464

6565
@Test
6666
void testHorizontalIntersection() {
67-
List<Object> segments = List.of(newSegment(0, 2, 4, 2), newSegment(2, 0, 2, 4));
67+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 2, 4, 2), newSegment(2, 0, 2, 4));
6868

69-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
69+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
7070
assertTrue(containsPoint(intersections, 2.0, 2.0));
7171
}
7272

7373
@Test
7474
void testEmptyList() {
75-
List<Object> segments = List.of();
76-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
75+
List<BentleyOttmann.Segment> segments = List.of();
76+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
7777
assertTrue(intersections.isEmpty());
7878
}
7979

8080
@Test
8181
void testSingleSegment() {
82-
List<Object> segments = List.of(newSegment(0, 0, 5, 5));
83-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
82+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 5, 5));
83+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
8484
assertTrue(intersections.isEmpty());
8585
}
8686

@@ -92,32 +92,32 @@ void testNullListThrowsException() {
9292
@Test
9393
void testParallelSegments() {
9494
// Test 1: Parallel diagonal segments
95-
List<Object> diagonalSegments = List.of(newSegment(0, 0, 4, 4), newSegment(1, 0, 5, 4), newSegment(2, 0, 6, 4));
96-
assertTrue(BentleyOttmann.findIntersections(cast(diagonalSegments)).isEmpty());
95+
List<BentleyOttmann.Segment> diagonalSegments = List.of(newSegment(0, 0, 4, 4), newSegment(1, 0, 5, 4), newSegment(2, 0, 6, 4));
96+
assertTrue(BentleyOttmann.findIntersections(diagonalSegments).isEmpty());
9797

9898
// Test 2: Parallel vertical segments
99-
List<Object> verticalSegments = List.of(newSegment(1, 0, 1, 5), newSegment(2, 0, 2, 5), newSegment(3, 0, 3, 5));
100-
assertTrue(BentleyOttmann.findIntersections(cast(verticalSegments)).isEmpty());
99+
List<BentleyOttmann.Segment> verticalSegments = List.of(newSegment(1, 0, 1, 5), newSegment(2, 0, 2, 5), newSegment(3, 0, 3, 5));
100+
assertTrue(BentleyOttmann.findIntersections(verticalSegments).isEmpty());
101101

102102
// Test 3: Parallel horizontal segments
103-
List<Object> horizontalSegments = List.of(newSegment(0, 1, 5, 1), newSegment(0, 2, 5, 2), newSegment(0, 3, 5, 3));
104-
assertTrue(BentleyOttmann.findIntersections(cast(horizontalSegments)).isEmpty());
103+
List<BentleyOttmann.Segment> horizontalSegments = List.of(newSegment(0, 1, 5, 1), newSegment(0, 2, 5, 2), newSegment(0, 3, 5, 3));
104+
assertTrue(BentleyOttmann.findIntersections(horizontalSegments).isEmpty());
105105
}
106106

107107
@Test
108108
void testTouchingEndpoints() {
109-
List<Object> segments = List.of(newSegment(0, 0, 2, 2), newSegment(2, 2, 4, 0));
109+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 2, 2), newSegment(2, 2, 4, 0));
110110

111-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
111+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
112112
assertEquals(1, intersections.size());
113113
assertTrue(containsPoint(intersections, 2.0, 2.0));
114114
}
115115

116116
@Test
117117
void testOverlappingCollinearSegments() {
118-
List<Object> segments = List.of(newSegment(0, 0, 4, 4), newSegment(2, 2, 6, 6));
118+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 4, 4), newSegment(2, 2, 6, 6));
119119

120-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
120+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
121121
// Overlapping collinear segments share the point (2,2) where second starts
122122
// and (4,4) where first ends - at least one should be detected
123123
assertFalse(intersections.isEmpty(), "Should find at least one overlap point");
@@ -127,13 +127,13 @@ void testOverlappingCollinearSegments() {
127127
@Test
128128
void testMultipleSegmentsAtOnePoint() {
129129
// Star pattern: 4 segments meeting at (2, 2)
130-
List<Object> segments = List.of(newSegment(0, 2, 4, 2), // horizontal
130+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 2, 4, 2), // horizontal
131131
newSegment(2, 0, 2, 4), // vertical
132132
newSegment(0, 0, 4, 4), // diagonal /
133133
newSegment(0, 4, 4, 0) // diagonal \
134134
);
135135

136-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
136+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
137137
assertTrue(containsPoint(intersections, 2.0, 2.0));
138138
// All segments meet at (2, 2), so should be reported once
139139
assertEquals(1, intersections.size());
@@ -142,7 +142,7 @@ void testMultipleSegmentsAtOnePoint() {
142142
@Test
143143
void testGridPattern() {
144144
// 3x3 grid: should have 9 intersection points
145-
List<Object> segments = new ArrayList<>();
145+
List<BentleyOttmann.Segment> segments = new ArrayList<>();
146146

147147
// Vertical lines at x = 0, 1, 2
148148
for (int i = 0; i <= 2; i++) {
@@ -154,7 +154,7 @@ void testGridPattern() {
154154
segments.add(newSegment(0, i, 2, i));
155155
}
156156

157-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
157+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
158158

159159
// Each vertical line crosses each horizontal line
160160
// 3 vertical × 3 horizontal = 9 intersections
@@ -171,12 +171,12 @@ void testGridPattern() {
171171
@Test
172172
void testTriangleIntersections() {
173173
// Three segments forming a triangle
174-
List<Object> segments = List.of(newSegment(0, 0, 4, 0), // base
174+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 4, 0), // base
175175
newSegment(0, 0, 2, 3), // left side
176176
newSegment(4, 0, 2, 3) // right side
177177
);
178178

179-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
179+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
180180
// Triangle vertices are intersections
181181
assertTrue(containsPoint(intersections, 0.0, 0.0));
182182
assertTrue(containsPoint(intersections, 4.0, 0.0));
@@ -187,52 +187,52 @@ void testTriangleIntersections() {
187187
@Test
188188
void testCrossingDiagonals() {
189189
// X pattern with multiple crossings
190-
List<Object> segments = List.of(newSegment(0, 0, 10, 10), newSegment(0, 10, 10, 0), newSegment(5, 0, 5, 10), newSegment(0, 5, 10, 5));
190+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 10, 10), newSegment(0, 10, 10, 0), newSegment(5, 0, 5, 10), newSegment(0, 5, 10, 5));
191191

192-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
192+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
193193
assertTrue(containsPoint(intersections, 5.0, 5.0), "Center point should be present");
194194
assertEquals(1, intersections.size());
195195
}
196196

197197
@Test
198198
void testVerySmallSegments() {
199-
List<Object> segments = List.of(newSegment(0.001, 0.001, 0.002, 0.002), newSegment(0.001, 0.002, 0.002, 0.001));
199+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0.001, 0.001, 0.002, 0.002), newSegment(0.001, 0.002, 0.002, 0.001));
200200

201-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
201+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
202202
assertEquals(1, intersections.size());
203203
assertTrue(containsPoint(intersections, 0.0015, 0.0015));
204204
}
205205

206206
@Test
207207
void testSegmentsShareCommonPoint() {
208-
List<Object> segmentsSameStart = List.of(newSegment(0, 0, 4, 4), newSegment(0, 0, 4, -4), newSegment(0, 0, -4, 4));
208+
List<BentleyOttmann.Segment> segmentsSameStart = List.of(newSegment(0, 0, 4, 4), newSegment(0, 0, 4, -4), newSegment(0, 0, -4, 4));
209209

210-
Set<Point2D.Double> intersectionsSameStart = BentleyOttmann.findIntersections(cast(segmentsSameStart));
210+
Set<Point2D.Double> intersectionsSameStart = BentleyOttmann.findIntersections(segmentsSameStart);
211211
assertTrue(containsPoint(intersectionsSameStart, 0.0, 0.0));
212-
List<Object> segmentsSameEnd = List.of(newSegment(0, 0, 4, 4), newSegment(8, 4, 4, 4), newSegment(4, 8, 4, 4));
212+
List<BentleyOttmann.Segment> segmentsSameEnd = List.of(newSegment(0, 0, 4, 4), newSegment(8, 4, 4, 4), newSegment(4, 8, 4, 4));
213213

214-
Set<Point2D.Double> intersectionsSameEnd = BentleyOttmann.findIntersections(cast(segmentsSameEnd));
214+
Set<Point2D.Double> intersectionsSameEnd = BentleyOttmann.findIntersections(segmentsSameEnd);
215215
assertTrue(containsPoint(intersectionsSameEnd, 4.0, 4.0));
216216
}
217217

218218
@Test
219219
void testSegmentsAtAngles() {
220220
// Segments at 45, 90, 135 degrees
221-
List<Object> segments = List.of(newSegment(0, 2, 4, 2), // horizontal
221+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 2, 4, 2), // horizontal
222222
newSegment(2, 0, 2, 4), // vertical
223223
newSegment(0, 0, 4, 4), // 45 degrees
224224
newSegment(0, 4, 4, 0) // 135 degrees
225225
);
226226

227-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
227+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
228228
assertTrue(containsPoint(intersections, 2.0, 2.0));
229229
}
230230

231231
@Test
232232
void testPerformanceWithManySegments() {
233233
// Generate 100 random segments
234234
Random random = new Random(42); // Fixed seed for reproducibility
235-
List<Object> segments = new ArrayList<>();
235+
List<BentleyOttmann.Segment> segments = new ArrayList<>();
236236

237237
for (int i = 0; i < 100; i++) {
238238
double x1 = random.nextDouble() * 100;
@@ -243,7 +243,7 @@ void testPerformanceWithManySegments() {
243243
}
244244

245245
long startTime = System.currentTimeMillis();
246-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
246+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
247247
long endTime = System.currentTimeMillis();
248248

249249
long duration = endTime - startTime;
@@ -259,12 +259,12 @@ void testPerformanceWithManySegments() {
259259
@Test
260260
void testIssueExample() {
261261
// Example from the GitHub issue
262-
List<Object> segments = List.of(newSegment(1, 1, 5, 5), // Segment A
262+
List<BentleyOttmann.Segment> segments = List.of(newSegment(1, 1, 5, 5), // Segment A
263263
newSegment(1, 5, 5, 1), // Segment B
264264
newSegment(3, 0, 3, 6) // Segment C
265265
);
266266

267-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
267+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
268268

269269
// Expected output: [(3, 3)]
270270
assertEquals(1, intersections.size(), "Should find exactly one intersection");
@@ -274,21 +274,21 @@ void testIssueExample() {
274274
@Test
275275
void testEventTypeOrdering() {
276276
// Multiple events at the same point with different types
277-
List<Object> segments = List.of(newSegment(2, 2, 6, 2), // ends at (2,2)
277+
List<BentleyOttmann.Segment> segments = List.of(newSegment(2, 2, 6, 2), // ends at (2,2)
278278
newSegment(0, 2, 2, 2), // ends at (2,2)
279279
newSegment(2, 2, 2, 6), // starts at (2,2)
280280
newSegment(2, 0, 2, 2) // ends at (2,2)
281281
);
282282

283-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
283+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
284284
assertTrue(containsPoint(intersections, 2.0, 2.0));
285285
}
286286

287287
@Test
288288
void testCollinearOverlapWithInteriorPoint() {
289289
// Test collinear segments where one segment's interior overlaps another
290-
List<Object> segments = List.of(newSegment(0, 0, 6, 6), newSegment(2, 2, 4, 4));
291-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
290+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 6, 6), newSegment(2, 2, 4, 4));
291+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
292292

293293
// Should find at least one overlap point (where segments touch/overlap)
294294
assertFalse(intersections.isEmpty(), "Should find overlap points for collinear segments");
@@ -299,38 +299,30 @@ void testCollinearOverlapWithInteriorPoint() {
299299
void testCollinearTouchingAtBothEndpoints() {
300300
// Test collinear segments that touch at both endpoints
301301
// This triggers the "endpoint of both" logic (line 354-355)
302-
List<Object> segments = List.of(newSegment(0, 0, 4, 4), newSegment(4, 4, 8, 8));
302+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 4, 4), newSegment(4, 4, 8, 8));
303303

304-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
304+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
305305
assertEquals(1, intersections.size());
306306
assertTrue(containsPoint(intersections, 4.0, 4.0), "Should find touching point");
307307
}
308308

309309
@Test
310310
void testCollinearOverlapPartialInterior() {
311311
// Test case where segments overlap but one point is inside, one is endpoint
312-
List<Object> segments = List.of(newSegment(0, 0, 5, 5), newSegment(3, 3, 7, 7));
312+
List<BentleyOttmann.Segment> segments = List.of(newSegment(0, 0, 5, 5), newSegment(3, 3, 7, 7));
313313

314-
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(cast(segments));
314+
Set<Point2D.Double> intersections = BentleyOttmann.findIntersections(segments);
315315

316316
// Should detect the overlap region
317317
assertFalse(intersections.isEmpty());
318318
// The algorithm should return at least one of the boundary points
319319
assertTrue(containsPoint(intersections, 3.0, 3.0) || containsPoint(intersections, 5.0, 5.0));
320320
}
321321

322-
private static Object newSegment(double x1, double y1, double x2, double y2) {
322+
private static BentleyOttmann.Segment newSegment(double x1, double y1, double x2, double y2) {
323323
return new BentleyOttmann.Segment(new Point2D.Double(x1, y1), new Point2D.Double(x2, y2));
324324
}
325325

326-
private static List<BentleyOttmann.Segment> cast(List<Object> objs) {
327-
List<BentleyOttmann.Segment> result = new ArrayList<>();
328-
for (Object o : objs) {
329-
result.add((BentleyOttmann.Segment) o);
330-
}
331-
return result;
332-
}
333-
334326
private static boolean containsPoint(Set<Point2D.Double> points, double x, double y) {
335327
return points.stream().anyMatch(p -> Math.abs(p.x - x) < EPS && Math.abs(p.y - y) < EPS);
336328
}

0 commit comments

Comments
 (0)