jagua_rs/collision_detection/hazards/
hazard.rs1use crate::collision_detection::narrow_phase::{EdgeBoxes, EdgeChains, EdgeSet};
2use crate::geometry::DTransformation;
3use crate::geometry::geo_enums::GeoPosition;
4use crate::geometry::primitives::{Edge, Rect, SPolygon};
5use slotmap::new_key_type;
6use std::fmt::Debug;
7use std::hash::Hash;
8use std::sync::Arc;
9
10new_key_type! {
11 pub struct HazKey;
13
14 pub struct PItemKey;
16}
17
18#[derive(Clone, Debug)]
22pub struct Hazard<E = BasicHazardEntity> {
23 entity: E,
24 shape: Arc<SPolygon>,
25 geometry: HazardGeometry,
26}
27
28impl<E: HazardEntity> Hazard<E> {
29 #[must_use]
30 pub fn new(entity: E, shape: Arc<SPolygon>) -> Self {
31 let geometry = HazardGeometry::new(&shape, entity.scope());
32 Self {
33 entity,
34 shape,
35 geometry,
36 }
37 }
38}
39
40impl<E: Copy> Hazard<E> {
41 #[must_use]
43 pub fn entity(&self) -> E {
44 self.entity
45 }
46
47 #[must_use]
49 pub fn shape(&self) -> &Arc<SPolygon> {
50 &self.shape
51 }
52
53 pub(crate) fn geometry(&self) -> &HazardGeometry {
54 &self.geometry
55 }
56}
57
58impl<E> EdgeSet for Hazard<E> {
59 #[inline(always)]
60 #[allow(clippy::inline_always)] fn any_edge_overlapping(&self, r: Rect, f: impl FnMut(&Edge) -> bool) -> bool {
62 match &self.geometry {
63 HazardGeometry::Interior(boxes) => boxes.any_edge_overlapping(&self.shape, r, f),
64 HazardGeometry::Exterior { chains, .. } => chains.any_edge_overlapping(r, f),
65 }
66 }
67}
68
69#[derive(Clone, Debug)]
72pub(crate) enum HazardGeometry {
73 Interior(EdgeBoxes),
74 Exterior {
76 chains: Arc<EdgeChains>,
77 is_rect: bool,
79 },
80}
81
82impl HazardGeometry {
83 #[allow(clippy::float_cmp)] fn new(shape: &SPolygon, scope: GeoPosition) -> Self {
85 match scope {
86 GeoPosition::Interior => HazardGeometry::Interior(EdgeBoxes::new(shape)),
87 GeoPosition::Exterior => {
88 let bbox = shape.bbox;
89 let is_rect = shape.n_vertices() == 4
90 && shape.vertices.iter().all(|p| {
91 (p.0 == bbox.x_min || p.0 == bbox.x_max)
92 && (p.1 == bbox.y_min || p.1 == bbox.y_max)
93 });
94 HazardGeometry::Exterior {
95 chains: Arc::new(EdgeChains::new(shape)),
96 is_rect,
97 }
98 }
99 }
100 }
101}
102
103pub trait HazardEntity: Copy + Eq + Hash + Debug {
109 fn scope(&self) -> GeoPosition;
112}
113
114#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
115pub enum BasicHazardEntity {
118 PlacedItem {
120 id: usize,
121 dt: DTransformation,
122 pk: PItemKey,
123 },
124 Exterior,
126 Hole { idx: usize },
128 InferiorQualityZone { quality: usize, idx: usize },
130}
131
132impl HazardEntity for BasicHazardEntity {
133 fn scope(&self) -> GeoPosition {
134 match self {
135 BasicHazardEntity::PlacedItem { .. }
136 | BasicHazardEntity::Hole { .. }
137 | BasicHazardEntity::InferiorQualityZone { .. } => GeoPosition::Interior,
138 BasicHazardEntity::Exterior => GeoPosition::Exterior,
139 }
140 }
141}