Skip to content

Commit 2cbaca7

Browse files
committed
Implement Graham Scan in Rust
1 parent c6ff7bb commit 2cbaca7

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#[derive(Debug)]
2+
struct Point {
3+
x: f64,
4+
y: f64,
5+
}
6+
7+
// Check if the turn of the points is counter clockwise.
8+
fn counter_clockwise(a: &Point, b: &Point, c: &Point) -> bool {
9+
((b.x - a.x) * (c.y - a.y)) >= ((b.y - a.y) * (c.x - a.x))
10+
}
11+
12+
// Calculate the polar angle of a point relative to a reference point.
13+
fn polar_angle(reference: &Point, point: &Point) -> f64 {
14+
(point.y - point.y).atan2(point.x - reference.x)
15+
}
16+
17+
fn graham_scan(mut points: Vec<Point>) -> Vec<Point> {
18+
// First, sort the points so the one with the lowest y-coordinate comes first (the pivot)
19+
sort_based_on_lowest_coordinate(&mut points);
20+
21+
// Take ownership of the pivot point
22+
let pivot: Point = points.remove(0);
23+
24+
// Sort all points based on the angle between the pivot point and itself
25+
&mut points
26+
.sort_by(|a, b| (polar_angle(a, &pivot).partial_cmp(&polar_angle(b, &pivot))).unwrap());
27+
28+
// Reinsert the pivot point
29+
points.insert(0, pivot);
30+
31+
let n = points.len();
32+
let mut m = 1;
33+
34+
// Move the points of the hull towards the beginning of the vector.
35+
for mut i in 2..n {
36+
while counter_clockwise(&points[m - 1], &points[m], &points[i]) {
37+
if m > 1 {
38+
m -= 1;
39+
} else if m == i {
40+
break;
41+
} else {
42+
i += 1;
43+
}
44+
}
45+
46+
m += 1;
47+
points.swap(i, m);
48+
}
49+
50+
// Remove all non-hull points from the vector
51+
points.truncate(m + 2);
52+
points
53+
}
54+
55+
fn sort_based_on_lowest_coordinate(points: &mut Vec<Point>) {
56+
points.sort_unstable_by(|a, b| (a.x).partial_cmp(&b.x).unwrap());
57+
points.sort_by(|a, b| (a.y).partial_cmp(&b.y).unwrap());
58+
}
59+
60+
fn main() {
61+
let points = vec![
62+
Point { x: 1.0, y: 3.0 },
63+
Point { x: 2.0, y: 4.0 },
64+
Point { x: 4.0, y: 0.0 },
65+
Point { x: 1.0, y: 0.0 },
66+
Point { x: 0.0, y: 2.0 },
67+
Point { x: 2.0, y: 2.0 },
68+
Point { x: 3.0, y: 4.0 },
69+
Point { x: 3.0, y: 1.0 },
70+
];
71+
72+
let hull_points = graham_scan(points);
73+
println!("{:#?}", hull_points);
74+
}

0 commit comments

Comments
 (0)