jagua_rs/collision_detection/
hazard_filter.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use itertools::Itertools;

use crate::collision_detection::hazard::Hazard;
use crate::collision_detection::hazard::HazardEntity;

/// Trait that allows for ignoring out specific hazards.
/// Enables querying the `CDEngine` only for relevant hazards.
pub trait HazardFilter {
    fn is_irrelevant(&self, entity: &HazardEntity) -> bool;
}

/// Returns the entities that are deemed irrelevant by the specified `HazardFilter`.
pub fn generate_irrelevant_hazards<'a>(
    filter: &impl HazardFilter,
    hazards: impl Iterator<Item = &'a Hazard>,
) -> Vec<HazardEntity> {
    hazards
        .filter_map(|h| match filter.is_irrelevant(&h.entity) {
            true => Some(h.entity),
            false => None,
        })
        .collect_vec()
}

/// Deems all hazards induced by the `Bin` as irrelevant.
#[derive(Clone)]
pub struct BinHazardFilter;

/// Deems hazards induced by `QualityZone`s above a cutoff quality as irrelevant.
#[derive(Clone, Debug)]
pub struct QZHazardFilter(pub usize);

/// Deems hazards induced by specific entities as irrelevant.
pub struct EntityHazardFilter(pub Vec<HazardEntity>);

/// Combines multiple `HazardFilter`s into a single filter.
pub struct CombinedHazardFilter<'a> {
    pub filters: Vec<Box<&'a dyn HazardFilter>>,
}

impl HazardFilter for BinHazardFilter {
    fn is_irrelevant(&self, entity: &HazardEntity) -> bool {
        match entity {
            HazardEntity::PlacedItem { .. } => false,
            HazardEntity::BinExterior => true,
            HazardEntity::BinHole { .. } => true,
            HazardEntity::InferiorQualityZone { .. } => true,
        }
    }
}

impl<'a> HazardFilter for CombinedHazardFilter<'a> {
    fn is_irrelevant(&self, entity: &HazardEntity) -> bool {
        self.filters.iter().any(|f| f.is_irrelevant(entity))
    }
}

impl HazardFilter for EntityHazardFilter {
    fn is_irrelevant(&self, entity: &HazardEntity) -> bool {
        self.0.contains(entity)
    }
}

impl HazardFilter for QZHazardFilter {
    fn is_irrelevant(&self, entity: &HazardEntity) -> bool {
        match entity {
            HazardEntity::InferiorQualityZone { quality, .. } => *quality >= self.0,
            _ => false,
        }
    }
}