Skip to content

Commit 36ec677

Browse files
committed
Implement Graham Scan in Rust
1 parent afcaf4d commit 36ec677

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed
3.98 MB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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 = 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 + 1);
52+
points
53+
}
54+
55+
fn sort_based_on_lowest_coordinate(points: &mut Vec<Point>) {
56+
points.sort_unstable_by(|a, b| (a.y).partial_cmp(&b.y).unwrap());
57+
}
58+
59+
fn main() {
60+
let points = vec![
61+
Point { x: 1.0, y: 3.0 },
62+
Point { x: 2.0, y: 4.0 },
63+
Point { x: 4.0, y: 0.0 },
64+
Point { x: 1.0, y: 0.0 },
65+
Point { x: 0.0, y: 2.0 },
66+
Point { x: 2.0, y: 2.0 },
67+
Point { x: 3.0, y: 4.0 },
68+
Point { x: 3.0, y: 1.0 },
69+
];
70+
71+
let hull_points = graham_scan(points);
72+
println!("{:#?}", hull_points);
73+
}

contents/graham_scan/graham_scan.md

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions
2828
[import:27-29, lang:"java"](code/java/GrahamScan.java)
2929
{% sample lang="cpp" %}
3030
[import:10-12, lang="cpp"](code/c++/graham_scan.cpp)
31+
{% sample lang="rs" %}
32+
[import:7-10, lang: "rust"](code/rust/graham_scan.rs)
3133
{% endmethod %}
3234

3335
If the output of this function is 0, the points are collinear.
@@ -58,6 +60,8 @@ In the end, the code should look something like this:
5860
[import:35-70, lang:"java"](code/java/GrahamScan.java)
5961
{% sample lang="cpp" %}
6062
[import:14-47, lang="cpp"](code/c++/graham_scan.cpp)
63+
{% sample lang="rs" %}
64+
[import:17-53, lang: "rust"](code/rust/graham_scan.rs)
6165
{% endmethod %}
6266

6367
### Bibliography
@@ -83,6 +87,8 @@ In the end, the code should look something like this:
8387
[import, lang:"java"](code/java/GrahamScan.java)
8488
{% sample lang="cpp" %}
8589
[import, lang="cpp"](code/c++/graham_scan.cpp)
90+
{% sample lang="rs" %}
91+
[import, lang: "rust"](code/rust/graham_scan.rs)
8692
{% endmethod %}
8793

8894
<script>

0 commit comments

Comments
 (0)