Skip to content

Commit 0b9c9c5

Browse files
committed
Implement Graham Scan in Rust
1 parent 8b50c0a commit 0b9c9c5

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed
3.98 MB
Binary file not shown.
Lines changed: 73 additions & 0 deletions
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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions
2424
[import:4-6, lang:"python"](code/python/grahamScan.py)
2525
{% sample lang="java" %}
2626
[import:27-29, lang:"java"](code/java/GrahamScan.java)
27+
{% sample lang="rs" %}
28+
[import:7-10, lang: "rust"](code/rust/graham_scan.rs)
2729
{% endmethod %}
2830

2931
If the output of this function is 0, the points are collinear.
@@ -50,6 +52,8 @@ In the end, the code should look something like this:
5052
[import:14-27, lang:"python"](code/python/grahamScan.py)
5153
{% sample lang="java" %}
5254
[import:35-70, lang:"java"](code/java/GrahamScan.java)
55+
{% sample lang="rs" %}
56+
[import:17-53, lang: "rust"](code/rust/graham_scan.rs)
5357
{% endmethod %}
5458

5559
### Bibliography
@@ -71,6 +75,8 @@ In the end, the code should look something like this:
7175
[import, lang:"python"](code/python/grahamScan.py)
7276
{% sample lang="java" %}
7377
[import, lang:"java"](code/java/GrahamScan.java)
78+
{% sample lang="rs" %}
79+
[import, lang: "rust"](code/rust/graham_scan.rs)
7480
{% endmethod %}
7581

7682
<script>

0 commit comments

Comments
 (0)