rust/hwphysics/src/grid.rs
author alfadur
Thu, 27 Jan 2022 03:51:13 +0300
changeset 15828 44b49f255e31
parent 15827 64b0a5cead86
child 15981 5ba4d3a0c3eb
permissions -rw-r--r--
add type safe power of two sizes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     1
use crate::{
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     2
    collision::{fppoint_round, CircleBounds, DetectedCollisions},
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     3
    common::GearId,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     4
};
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     5
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     6
use fpnum::FPPoint;
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
     7
use integral_geometry::{GridIndex, Point, PotSize};
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     8
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
     9
struct GridBin {
15827
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    10
    refs: Vec<GearId>,
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    11
    entries: Vec<CircleBounds>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    12
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    13
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    14
impl GridBin {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    15
    fn new() -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    16
        Self {
15827
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    17
            refs: vec![],
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    18
            entries: vec![],
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    19
        }
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    20
    }
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    21
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    22
    fn add(&mut self, gear_id: GearId, bounds: &CircleBounds) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    23
        self.refs.push(gear_id);
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    24
        self.entries.push(*bounds);
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    25
    }
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    26
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    27
    fn remove(&mut self, gear_id: GearId) -> bool {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    28
        if let Some(pos) = self.refs.iter().position(|id| *id == gear_id) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    29
            self.refs.swap_remove(pos);
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    30
            self.entries.swap_remove(pos);
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    31
            true
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    32
        } else {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    33
            false
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    34
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    35
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    36
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    37
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    38
const GRID_BIN_SIZE: usize = 128;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    39
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    40
pub struct Grid {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    41
    bins: Vec<GridBin>,
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    42
    space_size: PotSize,
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    43
    bins_count: PotSize,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    44
    index: GridIndex,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    45
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    46
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    47
impl Grid {
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    48
    pub fn new(size: PotSize) -> Self {
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    49
        let bins_count =
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    50
            PotSize::new(size.width() / GRID_BIN_SIZE, size.height() / GRID_BIN_SIZE).unwrap();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    51
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    52
        Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    53
            bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    54
            space_size: size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    55
            bins_count,
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    56
            index: PotSize::square(GRID_BIN_SIZE).unwrap().to_grid_index(),
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    57
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    58
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    59
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    60
    fn linear_bin_index(&self, index: Point) -> usize {
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    61
        self.bins_count
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    62
            .linear_index(index.x as usize, index.y as usize)
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    63
    }
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    64
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    65
    fn bin_index(&self, position: &FPPoint) -> Point {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    66
        self.index.map(fppoint_round(position))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    67
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    68
15261
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    69
    fn get_bin(&mut self, index: Point) -> &mut GridBin {
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    70
        let index = self.linear_bin_index(index);
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    71
        &mut self.bins[index]
15261
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    72
    }
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    73
15757
c7332c7f64cd remove crash from collision
alfadur
parents: 15756
diff changeset
    74
    fn try_get_bin(&mut self, index: Point) -> Option<&mut GridBin> {
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    75
        let index = self.linear_bin_index(index);
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
    76
        self.bins.get_mut(index)
15757
c7332c7f64cd remove crash from collision
alfadur
parents: 15756
diff changeset
    77
    }
c7332c7f64cd remove crash from collision
alfadur
parents: 15756
diff changeset
    78
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    79
    fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin {
15261
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    80
        self.get_bin(self.bin_index(position))
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    81
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    82
15827
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    83
    pub fn insert(&mut self, gear_id: GearId, bounds: &CircleBounds) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    84
        self.lookup_bin(&bounds.center).add(gear_id, bounds);
15261
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    85
    }
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    86
15827
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    87
    fn remove_all(&mut self, gear_id: GearId) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    88
        for bin in &mut self.bins {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    89
            if bin.remove(gear_id) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    90
                break;
15757
c7332c7f64cd remove crash from collision
alfadur
parents: 15756
diff changeset
    91
            }
15261
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15120
diff changeset
    92
        }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    93
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
    94
15827
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    95
    pub fn remove(&mut self, gear_id: GearId, bounds: Option<&CircleBounds>) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    96
        if let Some(bounds) = bounds {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    97
            if !self.lookup_bin(&bounds.center).remove(gear_id) {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    98
                self.remove_all(gear_id);
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
    99
            }
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
   100
        } else {
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
   101
            self.remove_all(gear_id);
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
   102
        }
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
   103
    }
64b0a5cead86 use grid only for static gears
alfadur
parents: 15757
diff changeset
   104
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
   105
    pub fn check_collisions(&self, collisions: &mut DetectedCollisions) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
   106
        for bin in &self.bins {
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15827
diff changeset
   107
            for (index, bounds) in bin.entries.iter().enumerate() {}
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
   108
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
   109
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14716
diff changeset
   110
}