Skip to content

Commit dbcce6b

Browse files
committed
Refactor to suggested changes
1 parent 92638a6 commit dbcce6b

File tree

5 files changed

+203
-271
lines changed

5 files changed

+203
-271
lines changed

src/main/java/com/thealgorithms/divideandconquer/ConvexHull.java

-229
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.Comparator;
6+
import java.util.HashSet;
7+
import java.util.List;
8+
import java.util.Set;
9+
import java.util.TreeSet;
10+
11+
/**
12+
* A class providing algorithms to compute the convex hull of a set of points
13+
* using brute-force and recursive methods.
14+
*
15+
* Convex hull: The smallest convex polygon that contains all the given points.
16+
*
17+
* Algorithms provided:
18+
* 1. Brute-Force Method
19+
* 2. Recursive (Divide-and-Conquer) Method
20+
*
21+
* @author Hardvan
22+
*/
23+
public final class ConvexHull {
24+
private ConvexHull() {
25+
}
26+
27+
private static boolean checkPointOrientation(Point i, Point j, Point k) {
28+
int detK = Point.orientation(i, j, k);
29+
if (detK > 0) {
30+
return true; // pointsLeftOfIJ
31+
} else if (detK < 0) {
32+
return false; // pointsRightOfIJ
33+
} else {
34+
return k.compareTo(i) >= 0 && k.compareTo(j) <= 0;
35+
}
36+
}
37+
38+
public static List<Point> convexHullBruteForce(List<Point> points) {
39+
Set<Point> convexSet = new TreeSet<>(Comparator.naturalOrder());
40+
41+
for (int i = 0; i < points.size() - 1; i++) {
42+
for (int j = i + 1; j < points.size(); j++) {
43+
boolean allPointsOnOneSide = true;
44+
boolean leftSide = checkPointOrientation(points.get(i), points.get(j), points.get((i + 1) % points.size()));
45+
46+
for (int k = 0; k < points.size(); k++) {
47+
if (k != i && k != j && checkPointOrientation(points.get(i), points.get(j), points.get(k)) != leftSide) {
48+
allPointsOnOneSide = false;
49+
break;
50+
}
51+
}
52+
53+
if (allPointsOnOneSide) {
54+
convexSet.add(points.get(i));
55+
convexSet.add(points.get(j));
56+
}
57+
}
58+
}
59+
60+
return new ArrayList<>(convexSet);
61+
}
62+
63+
public static List<Point> convexHullRecursive(List<Point> points) {
64+
Collections.sort(points);
65+
Set<Point> convexSet = new HashSet<>();
66+
Point leftMostPoint = points.get(0);
67+
Point rightMostPoint = points.get(points.size() - 1);
68+
69+
convexSet.add(leftMostPoint);
70+
convexSet.add(rightMostPoint);
71+
72+
List<Point> upperHull = new ArrayList<>();
73+
List<Point> lowerHull = new ArrayList<>();
74+
75+
for (int i = 1; i < points.size() - 1; i++) {
76+
int det = Point.orientation(leftMostPoint, rightMostPoint, points.get(i));
77+
if (det > 0) {
78+
upperHull.add(points.get(i));
79+
} else if (det < 0) {
80+
lowerHull.add(points.get(i));
81+
}
82+
}
83+
84+
constructHull(upperHull, leftMostPoint, rightMostPoint, convexSet);
85+
constructHull(lowerHull, rightMostPoint, leftMostPoint, convexSet);
86+
87+
List<Point> result = new ArrayList<>(convexSet);
88+
Collections.sort(result);
89+
return result;
90+
}
91+
92+
private static void constructHull(List<Point> points, Point left, Point right, Set<Point> convexSet) {
93+
if (!points.isEmpty()) {
94+
Point extremePoint = null;
95+
int extremePointDistance = Integer.MIN_VALUE;
96+
List<Point> candidatePoints = new ArrayList<>();
97+
98+
for (Point p : points) {
99+
int det = Point.orientation(left, right, p);
100+
if (det > 0) {
101+
candidatePoints.add(p);
102+
if (det > extremePointDistance) {
103+
extremePointDistance = det;
104+
extremePoint = p;
105+
}
106+
}
107+
}
108+
109+
if (extremePoint != null) {
110+
constructHull(candidatePoints, left, extremePoint, convexSet);
111+
convexSet.add(extremePoint);
112+
constructHull(candidatePoints, extremePoint, right, convexSet);
113+
}
114+
}
115+
}
116+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.util.Comparator;
4+
5+
public record Point(int x, int y) implements Comparable<Point> {
6+
7+
@Override
8+
public int compareTo(Point other) {
9+
int cmpY = Integer.compare(this.y, other.y);
10+
return cmpY != 0 ? cmpY : Integer.compare(this.x, other.x);
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return String.format("(%d, %d)", x, y);
16+
}
17+
18+
public Comparator<Point> polarOrder() {
19+
return new PolarOrder();
20+
}
21+
22+
public static int orientation(Point a, Point b, Point c) {
23+
return Integer.compare((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x), 0);
24+
}
25+
26+
private final class PolarOrder implements Comparator<Point> {
27+
@Override
28+
public int compare(Point p1, Point p2) {
29+
int dx1 = p1.x - x;
30+
int dy1 = p1.y - y;
31+
int dx2 = p2.x - x;
32+
int dy2 = p2.y - y;
33+
34+
if (dy1 >= 0 && dy2 < 0) {
35+
return -1; // p1 above p2
36+
} else if (dy2 >= 0 && dy1 < 0) {
37+
return 1; // p1 below p2
38+
} else if (dy1 == 0 && dy2 == 0) { // Collinear and horizontal
39+
return Integer.compare(dx2, dx1);
40+
} else {
41+
return -orientation(Point.this, p1, p2); // Compare orientation
42+
}
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)