Skip to content

Commit 4bea1d1

Browse files
committed
Native polygon intersection function to accept references that pyfunction cannot
1 parent 2e04341 commit 4bea1d1

2 files changed

Lines changed: 64 additions & 3 deletions

File tree

src/geometry.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,66 @@
11
use pyo3::prelude::*;
22

3+
pub fn are_polygons_intersecting_native(
4+
poly_a: &Vec<(f32, f32)>,
5+
poly_b: &Vec<(f32, f32)>,
6+
) -> bool {
7+
// If either polygon is empty, we should just return False
8+
if poly_a.is_empty() || poly_b.is_empty() {
9+
return false;
10+
}
11+
let polygons = [poly_a, poly_b];
12+
for polygon in &polygons {
13+
for i1 in 0..polygon.len() {
14+
let i2 = (i1 + 1) % polygon.len();
15+
let projection_1 = polygon[i1];
16+
let projection_2 = polygon[i2];
17+
18+
let normal = (
19+
projection_2.1 - projection_1.1,
20+
projection_1.0 - projection_2.0,
21+
);
22+
23+
let mut min_a: Option<f32> = None;
24+
let mut max_a: Option<f32> = None;
25+
let mut min_b: Option<f32> = None;
26+
let mut max_b: Option<f32> = None;
27+
28+
for point in polygons[0] {
29+
let projected = normal.0 * point.0 + normal.1 * point.1;
30+
match min_a {
31+
Some(x) if projected < x => min_a = Some(projected),
32+
Some(_x) => {}
33+
None => min_a = Some(projected),
34+
}
35+
match max_a {
36+
Some(x) if projected > x => max_a = Some(projected),
37+
Some(_x) => {}
38+
None => max_a = Some(projected),
39+
}
40+
}
41+
42+
for point in polygons[1] {
43+
let projected = normal.0 * point.0 + normal.1 * point.1;
44+
match min_b {
45+
Some(x) if projected < x => min_b = Some(projected),
46+
Some(_x) => {}
47+
None => min_b = Some(projected),
48+
}
49+
match max_b {
50+
Some(x) if projected > x => max_b = Some(projected),
51+
Some(_x) => {}
52+
None => max_b = Some(projected),
53+
}
54+
}
55+
56+
if max_a <= min_b || max_b <= min_a {
57+
return false;
58+
}
59+
}
60+
}
61+
true
62+
}
63+
364
#[pyfunction]
465
pub fn are_polygons_intersecting(poly_a: Vec<(f32, f32)>, poly_b: Vec<(f32, f32)>) -> bool {
566
// If either polygon is empty, we should just return False

src/sprite_list.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::geometry::are_polygons_intersecting;
1+
use crate::geometry::are_polygons_intersecting_native;
22
use crate::hitbox::{HitBox, RotatableHitBox};
33
use pyo3::prelude::*;
44

@@ -72,7 +72,7 @@ pub fn check_for_collision_with_list(
7272
panic!("unknown hitbox type");
7373
};
7474

75-
let check_2 = are_polygons_intersecting(main_points.to_vec(), other_points);
75+
let check_2 = are_polygons_intersecting_native(&main_points, &other_points);
7676

7777
if check_2 {
7878
final_sprites.push(sprite2.to_object(py));
@@ -149,7 +149,7 @@ pub fn check_for_collision_with_lists(
149149
panic!("unknown hitbox type");
150150
};
151151

152-
let check_2 = are_polygons_intersecting(main_points.to_vec(), other_points);
152+
let check_2 = are_polygons_intersecting_native(&main_points, &other_points);
153153

154154
if check_2 {
155155
final_sprites.push(sprite2.to_object(py));

0 commit comments

Comments
 (0)