Skip to content

Commit

Permalink
voxel: Add explicit connections to code
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondraceq committed Nov 2, 2023
1 parent f1b0a7a commit 80ea26f
Show file tree
Hide file tree
Showing 15 changed files with 627 additions and 38 deletions.
14 changes: 9 additions & 5 deletions softwareComponents/voxelReconfig/src/atoms/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,17 @@ impl Rotation {
}
}

pub fn rotate_dir(&self, dir: Direction) -> Direction {
let result_is_positive = if dir.axis() == self.axis() {
dir.is_positive()
pub fn dir_is_positive_inverted(&self, dir: Direction) -> bool {
if dir.axis() == self.axis() {
false
} else {
let is_next_axis = dir.axis() == self.axis().next_axis();
is_next_axis ^ self.angle().is_positive() ^ dir.is_positive()
};
is_next_axis ^ self.angle().is_positive()
}
}

pub fn rotate_dir(&self, dir: Direction) -> Direction {
let result_is_positive = dir.is_positive() ^ self.dir_is_positive_inverted(dir);
let result = Direction::new_with(self.rotate_axis(dir.axis()), result_is_positive);

debug_assert_eq!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub enum Heuristic {
}

impl Heuristic {
pub fn get_fn<'a, TWorld>(self, goal: &TWorld) -> Box<dyn FnMut(&TWorld) -> usize + 'a>
pub fn get_fn<'a, TWorld>(self, goal: &TWorld) -> Box<dyn 'a + FnMut(&TWorld) -> usize>
where
TWorld: 'a + NormVoxelWorld + Eq + std::hash::Hash,
TWorld::IndexType: num::Integer + std::hash::Hash,
Expand Down
8 changes: 3 additions & 5 deletions softwareComponents/voxelReconfig/src/voxel_world/centered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,9 @@ where
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(
self.world()
.all_voxels()
.map(|(orig_pos, voxel)| (self.get_new_pos(orig_pos), voxel)),
)
self.world()
.all_voxels()
.map(|(orig_pos, voxel)| (self.get_new_pos(orig_pos), voxel))
}

fn get_voxel(&self, pos: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<TIndex: MapVoxelWorldIndex> VoxelWorld for MapVoxelWorld<TIndex> {
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(self.data.iter().map(|(&OrdPos(pos), &voxel)| (pos, voxel)))
self.data.iter().map(|(&OrdPos(pos), &voxel)| (pos, voxel))
}

fn get_voxel(&self, pos: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,18 @@ impl<TIndex: MatrixVoxelWorldIndex> VoxelWorld for MatrixVoxelWorld<TIndex> {
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(
self.data
.get_data()
.zip(0..)
.flat_map(|(plain, x)| {
plain.zip(0..).flat_map(move |(row, y)| {
row.iter()
.copied()
.zip(0..)
.map(move |(voxel, z)| (Self::to_position([x, y, z]).unwrap(), voxel))
})
self.data
.get_data()
.zip(0..)
.flat_map(|(plain, x)| {
plain.zip(0..).flat_map(move |(row, y)| {
row.iter()
.copied()
.zip(0..)
.map(move |(voxel, z)| (Self::to_position([x, y, z]).unwrap(), voxel))
})
.filter_map(|(pos, voxel)| Some((pos, voxel.get_voxel()?))),
)
})
.filter_map(|(pos, voxel)| Some((pos, voxel.get_voxel()?)))
}

fn get_voxel(&self, position: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<TIndex: SortvecVoxelWorldIndex> VoxelWorld for SortvecVoxelWorld<TIndex> {
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(self.data.iter().map(|(&OrdPos(pos), &voxel)| (pos, voxel)))
self.data.iter().map(|(&OrdPos(pos), &voxel)| (pos, voxel))
}

fn get_voxel(&self, pos: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down
1 change: 1 addition & 0 deletions softwareComponents/voxelReconfig/src/voxel_world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod world_rotation;

pub mod impls;
pub mod traits;
pub mod with_connections;

pub use centered::CenteredVoxelWorld;
pub use rotated::{rotate_voxel, RotatedVoxelWorld};
Expand Down
4 changes: 2 additions & 2 deletions softwareComponents/voxelReconfig/src/voxel_world/rotated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ where
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(self.world().all_voxels().map(|(orig_pos, voxel)| {
self.world().all_voxels().map(|(orig_pos, voxel)| {
let rot_voxel = rotate_voxel(voxel, self.rotation);
let rot_pos = self.get_new_pos(orig_pos);
(rot_pos, rot_voxel)
}))
})
}

fn get_voxel(&self, pos: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down
16 changes: 6 additions & 10 deletions softwareComponents/voxelReconfig/src/voxel_world/subworld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,9 @@ impl<'a, TWorld: VoxelWorld> VoxelWorld for VoxelSubworld<'a, TWorld> {
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(
self.included
.iter()
.map(|&OrdPos(pos)| (pos, self.world.get_voxel(pos).unwrap())),
)
self.included
.iter()
.map(|&OrdPos(pos)| (pos, self.world.get_voxel(pos).unwrap()))
}

fn get_voxel(&self, pos: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down Expand Up @@ -207,11 +205,9 @@ pub mod complement {
}

fn all_voxels(&self) -> Self::PosVoxelIter<'_> {
Box::new(
self.underlying_world()
.all_voxels()
.filter(|&(pos, _)| self.contains(pos)),
)
self.underlying_world()
.all_voxels()
.filter(|&(pos, _)| self.contains(pos))
}

fn get_voxel(&self, pos: Pos<Self::IndexType>) -> Option<Voxel> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use super::super::Connections;
use crate::atoms::Axis;
use crate::pos::ord::OrdPos;
use crate::pos::Pos;
use std::collections::{btree_map, BTreeMap};

pub trait MapConnectionsIndex:
num::Signed + Ord + Copy + std::hash::Hash + std::fmt::Debug
{
}
impl<T> MapConnectionsIndex for T where
Self: num::Signed + Ord + Copy + std::hash::Hash + std::fmt::Debug
{
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MapConnections<IndexType: MapConnectionsIndex> {
connections: BTreeMap<OrdPos<IndexType>, [bool; 3]>,
}

impl<IndexType: MapConnectionsIndex> Default for MapConnections<IndexType> {
fn default() -> Self {
Self {
connections: Default::default(),
}
}
}

fn axes_from_inner_value(axes_connected: [bool; 3]) -> smallvec::SmallVec<[Axis; 3]> {
axes_connected
.into_iter()
.zip(enum_iterator::all())
.filter(|&(axis_connected, _)| axis_connected)
.map(|(_, axis)| axis)
.collect()
}

impl<TIndex: MapConnectionsIndex> Connections for MapConnections<TIndex> {
type IndexType = TIndex;
type ConnectionIter<'a> = impl 'a + Iterator<Item = (Pos<Self::IndexType>, Axis)>
where
Self: 'a;

fn connect(&mut self, pos_from: Pos<Self::IndexType>, connected_to: Axis) {
self.connections.entry(OrdPos(pos_from)).or_default()[connected_to.as_index()] = true;
}

fn disconnect(&mut self, pos_from: Pos<Self::IndexType>, connected_to: Axis) {
if let btree_map::Entry::Occupied(mut entry) = self.connections.entry(OrdPos(pos_from)) {
entry.get_mut()[connected_to.as_index()] = false;
if entry.get().iter().all(|&value| !value) {
// Respect default equality
entry.remove();
}
}
}

fn is_connected(&self, pos_from: Pos<Self::IndexType>, connected_to: Axis) -> bool {
if let Some(connections) = self.connections.get(&OrdPos(pos_from)) {
connections[connected_to.as_index()]
} else {
false
}
}

fn connections_from(&self, pos_from: Pos<Self::IndexType>) -> smallvec::SmallVec<[Axis; 3]> {
self.connections
.get(&OrdPos(pos_from))
.copied()
.map_or_else(Default::default, axes_from_inner_value)
}

fn all_connections(&self) -> Self::ConnectionIter<'_> {
self.connections.iter().flat_map(|(&OrdPos(pos), &axes)| {
axes_from_inner_value(axes)
.into_iter()
.map(move |axis| (pos, axis))
})
}

fn from_connections(
connections_iter: impl IntoIterator<Item = (Pos<Self::IndexType>, Axis)>,
) -> Self {
let mut result = Self::default();
for (pos, axis) in connections_iter {
result.connect(pos, axis);
}
result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod map_connections;
pub mod set_connections;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use super::super::Connections;
use crate::atoms::Axis;
use crate::pos::ord::OrdPos;
use crate::pos::Pos;
use enum_iterator::Sequence;
use std::collections::BTreeSet;

pub trait SetConnectionsIndex:
num::Signed + Ord + Copy + std::hash::Hash + std::fmt::Debug
{
}
impl<T> SetConnectionsIndex for T where
Self: num::Signed + Ord + Copy + std::hash::Hash + std::fmt::Debug
{
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SetConnections<IndexType: SetConnectionsIndex> {
connections: BTreeSet<(OrdPos<IndexType>, Axis)>,
}

impl<TIndex: SetConnectionsIndex> Default for SetConnections<TIndex> {
fn default() -> Self {
Self {
connections: Default::default(),
}
}
}

fn iter_adaptor<TIndex: num::Num + Copy>(value: &(OrdPos<TIndex>, Axis)) -> (Pos<TIndex>, Axis) {
let &(OrdPos(pos), axis) = value;
(pos, axis)
}

impl<TIndex: SetConnectionsIndex> Connections for SetConnections<TIndex> {
type IndexType = TIndex;
type ConnectionIter<'a> = impl 'a + Iterator<Item = (Pos<Self::IndexType>, Axis)>
where
Self: 'a;

fn connect(&mut self, pos_from: Pos<Self::IndexType>, connected_to: Axis) {
self.connections.insert((OrdPos(pos_from), connected_to));
}

fn disconnect(&mut self, pos_from: Pos<Self::IndexType>, connected_to: Axis) {
self.connections.remove(&(OrdPos(pos_from), connected_to));
}

fn is_connected(&self, pos_from: Pos<Self::IndexType>, connected_to: Axis) -> bool {
self.connections.contains(&(OrdPos(pos_from), connected_to))
}

fn connections_from(&self, pos_from: Pos<Self::IndexType>) -> smallvec::SmallVec<[Axis; 3]> {
let first_axis = Axis::first().unwrap();
let last_axis = Axis::last().unwrap();
self.connections
.range((OrdPos(pos_from), first_axis)..=(OrdPos(pos_from), last_axis))
.map(|&(_, axis)| axis)
.collect()
}

fn all_connections(&self) -> Self::ConnectionIter<'_> {
self.connections.iter().map(iter_adaptor)
}

fn from_connections(
connections_iter: impl IntoIterator<Item = (Pos<Self::IndexType>, Axis)>,
) -> Self {
Self {
connections: connections_iter
.into_iter()
.map(|(pos, axis)| (OrdPos(pos), axis))
.collect(),
}
}
}
Loading

0 comments on commit 80ea26f

Please sign in to comment.