From d8b1fcfc5d9715342ef08e55aad27f64d1a990a9 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 2 Mar 2024 02:45:06 -0500 Subject: [PATCH] Native Polygon Intersection --- src/geometry.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++ src/sprite_list.rs | 6 ++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/geometry.rs b/src/geometry.rs index b8906aa..3ea7a95 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -1,5 +1,66 @@ use pyo3::prelude::*; +pub fn are_polygons_intersecting_native( + poly_a: &Vec<(f32, f32)>, + poly_b: &Vec<(f32, f32)>, +) -> bool { + // If either polygon is empty, we should just return False + if poly_a.is_empty() || poly_b.is_empty() { + return false; + } + let polygons = [poly_a, poly_b]; + for polygon in &polygons { + for i1 in 0..polygon.len() { + let i2 = (i1 + 1) % polygon.len(); + let projection_1 = polygon[i1]; + let projection_2 = polygon[i2]; + + let normal = ( + projection_2.1 - projection_1.1, + projection_1.0 - projection_2.0, + ); + + let mut min_a: Option = None; + let mut max_a: Option = None; + let mut min_b: Option = None; + let mut max_b: Option = None; + + for point in polygons[0] { + let projected = normal.0 * point.0 + normal.1 * point.1; + match min_a { + Some(x) if projected < x => min_a = Some(projected), + Some(_x) => {} + None => min_a = Some(projected), + } + match max_a { + Some(x) if projected > x => max_a = Some(projected), + Some(_x) => {} + None => max_a = Some(projected), + } + } + + for point in polygons[1] { + let projected = normal.0 * point.0 + normal.1 * point.1; + match min_b { + Some(x) if projected < x => min_b = Some(projected), + Some(_x) => {} + None => min_b = Some(projected), + } + match max_b { + Some(x) if projected > x => max_b = Some(projected), + Some(_x) => {} + None => max_b = Some(projected), + } + } + + if max_a <= min_b || max_b <= min_a { + return false; + } + } + } + true +} + #[pyfunction] pub fn are_polygons_intersecting(poly_a: Vec<(f32, f32)>, poly_b: Vec<(f32, f32)>) -> bool { // If either polygon is empty, we should just return False diff --git a/src/sprite_list.rs b/src/sprite_list.rs index 64a30ce..89e2807 100644 --- a/src/sprite_list.rs +++ b/src/sprite_list.rs @@ -1,4 +1,4 @@ -use crate::geometry::are_polygons_intersecting; +use crate::geometry::are_polygons_intersecting_native; use crate::hitbox::{HitBox, RotatableHitBox}; use pyo3::prelude::*; @@ -72,7 +72,7 @@ pub fn check_for_collision_with_list( panic!("unknown hitbox type"); }; - let check_2 = are_polygons_intersecting(main_points.to_vec(), other_points); + let check_2 = are_polygons_intersecting_native(&main_points, &other_points); if check_2 { final_sprites.push(sprite2.to_object(py)); @@ -149,7 +149,7 @@ pub fn check_for_collision_with_lists( panic!("unknown hitbox type"); }; - let check_2 = are_polygons_intersecting(main_points.to_vec(), other_points); + let check_2 = are_polygons_intersecting_native(&main_points, &other_points); if check_2 { final_sprites.push(sprite2.to_object(py));