22
22
* public void setRightMostLowestPoint(MyPoint p) {<br>
23
23
* rightMostLowestPoint = p;<br>
24
24
* }<br>
25
- * \ @Override public int compareTo(MyPoint o) {<br>
25
+ * \@Override public int compareTo(MyPoint o) {<br>
26
26
* // Implement it to compare this point with point o<br>
27
27
* // angularly along the x-axis with rightMostLowestPoint<br>
28
28
* // as the center, as shown in Figure 22.10b. By implementing<br>
@@ -67,72 +67,99 @@ public static void main(String[] args) {
67
67
}
68
68
69
69
public static ArrayList <MyPoint > getConvexHull (double [][] s ) {
70
- /* Find Lowest and Rightest Point */
71
- double yMin = s [ 0 ][ 1 ];
72
- int minPos = 0 ;
73
- // Find the bottom most point
70
+ /* Grahams Algorithm:
71
+ Step 1: Given a list of points S, select the rightmost lowest.
72
+ */
73
+ double [] lowestRightMostPt = s [ 0 ]; // initialize to first point
74
74
for (int i = 1 ; i < s .length ; i ++) {
75
- double y = s [i ][ 1 ];
75
+ double [] nextPt = s [i ];
76
76
// Pick the bottom-most or chose the right
77
77
// most point in case of tie
78
- if ((y < yMin ) || (yMin == y && s [i ][0 ] > s [minPos ][0 ])) {
79
- yMin = s [i ][1 ];
80
- minPos = i ;
81
-
82
- }
78
+ lowestRightMostPt = getLowestRightMostPoint (lowestRightMostPt , nextPt );
83
79
}
84
- // Swamp the bottom-most point for first position
85
- double [] temp = s [0 ];
86
- s [0 ] = s [minPos ];
87
- s [minPos ] = temp ;
88
- MyPoint rightMostLowestPoint = new MyPoint (s [0 ][0 ], s [0 ][1 ]);
89
- ArrayList <MyPoint > rawPoints = new ArrayList <>();
90
- rawPoints .add (rightMostLowestPoint );
91
- // Create array of MyPoint objects and set rightMostLowestPoint
92
- for (int i = 1 ; i < s .length ; i ++) {
93
- MyPoint pt = new MyPoint (s [i ][0 ], s [i ][1 ]);
94
- pt .setRightMostLowestPoint (rightMostLowestPoint );
95
- rawPoints .add (pt );
96
- }
97
- ArrayList <MyPoint > cleanedPoints = new ArrayList <>();
98
- cleanedPoints .add (rightMostLowestPoint );
99
- //Clean points with same angle
100
- for (int i = 1 ; i < rawPoints .size () - 1 ; i ++) {
101
- // Only add points where the angle of p[i] and p[i+1] is NOT the same with respect to p0
102
- if (orientation (rightMostLowestPoint , rawPoints .get (i ), rawPoints .get (i + 1 )) != 0 ) {
103
- cleanedPoints .add (rawPoints .get (i ));
104
- }
80
+ MyPoint rightMostLowestPoint = new MyPoint (lowestRightMostPt [0 ], lowestRightMostPt [1 ]);
81
+ /*
82
+ Step 2: Sort the points in S angularly along the x-axis with p0 as the
83
+ center, as shown in Figure 22.10b. If there is a tie and two points have
84
+ the same angle, discard the one that is closer to p0. The points in S are
85
+ now sorted as p0, p1, p2, ..., pn-1.
86
+ */
87
+ // For Step 2 - We use Comparable interface to sort the points to simplify coding.
88
+ ArrayList <MyPoint > pointsList = new ArrayList <>();
89
+ for (double [] pt : s ) {
90
+ MyPoint p = new MyPoint (pt [0 ], pt [1 ]);
91
+ p .setRightMostLowestPoint (rightMostLowestPoint );
92
+ pointsList .add (p );
105
93
}
94
+
106
95
// If modified array of points has less than 3 points,
107
96
// convex hull is not possible
108
- if (cleanedPoints .size () < 3 ) {
97
+ if (pointsList .size () < 3 ) {
109
98
throw new RuntimeException ("Graham's Algorithm for ConvexHull requires " +
110
99
"at least 3 points with different angles..." );
111
100
}
112
- Collections .sort (cleanedPoints );
101
+ Collections .sort (pointsList );
113
102
// Graham scan
114
103
// Create an empty stack and push first three points to it
104
+ /* Step 3: Push p0, p1, and p2 into stack H. (After the algorithm finishes,
105
+ H contains all the points in the convex hull.)
106
+ i = 3;
107
+ while (i < n) {
108
+ Let t1 and t2 be the top first and second element in stack H;
109
+ if (pi is on the left side of the direct line from t2 to t1) {
110
+ Push pi to H;
111
+ i++; // Consider the next point in S.
112
+ }
113
+ else
114
+ Pop the top element off stack H.
115
+ }
116
+ Step 5: The points in H form a convex hull.
117
+ */
115
118
Stack <MyPoint > stack = new Stack <>();
116
- int m = cleanedPoints .size ();
117
- stack .push (cleanedPoints .get (0 )); // p0 (lowest and rightest point)
118
- stack .push (cleanedPoints .get (1 )); // p1
119
- stack .push (cleanedPoints .get (2 )); // p2
119
+ int m = pointsList .size ();
120
+ MyPoint p0 = pointsList .get (0 );
121
+ MyPoint p1 = pointsList .get (1 );
122
+ MyPoint p2 = pointsList .get (2 );
123
+ stack .push (p0 );
124
+ stack .push (p1 );
125
+ stack .push (p2 );
120
126
// Process remaining n-3 points
121
- for (int i = 3 ; i < m ; i ++) {
127
+ int i = 3 ;
128
+ while (i < m ) {
122
129
// Keep removing top while the angle formed by
123
130
// points next-to-top, top, and points[i] makes
124
131
// a non-left turn
125
- while (orientation (nextToTop (stack ), stack .peek (), cleanedPoints .get (i )) != 2 ) {
126
- stack .pop ();
127
- stack .push (cleanedPoints .get (i ));
132
+ MyPoint p3 = pointsList .get (i );
133
+ int orientation = orientation (p2 , p1 , p3 );
134
+ if (orientation == 2 ) {
135
+ stack .push (p3 );
136
+ } else if (orientation == 1 ) {
137
+ stack .pop (); // pop p2
138
+ stack .push (p3 );
139
+ } else {
140
+ stack .pop (); // pop p2
128
141
}
142
+ p2 = stack .peek ();
143
+ p1 = stack .get (stack .size () - 2 );
144
+ i ++;
129
145
130
146
}
131
147
// Now stack has the output points, print contents of stack
132
-
133
148
return new ArrayList <>(stack );
134
149
}
135
150
151
+
152
+ static double [] getLowestRightMostPoint (double [] pt1 , double [] pt2 ) {
153
+ if (pt2 [1 ] < pt1 [1 ]) {
154
+ return pt2 ;
155
+ } else if (pt2 [1 ] == pt1 [1 ]) {
156
+ if (pt2 [0 ] > pt1 [0 ]) {
157
+ return pt2 ;
158
+ }
159
+ }
160
+ return pt1 ;
161
+ }
162
+
136
163
/**
137
164
* To find orientation of ordered triplet (p, q, r).
138
165
*
@@ -159,17 +186,6 @@ static double distSq(MyPoint p1, MyPoint p2) {
159
186
(p1 .y - p2 .y ) * (p1 .y - p2 .y );
160
187
}
161
188
162
- /**
163
- * A utility function to find next to top in a stack
164
- */
165
- static MyPoint nextToTop (Stack <MyPoint > s ) {
166
- MyPoint p = s .pop ();
167
- MyPoint res = s .peek ();
168
- s .push (p );
169
- return res ;
170
- }
171
-
172
-
173
189
private static class MyPoint implements Comparable <MyPoint > {
174
190
double x , y ;
175
191
MyPoint rightMostLowestPoint ;
@@ -195,15 +211,18 @@ public int compareTo(MyPoint o) {
195
211
// Find orientation
196
212
int orientation = orientation (rightMostLowestPoint , this , o );
197
213
if (orientation == 0 ) {
198
- return distSq (rightMostLowestPoint , o ) >= distSq (rightMostLowestPoint , this ) ? -1 : 1 ;
214
+ double distSqObj1 = distSq (rightMostLowestPoint , this );
215
+ double distSqObj2 = distSq (rightMostLowestPoint , o );
216
+ return Double .compare (distSqObj1 , distSqObj2 );
199
217
}
200
- return (orientation == 2 ) ? - 1 : 1 ;
218
+ return (orientation == 2 ) ? 1 : - 1 ;
201
219
}
202
220
203
221
@ Override
204
222
public String toString () {
205
223
return "(" + x + ", " + y + ")" ;
206
224
}
225
+
207
226
}
208
227
209
228
}
0 commit comments