Skip to content

Commit 44c8a26

Browse files
Sushant NadavadeSushant Nadavade
authored andcommitted
improvements are made
1 parent 2f46d1f commit 44c8a26

File tree

2 files changed

+108
-202
lines changed

2 files changed

+108
-202
lines changed

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

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,32 @@
66

77
/**
88
* A class implementing the Rotating Calipers algorithm for geometric computations on convex polygons.
9-
*
9+
*
1010
* The Rotating Calipers algorithm is an efficient technique for solving various geometric problems
1111
* on convex polygons, including:
1212
* - Computing the diameter (maximum distance between any two points)
1313
* - Computing the width (minimum distance between parallel supporting lines)
1414
* - Finding the minimum-area bounding rectangle
15-
*
15+
*
1616
* Algorithm Description:
1717
* 1. Compute the convex hull of the given points
1818
* 2. Use rotating calipers (parallel lines) that rotate around the convex hull
1919
* 3. For each rotation, compute the desired geometric property
2020
* 4. Return the optimal result
21-
*
21+
*
2222
* Time Complexity: O(n) where n is the number of points in the convex hull
2323
* Space Complexity: O(n) for storing the convex hull
24-
*
24+
*
2525
* Reference:
2626
* Shamos, M. I. (1978). Computational Geometry.
27-
*
27+
*
2828
* @author TheAlgorithms
2929
*/
3030
public final class RotatingCalipers {
31-
31+
3232
private RotatingCalipers() {
3333
}
34-
34+
3535
/**
3636
* Represents a pair of points with their distance.
3737
*/
@@ -41,7 +41,7 @@ public String toString() {
4141
return String.format("PointPair(%s, %s, distance=%.2f)", p1, p2, distance);
4242
}
4343
}
44-
44+
4545
/**
4646
* Represents a rectangle with its area.
4747
*/
@@ -51,11 +51,11 @@ public String toString() {
5151
return String.format("Rectangle(%s, %s, area=%.2f)", bottomLeft, topRight, area);
5252
}
5353
}
54-
54+
5555
/**
5656
* Computes the diameter of a convex polygon using rotating calipers.
5757
* The diameter is the maximum distance between any two points of the polygon.
58-
*
58+
*
5959
* @param points List of points representing a convex polygon
6060
* @return PointPair containing the two points with maximum distance and the distance
6161
* @throws IllegalArgumentException if points is null or has less than 2 points
@@ -64,54 +64,54 @@ public static PointPair computeDiameter(List<Point> points) {
6464
if (points == null || points.size() < 2) {
6565
throw new IllegalArgumentException("Points list must contain at least 2 points");
6666
}
67-
67+
6868
List<Point> hull = ConvexHull.convexHullRecursive(new ArrayList<>(points));
6969
if (hull.size() < 2) {
7070
throw new IllegalArgumentException("Convex hull must contain at least 2 points");
7171
}
72-
72+
7373
hull = ensureCounterClockwiseOrder(hull);
74-
74+
7575
if (hull.size() == 2) {
7676
Point p1 = hull.get(0);
7777
Point p2 = hull.get(1);
7878
return new PointPair(p1, p2, distance(p1, p2));
7979
}
80-
80+
8181
int n = hull.size();
8282
PointPair maxPair = null;
8383
double maxDistance = 0.0;
84-
84+
8585
int j = 1;
8686
for (int i = 0; i < n; i++) {
8787
Point p1 = hull.get(i);
88-
88+
8989
while (true) {
9090
Point next = hull.get((j + 1) % n);
9191
double dist1 = distance(p1, hull.get(j));
9292
double dist2 = distance(p1, next);
93-
93+
9494
if (dist2 > dist1) {
9595
j = (j + 1) % n;
9696
} else {
9797
break;
9898
}
9999
}
100-
100+
101101
double dist = distance(p1, hull.get(j));
102102
if (dist > maxDistance) {
103103
maxDistance = dist;
104104
maxPair = new PointPair(p1, hull.get(j), dist);
105105
}
106106
}
107-
107+
108108
return maxPair;
109109
}
110-
110+
111111
/**
112112
* Computes the width of a convex polygon using rotating calipers.
113113
* The width is the minimum distance between two parallel supporting lines.
114-
*
114+
*
115115
* @param points List of points representing a convex polygon
116116
* @return The minimum width of the polygon
117117
* @throws IllegalArgumentException if points is null or has less than 2 points
@@ -120,40 +120,40 @@ public static double computeWidth(List<Point> points) {
120120
if (points == null || points.size() < 2) {
121121
throw new IllegalArgumentException("Points list must contain at least 2 points");
122122
}
123-
123+
124124
List<Point> hull = ConvexHull.convexHullRecursive(new ArrayList<>(points));
125125
if (hull.size() < 2) {
126126
throw new IllegalArgumentException("Convex hull must contain at least 2 points");
127127
}
128-
128+
129129
hull = ensureCounterClockwiseOrder(hull);
130-
130+
131131
if (hull.size() == 2) {
132132
return 0.0;
133133
}
134-
134+
135135
int n = hull.size();
136136
double minWidth = Double.MAX_VALUE;
137-
137+
138138
// Use rotating calipers to find minimum width
139139
for (int i = 0; i < n; i++) {
140140
Point p1 = hull.get(i);
141141
Point p2 = hull.get((i + 1) % n);
142-
142+
143143
// Find the antipodal point for this edge
144144
int j = findAntipodalPoint(hull, i);
145-
145+
146146
// Compute width as distance between parallel lines
147147
double width = distanceToLine(p1, p2, hull.get(j));
148148
minWidth = Math.min(minWidth, width);
149149
}
150-
150+
151151
return minWidth;
152152
}
153-
153+
154154
/**
155155
* Computes the minimum-area bounding rectangle of a convex polygon using rotating calipers.
156-
*
156+
*
157157
* @param points List of points representing a convex polygon
158158
* @return Rectangle containing the minimum-area bounding rectangle
159159
* @throws IllegalArgumentException if points is null or has less than 2 points
@@ -162,71 +162,71 @@ public static Rectangle computeMinimumAreaBoundingRectangle(List<Point> points)
162162
if (points == null || points.size() < 2) {
163163
throw new IllegalArgumentException("Points list must contain at least 2 points");
164164
}
165-
165+
166166
List<Point> hull = ConvexHull.convexHullRecursive(new ArrayList<>(points));
167167
if (hull.size() < 2) {
168168
throw new IllegalArgumentException("Convex hull must contain at least 2 points");
169169
}
170-
170+
171171
hull = ensureCounterClockwiseOrder(hull);
172-
172+
173173
if (hull.size() == 2) {
174174
Point p1 = hull.get(0);
175175
Point p2 = hull.get(1);
176176
return new Rectangle(p1, p2, 0.0);
177177
}
178-
178+
179179
int n = hull.size();
180180
double minArea = Double.MAX_VALUE;
181181
Rectangle bestRectangle = null;
182-
182+
183183
for (int i = 0; i < n; i++) {
184184
Point p1 = hull.get(i);
185185
Point p2 = hull.get((i + 1) % n);
186-
186+
187187
int j = findAntipodalPoint(hull, i);
188-
188+
189189
double edgeLength = distance(p1, p2);
190190
double height = distanceToLine(p1, p2, hull.get(j));
191-
191+
192192
double area = edgeLength * height;
193-
193+
194194
if (area < minArea) {
195195
minArea = area;
196196
Point bottomLeft = computeRectangleCorner(p1, p2, hull.get(j), true);
197197
Point topRight = computeRectangleCorner(p1, p2, hull.get(j), false);
198198
bestRectangle = new Rectangle(bottomLeft, topRight, area);
199199
}
200200
}
201-
201+
202202
return bestRectangle;
203203
}
204-
204+
205205
/**
206206
* Finds the antipodal point for a given edge using rotating calipers.
207207
*/
208208
private static int findAntipodalPoint(List<Point> hull, int edgeStart) {
209209
int n = hull.size();
210210
int j = (edgeStart + 1) % n;
211-
211+
212212
Point p1 = hull.get(edgeStart);
213213
Point p2 = hull.get((edgeStart + 1) % n);
214-
214+
215215
while (true) {
216216
Point next = hull.get((j + 1) % n);
217217
double dist1 = distanceToLine(p1, p2, hull.get(j));
218218
double dist2 = distanceToLine(p1, p2, next);
219-
219+
220220
if (dist2 > dist1) {
221221
j = (j + 1) % n;
222222
} else {
223223
break;
224224
}
225225
}
226-
226+
227227
return j;
228228
}
229-
229+
230230
/**
231231
* Computes a corner of the bounding rectangle.
232232
*/
@@ -235,14 +235,14 @@ private static Point computeRectangleCorner(Point p1, Point p2, Point antipodal,
235235
int maxX = Math.max(Math.max(p1.x(), p2.x()), antipodal.x());
236236
int minY = Math.min(Math.min(p1.y(), p2.y()), antipodal.y());
237237
int maxY = Math.max(Math.max(p1.y(), p2.y()), antipodal.y());
238-
238+
239239
if (isBottomLeft) {
240240
return new Point(minX, minY);
241241
} else {
242242
return new Point(maxX, maxY);
243243
}
244244
}
245-
245+
246246
/**
247247
* Computes the Euclidean distance between two points.
248248
*/
@@ -251,27 +251,27 @@ private static double distance(Point p1, Point p2) {
251251
int dy = p2.y() - p1.y();
252252
return Math.sqrt(dx * dx + dy * dy);
253253
}
254-
254+
255255
/**
256256
* Computes the perpendicular distance from a point to a line defined by two points.
257257
*/
258258
private static double distanceToLine(Point lineStart, Point lineEnd, Point point) {
259259
int dx = lineEnd.x() - lineStart.x();
260260
int dy = lineEnd.y() - lineStart.y();
261-
261+
262262
if (dx == 0 && dy == 0) {
263263
return distance(lineStart, point);
264264
}
265-
265+
266266
int px = point.x() - lineStart.x();
267267
int py = point.y() - lineStart.y();
268-
268+
269269
double crossProduct = Math.abs(px * dy - py * dx);
270270
double lineLength = Math.sqrt(dx * dx + dy * dy);
271-
271+
272272
return crossProduct / lineLength;
273273
}
274-
274+
275275
/**
276276
* Ensures the hull points are in counter-clockwise order for rotating calipers.
277277
* The convex hull algorithm returns points sorted by natural order, but rotating calipers
@@ -281,7 +281,7 @@ private static List<Point> ensureCounterClockwiseOrder(List<Point> hull) {
281281
if (hull.size() <= 2) {
282282
return hull;
283283
}
284-
284+
285285
Point bottomMost = hull.get(0);
286286
int bottomIndex = 0;
287287
for (int i = 1; i < hull.size(); i++) {
@@ -291,23 +291,23 @@ private static List<Point> ensureCounterClockwiseOrder(List<Point> hull) {
291291
bottomIndex = i;
292292
}
293293
}
294-
294+
295295
List<Point> orderedHull = new ArrayList<>();
296296
for (int i = 0; i < hull.size(); i++) {
297297
orderedHull.add(hull.get((bottomIndex + i) % hull.size()));
298298
}
299-
299+
300300
if (orderedHull.size() >= 3) {
301301
Point p1 = orderedHull.get(0);
302302
Point p2 = orderedHull.get(1);
303303
Point p3 = orderedHull.get(2);
304-
304+
305305
if (Point.orientation(p1, p2, p3) < 0) {
306306
Collections.reverse(orderedHull);
307307
Collections.rotate(orderedHull, 1);
308308
}
309309
}
310-
310+
311311
return orderedHull;
312312
}
313313
}

0 commit comments

Comments
 (0)