use na;
use grid::{GridCoord, GridPoint3, Dir};
use grid::cell_shape::NEIGHBOR_OFFSETS;
use super::triangles::*;
use super::transform::*;
pub fn adjacent_pos_in_dir(pos: GridPoint3, dir: Dir) -> Result<GridPoint3, ()> {
if !dir.points_at_hex_edge() {
return Err(());
}
let edge_index = (dir.index / 2) as usize;
let (dx, dy) = NEIGHBOR_OFFSETS[edge_index];
Ok(GridPoint3::new(pos.root, pos.x + dx, pos.y + dy, pos.z))
}
pub fn transform_into_exit_triangle(
pos: &mut GridPoint3,
dir: &mut Dir,
resolution: [GridCoord; 2],
exit: &Exit,
) {
let exit_tri = &TRIANGLES[exit.triangle_index];
pos.root.index = (pos.root.index + exit.root_offset) % 5;
let (new_pos, new_dir) = local_to_world(*pos, *dir, resolution, exit_tri);
*pos = new_pos;
*dir = new_dir;
}
pub fn closest_triangle_to_point(
pos: &GridPoint3,
resolution: [GridCoord; 2],
) -> &'static Triangle {
let candidate_triangles = if pos.x + pos.y < resolution[0] {
&TRIANGLES[0..3]
} else if pos.y < resolution[0] {
&TRIANGLES[3..6]
} else if pos.x + pos.y < resolution[1] {
&TRIANGLES[6..9]
} else {
&TRIANGLES[9..12]
};
type Pos2 = na::Point2<GridCoord>;
let pos2 = Pos2::new(pos.x, pos.y);
candidate_triangles
.iter()
.min_by_key(|triangle| {
let apex = Pos2::new(triangle.apex[0], triangle.apex[1]) * resolution[0];
let apex_to_pos = (pos2 - apex).abs();
apex_to_pos.x + apex_to_pos.y
})
.expect(
"There should have been exactly three items; this shouldn't be possible!",
)
}
pub fn triangle_on_pos_with_closest_mid_axis(
pos: &GridPoint3,
dir: &Dir,
resolution: [GridCoord; 2],
) -> &'static Triangle {
type Pos2 = na::Point2<GridCoord>;
let pos2 = Pos2::new(pos.x, pos.y);
TRIANGLES
.iter()
.filter(|triangle| {
use num_traits::Zero;
let apex = Pos2::new(triangle.apex[0], triangle.apex[1]) * resolution[0];
let apex_to_pos = (pos2 - apex).abs();
apex_to_pos.is_zero()
})
.min_by_key(|triangle| {
let middle_axis_dir: i16 = (triangle.x_dir as i16 + 1) % 12;
let mut a = middle_axis_dir - dir.index as i16;
if a > 6 {
a -= 12;
} else if a < -6 {
a += 12;
}
a.abs()
})
.expect(
"There should have been 1-3 triangles; did you call this with a non-pentagon pos?",
)
}
pub fn is_pentagon(pos: &GridPoint3, resolution: [GridCoord; 2]) -> bool {
let is_north = pos.x == 0 && pos.y == 0;
let is_north_east = pos.x == 0 && pos.y == resolution[0];
let is_east = pos.x == 0 && pos.y == resolution[1];
let is_west = pos.x == resolution[0] && pos.y == 0;
let is_south_west = pos.x == resolution[0] && pos.y == resolution[0];
let is_south = pos.x == resolution[0] && pos.y == resolution[1];
is_north || is_north_east || is_east || is_west || is_south_west || is_south
}
pub fn is_on_root_edge(pos: &GridPoint3, resolution: [GridCoord; 2]) -> bool {
pos.x == 0 || pos.y == 0 || pos.x == resolution[0] || pos.y == resolution[1]
}
pub fn debug_assert_pos_within_root(pos: &mut GridPoint3, resolution: [GridCoord; 2]) {
debug_assert!(
pos.x >= 0 && pos.y >= 0 && pos.x <= resolution[0] && pos.y <= resolution[1],
"`pos` was outside its root at the given resolution."
);
}