refactor(router/navmesh): Change `NavnodeWeight` from struct to enum

This commit is contained in:
Mikolaj Wielgus 2025-05-22 18:00:47 +02:00
parent 1acae9ab41
commit fe6a286e32
4 changed files with 75 additions and 58 deletions

View File

@ -255,20 +255,22 @@ impl Viewport {
for edge in navmesh.edge_references() {
let mut from = PrimitiveIndex::from(
navmesh.node_weight(edge.source()).unwrap().node,
navmesh.node_weight(edge.source()).unwrap().node(),
)
.primitive(board.layout().drawing())
.shape()
.center();
let mut to = PrimitiveIndex::from(
navmesh.node_weight(edge.target()).unwrap().node,
navmesh.node_weight(edge.target()).unwrap().node(),
)
.primitive(board.layout().drawing())
.shape()
.center();
if let Some(from_sense) =
navmesh.node_weight(edge.source()).unwrap().maybe_sense
if let Some(from_sense) = navmesh
.node_weight(edge.source())
.unwrap()
.maybe_sense()
{
from += match from_sense {
RotationSense::Counterclockwise => {
@ -278,8 +280,10 @@ impl Viewport {
};
}
if let Some(to_sense) =
navmesh.node_weight(edge.target()).unwrap().maybe_sense
if let Some(to_sense) = navmesh
.node_weight(edge.target())
.unwrap()
.maybe_sense()
{
to += match to_sense {
RotationSense::Counterclockwise => {
@ -335,7 +339,7 @@ impl Viewport {
for index in navmesh.graph().node_indices() {
let navnode = NavnodeIndex(index);
let mut pos = PrimitiveIndex::from(
navmesh.node_weight(navnode).unwrap().node,
navmesh.node_weight(navnode).unwrap().node(),
)
.primitive(board.layout().drawing())
.shape()
@ -344,7 +348,7 @@ impl Viewport {
pos += match navmesh
.node_weight(navnode)
.unwrap()
.maybe_sense
.maybe_sense()
{
Some(RotationSense::Counterclockwise) => {
[0.0, 150.0].into()

View File

@ -18,7 +18,7 @@ use crate::{
use super::{
draw::Draw,
navcorder::{Navcorder, NavcorderException},
navmesh::{BinavnodeNodeIndex, Navmesh, NavnodeIndex},
navmesh::{NavigableNodeIndex, Navmesh, NavnodeIndex},
};
/// The `Navcord` is a data structure that holds the movable non-borrowing data
@ -71,21 +71,21 @@ impl Navcord {
) -> Result<CaneHead, NavcorderException> {
let around_node_weight = navmesh.node_weight(around).unwrap();
let sense = around_node_weight
.maybe_sense
.maybe_sense()
.ok_or(NavcorderException::CannotWrap)?;
match around_node_weight.node {
BinavnodeNodeIndex::FixedDot(dot) => {
match around_node_weight.node() {
NavigableNodeIndex::FixedDot(dot) => {
layout.cane_around_dot(&mut self.recorder, head, dot, sense, self.width)
}
BinavnodeNodeIndex::FixedBend(fixed_bend) => layout.cane_around_bend(
NavigableNodeIndex::FixedBend(fixed_bend) => layout.cane_around_bend(
&mut self.recorder,
head,
fixed_bend.into(),
sense,
self.width,
),
BinavnodeNodeIndex::LooseBend(loose_bend) => layout.cane_around_bend(
NavigableNodeIndex::LooseBend(loose_bend) => layout.cane_around_bend(
&mut self.recorder,
head,
loose_bend.into(),
@ -108,7 +108,7 @@ impl Navcord {
) -> Result<(), NavcorderException> {
if to == navmesh.destination_navnode() {
let to_node_weight = navmesh.node_weight(to).unwrap();
let BinavnodeNodeIndex::FixedDot(to_dot) = to_node_weight.node else {
let NavigableNodeIndex::FixedDot(to_dot) = to_node_weight.node() else {
unreachable!();
};

View File

@ -58,28 +58,28 @@ impl GetPetgraphIndex for NavnodeIndex {
/// not considered navnodes.
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinavnodeNodeIndex {
pub enum NavigableNodeIndex {
FixedDot(FixedDotIndex),
FixedBend(FixedBendIndex),
LooseBend(LooseBendIndex),
}
impl From<BinavnodeNodeIndex> for PrimitiveIndex {
fn from(vertex: BinavnodeNodeIndex) -> Self {
impl From<NavigableNodeIndex> for PrimitiveIndex {
fn from(vertex: NavigableNodeIndex) -> Self {
match vertex {
BinavnodeNodeIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot),
BinavnodeNodeIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend),
BinavnodeNodeIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend),
NavigableNodeIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot),
NavigableNodeIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend),
NavigableNodeIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend),
}
}
}
impl From<BinavnodeNodeIndex> for GearIndex {
fn from(vertex: BinavnodeNodeIndex) -> Self {
impl From<NavigableNodeIndex> for GearIndex {
fn from(vertex: NavigableNodeIndex) -> Self {
match vertex {
BinavnodeNodeIndex::FixedDot(dot) => GearIndex::FixedDot(dot),
BinavnodeNodeIndex::FixedBend(bend) => GearIndex::FixedBend(bend),
BinavnodeNodeIndex::LooseBend(bend) => GearIndex::LooseBend(bend),
NavigableNodeIndex::FixedDot(dot) => GearIndex::FixedDot(dot),
NavigableNodeIndex::FixedBend(bend) => GearIndex::FixedBend(bend),
NavigableNodeIndex::LooseBend(bend) => GearIndex::LooseBend(bend),
}
}
}
@ -97,16 +97,16 @@ enum TrianvertexNodeIndex {
FixedBend(FixedBendIndex),
}
impl From<TrianvertexNodeIndex> for BinavnodeNodeIndex {
impl From<TrianvertexNodeIndex> for NavigableNodeIndex {
fn from(vertex: TrianvertexNodeIndex) -> Self {
match vertex {
TrianvertexNodeIndex::FixedDot(dot) => BinavnodeNodeIndex::FixedDot(dot),
TrianvertexNodeIndex::FixedBend(bend) => BinavnodeNodeIndex::FixedBend(bend),
TrianvertexNodeIndex::FixedDot(dot) => NavigableNodeIndex::FixedDot(dot),
TrianvertexNodeIndex::FixedBend(bend) => NavigableNodeIndex::FixedBend(bend),
}
}
}
#[derive(Debug, Clone)]
#[derive(Clone, Debug)]
struct TrianvertexWeight {
pub node: TrianvertexNodeIndex,
pub pos: Point,
@ -130,15 +130,41 @@ impl HasPosition for TrianvertexWeight {
///
/// See the following blog post for more information and a visualization of the navmesh
/// during autorouting: <https://topola.dev/blog/2024/07/20/junejuly-2024-development-update/#advanced-debug-visualization>
#[derive(Debug, Clone)]
pub struct NavnodeWeight {
pub node: BinavnodeNodeIndex,
#[derive(Clone, Debug)]
pub enum NavnodeWeight {
/// All navigable layout nodes except origin and destination nodes are
/// assigned one or more trinavnodes.
/// Each trinavnode consists of three navnodes distinguished by the three
/// following variants:
/// There are two navnodes for each navigable node:
/// one is clockwise (`Some(true)`), the other counterclockwise (`Some(false)`).
/// The origin and destination nodes however have
/// only one corresponding navmesh vertex each (`None`).
pub maybe_sense: Option<RotationSense>,
/// Navnode corresponding to a counterclockwise wrap around the layout node.
CounterclockwiseStep(NavigableNodeIndex),
/// Navnode corresponding to a clockwise wrap around the layout node.
ClockwiseStep(NavigableNodeIndex),
/// Navnode corresponding to a leap between two step or terminal navnodes.
//Leap(NavigableNodeIndex),
/// Unlike the others, origin and destination layout nodes each are assigned
/// only one navnode, which we call the "terminal navnode".
Terminal(NavigableNodeIndex),
}
impl NavnodeWeight {
pub fn node(&self) -> NavigableNodeIndex {
match self {
NavnodeWeight::CounterclockwiseStep(node) => *node,
NavnodeWeight::ClockwiseStep(node) => *node,
NavnodeWeight::Terminal(node) => *node,
}
}
pub fn maybe_sense(&self) -> Option<RotationSense> {
match self {
NavnodeWeight::CounterclockwiseStep(..) => Some(RotationSense::Counterclockwise),
NavnodeWeight::ClockwiseStep(..) => Some(RotationSense::Clockwise),
NavnodeWeight::Terminal(..) => None,
}
}
}
#[derive(Error, Debug, Clone)]
@ -222,18 +248,12 @@ impl Navmesh {
for trianvertex in triangulation.node_identifiers() {
if trianvertex == origin.into() {
let navnode = graph.add_node(NavnodeWeight {
node: trianvertex.into(),
maybe_sense: None,
});
let navnode = graph.add_node(NavnodeWeight::Terminal(trianvertex.into()));
origin_navnode = Some(navnode);
map.insert(trianvertex, vec![(navnode, navnode)]);
} else if trianvertex == destination.into() {
let navnode = graph.add_node(NavnodeWeight {
node: trianvertex.into(),
maybe_sense: None,
});
let navnode = graph.add_node(NavnodeWeight::Terminal(trianvertex.into()));
destination_navnode = Some(navnode);
map.insert(trianvertex, vec![(navnode, navnode)]);
@ -241,7 +261,7 @@ impl Navmesh {
map.insert(trianvertex, vec![]);
let mut gear =
Into::<GearIndex>::into(Into::<BinavnodeNodeIndex>::into(trianvertex));
Into::<GearIndex>::into(Into::<NavigableNodeIndex>::into(trianvertex));
if options.squeeze_through_under_bends {
Self::add_node_to_graph_and_map_as_binavnode(
@ -311,17 +331,10 @@ impl Navmesh {
graph: &mut UnGraph<NavnodeWeight, (), usize>,
map: &mut BTreeMap<TrianvertexNodeIndex, Vec<(NodeIndex<usize>, NodeIndex<usize>)>>,
trianvertex: TrianvertexNodeIndex,
node: BinavnodeNodeIndex,
node: NavigableNodeIndex,
) {
let navnode1 = graph.add_node(NavnodeWeight {
node,
maybe_sense: Some(RotationSense::Counterclockwise),
});
let navnode2 = graph.add_node(NavnodeWeight {
node,
maybe_sense: Some(RotationSense::Clockwise),
});
let navnode1 = graph.add_node(NavnodeWeight::CounterclockwiseStep(node));
let navnode2 = graph.add_node(NavnodeWeight::ClockwiseStep(node));
map.get_mut(&trianvertex)
.unwrap()

View File

@ -138,7 +138,7 @@ impl<R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex> for RouterAst
}
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavnodeIndex) -> f64 {
let start_point = PrimitiveIndex::from(navmesh.node_weight(vertex).unwrap().node)
let start_point = PrimitiveIndex::from(navmesh.node_weight(vertex).unwrap().node())
.primitive(self.layout.drawing())
.shape()
.center();