Skip to content

Commit cfb16e1

Browse files
committed
graham scan convux hull
1 parent 077625f commit cfb16e1

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

Math/convuxhull/grahamscan.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include <iostream>
2+
#include <stack>
3+
#include <stdlib.h>
4+
using namespace std;
5+
6+
struct Point
7+
{
8+
int x, y;
9+
};
10+
11+
// A globle point needed for sorting points with reference
12+
// to the first point Used in compare function of qsort()
13+
Point p0;
14+
15+
// A utility function to find next to top in a stack
16+
Point nextToTop(stack<Point> &S)
17+
{
18+
Point p = S.top();
19+
S.pop();
20+
Point res = S.top();
21+
S.push(p);
22+
return res;
23+
}
24+
25+
// A utility function to swap two points
26+
int swap(Point &p1, Point &p2)
27+
{
28+
Point temp = p1;
29+
p1 = p2;
30+
p2 = temp;
31+
}
32+
33+
// A utility function to return square of distance
34+
// between p1 and p2
35+
int distSq(Point p1, Point p2)
36+
{
37+
return (p1.x - p2.x)*(p1.x - p2.x) +
38+
(p1.y - p2.y)*(p1.y - p2.y);
39+
}
40+
41+
// To find orientation of ordered triplet (p, q, r).
42+
// The function returns following values
43+
// 0 --> p, q and r are colinear
44+
// 1 --> Clockwise
45+
// 2 --> Counterclockwise
46+
int orientation(Point p, Point q, Point r)
47+
{
48+
int val = (q.y - p.y) * (r.x - q.x) -
49+
(q.x - p.x) * (r.y - q.y);
50+
51+
if (val == 0) return 0; // colinear
52+
return (val > 0)? 1: 2; // clock or counterclock wise
53+
}
54+
55+
// A function used by library function qsort() to sort an array of
56+
// points with respect to the first point
57+
int compare(const void *vp1, const void *vp2)
58+
{
59+
Point *p1 = (Point *)vp1;
60+
Point *p2 = (Point *)vp2;
61+
62+
// Find orientation
63+
int o = orientation(p0, *p1, *p2);
64+
if (o == 0)
65+
return (distSq(p0, *p2) >= distSq(p0, *p1))? -1 : 1;
66+
67+
return (o == 2)? -1: 1;
68+
}
69+
70+
// Prints convex hull of a set of n points.
71+
void convexHull(Point points[], int n)
72+
{
73+
// Find the bottommost point
74+
int ymin = points[0].y, min = 0;
75+
for (int i = 1; i < n; i++)
76+
{
77+
int y = points[i].y;
78+
79+
// Pick the bottom-most or chose the left
80+
// most point in case of tie
81+
if ((y < ymin) || (ymin == y &&
82+
points[i].x < points[min].x))
83+
ymin = points[i].y, min = i;
84+
}
85+
86+
// Place the bottom-most point at first position
87+
swap(points[0], points[min]);
88+
89+
// Sort n-1 points with respect to the first point.
90+
// A point p1 comes before p2 in sorted ouput if p2
91+
// has larger polar angle (in counterclockwise
92+
// direction) than p1
93+
p0 = points[0];
94+
qsort(&points[1], n-1, sizeof(Point), compare);
95+
96+
// If two or more points make same angle with p0,
97+
// Remove all but the one that is farthest from p0
98+
// Remember that, in above sorting, our criteria was
99+
// to keep the farthest point at the end when more than
100+
// one points have same angle.
101+
int m = 1; // Initialize size of modified array
102+
for (int i=1; i<n; i++)
103+
{
104+
// Keep removing i while angle of i and i+1 is same
105+
// with respect to p0
106+
while (i < n-1 && orientation(p0, points[i],
107+
points[i+1]) == 0)
108+
i++;
109+
110+
111+
points[m] = points[i];
112+
m++; // Update size of modified array
113+
}
114+
115+
// If modified array of points has less than 3 points,
116+
// convex hull is not possible
117+
if (m < 3) return;
118+
119+
// Create an empty stack and push first three points
120+
// to it.
121+
stack<Point> S;
122+
S.push(points[0]);
123+
S.push(points[1]);
124+
S.push(points[2]);
125+
126+
// Process remaining n-3 points
127+
for (int i = 3; i < m; i++)
128+
{
129+
// Keep removing top while the angle formed by
130+
// points next-to-top, top, and points[i] makes
131+
// a non-left turn
132+
while (orientation(nextToTop(S), S.top(), points[i]) != 2)
133+
S.pop();
134+
S.push(points[i]);
135+
}
136+
137+
// Now stack has the output points, print contents of stack
138+
while (!S.empty())
139+
{
140+
Point p = S.top();
141+
cout << "(" << p.x << ", " << p.y <<")" << endl;
142+
S.pop();
143+
}
144+
}
145+
146+
int main()
147+
{
148+
Point points[] = {{0, 3}, {1, 1}, {2, 2}, {4, 4},
149+
{0, 0}, {1, 2}, {3, 1}, {3, 3}};
150+
int n = sizeof(points)/sizeof(points[0]);
151+
convexHull(points, n);
152+
return 0;
153+
}
154+
155+
/*
156+
(0, 3)
157+
(4, 4)
158+
(3, 1)
159+
(0, 0)
160+
161+
*/

0 commit comments

Comments
 (0)