mirror of https://codeberg.org/topola/topola.git
router: store every vertex (fails tests but almost functional)
Previously, rail vertices were not stored but generated on demand from data stored in a `Triangulation<...>`. This functionality is removed in favor of storing every vertex in `Navmesh`'s own graph built from the `Triangulation<...>`, which is now afterwards discarded. Tests still fail and rails aren't added yet, but this is close enough to completion for me to commit so that I can now go to sleep without worrying.
This commit is contained in:
parent
d4a310a5c0
commit
ae2a862e0e
|
|
@ -33,7 +33,7 @@ use topola::{
|
|||
math::Circle,
|
||||
router::{
|
||||
draw::DrawException,
|
||||
navmesh::{Navmesh, NavmeshEdgeReference, NavvertexNodeIndex},
|
||||
navmesh::{BinavvertexNodeIndex, Navmesh},
|
||||
tracer::{Trace, Tracer},
|
||||
},
|
||||
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
|
||||
|
|
@ -49,7 +49,7 @@ pub struct SharedData {
|
|||
pub from: Option<FixedDotIndex>,
|
||||
pub to: Option<FixedDotIndex>,
|
||||
pub navmesh: Option<Navmesh>,
|
||||
pub path: Vec<NavvertexNodeIndex>,
|
||||
pub path: Vec<BinavvertexNodeIndex>,
|
||||
pub ghosts: Vec<PrimitiveShape>,
|
||||
pub highlighteds: Vec<PrimitiveIndex>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
|||
use topola::{
|
||||
autorouter::invoker::{Command, Invoker},
|
||||
board::mesadata::MesadataTrait,
|
||||
drawing::{graph::MakePrimitive, primitive::MakePrimitiveShape},
|
||||
drawing::{
|
||||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
primitive::MakePrimitiveShape,
|
||||
},
|
||||
geometry::{shape::ShapeTrait, GenericNode},
|
||||
layout::{via::ViaWeight, zone::MakePolyShape},
|
||||
math::Circle,
|
||||
|
|
@ -165,14 +168,12 @@ impl Viewport {
|
|||
}
|
||||
|
||||
if let Some(navmesh) = &shared_data.navmesh {
|
||||
for edge in navmesh.edge_references() {
|
||||
let from = edge
|
||||
.source()
|
||||
for edge in navmesh.graph().edge_references() {
|
||||
let from = PrimitiveIndex::from(navmesh.graph().node_weight(edge.source()).unwrap().node)
|
||||
.primitive(board.layout().drawing())
|
||||
.shape()
|
||||
.center();
|
||||
let to = edge
|
||||
.target()
|
||||
let to = PrimitiveIndex::from(navmesh.graph().node_weight(edge.target()).unwrap().node)
|
||||
.primitive(board.layout().drawing())
|
||||
.shape()
|
||||
.center();
|
||||
|
|
@ -182,11 +183,11 @@ impl Viewport {
|
|||
shared_data
|
||||
.path
|
||||
.iter()
|
||||
.position(|node| *node == edge.source()),
|
||||
.position(|node| *node == navmesh.graph().node_weight(edge.source()).unwrap().node),
|
||||
shared_data
|
||||
.path
|
||||
.iter()
|
||||
.position(|node| *node == edge.target()),
|
||||
.position(|node| *node == navmesh.graph().node_weight(edge.target()).unwrap().node),
|
||||
) {
|
||||
if target_pos == source_pos + 1
|
||||
|| source_pos == target_pos + 1
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ where
|
|||
K: Measure + Copy,
|
||||
G::NodeId: Eq + Hash,
|
||||
{
|
||||
fn is_goal(&mut self, node: G::NodeId, tracker: &PathTracker<G>) -> Option<R>;
|
||||
fn edge_cost(&mut self, edge: G::EdgeRef) -> Option<K>;
|
||||
fn estimate_cost(&mut self, node: G::NodeId) -> K;
|
||||
fn is_goal(&mut self, graph: &G, node: G::NodeId, tracker: &PathTracker<G>) -> Option<R>;
|
||||
fn edge_cost(&mut self, graph: &G, edge: G::EdgeRef) -> Option<K>;
|
||||
fn estimate_cost(&mut self, graph: &G, node: G::NodeId) -> K;
|
||||
}
|
||||
|
||||
pub struct Astar<G, K>
|
||||
|
|
@ -153,7 +153,7 @@ where
|
|||
let zero_score = K::default();
|
||||
this.scores.insert(start, zero_score);
|
||||
this.visit_next
|
||||
.push(MinScored(strategy.estimate_cost(start), start));
|
||||
.push(MinScored(strategy.estimate_cost(&&graph, start), start));
|
||||
this
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ where
|
|||
return Err(AstarError::NotFound);
|
||||
};
|
||||
|
||||
if let Some(result) = strategy.is_goal(node, &self.path_tracker) {
|
||||
if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) {
|
||||
let path = self.path_tracker.reconstruct_path_to(node);
|
||||
let cost = self.scores[&node];
|
||||
return Ok(AstarStatus::Finished(cost, path, result));
|
||||
|
|
@ -190,7 +190,7 @@ where
|
|||
}
|
||||
|
||||
for edge in self.graph.edges(node) {
|
||||
if let Some(edge_cost) = strategy.edge_cost(edge) {
|
||||
if let Some(edge_cost) = strategy.edge_cost(&self.graph, edge) {
|
||||
let next = edge.target();
|
||||
let next_score = node_score + edge_cost;
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ where
|
|||
}
|
||||
|
||||
self.path_tracker.set_predecessor(next, node);
|
||||
let next_estimate_score = next_score + strategy.estimate_cost(next);
|
||||
let next_estimate_score = next_score + strategy.estimate_cost(&self.graph, next);
|
||||
self.visit_next.push(MinScored(next_estimate_score, next));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,46 @@
|
|||
use std::iter;
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use geo::Point;
|
||||
use itertools::Itertools;
|
||||
use petgraph::visit::{self, NodeIndexable};
|
||||
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
|
||||
use petgraph::{
|
||||
graph::UnGraph,
|
||||
stable_graph::NodeIndex,
|
||||
visit::{IntoNodeIdentifiers, NodeIndexable},
|
||||
};
|
||||
use spade::{HasPosition, InsertionError, Point2};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::drawing::graph::{GetLayer, GetMaybeNet};
|
||||
use crate::geometry::shape::ShapeTrait;
|
||||
use crate::{
|
||||
drawing::{
|
||||
bend::{FixedBendIndex, LooseBendIndex},
|
||||
dot::FixedDotIndex,
|
||||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
primitive::{GetCore, MakePrimitiveShape, Primitive},
|
||||
graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex},
|
||||
primitive::{MakePrimitiveShape, Primitive},
|
||||
rules::RulesTrait,
|
||||
Drawing,
|
||||
},
|
||||
geometry::shape::ShapeTrait,
|
||||
graph::GetPetgraphIndex,
|
||||
layout::Layout,
|
||||
triangulation::{GetTrianvertexNodeIndex, Triangulation, TriangulationEdgeReference},
|
||||
triangulation::{GetTrianvertexNodeIndex, Triangulation},
|
||||
};
|
||||
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum NavvertexNodeIndex {
|
||||
pub enum BinavvertexNodeIndex {
|
||||
FixedDot(FixedDotIndex),
|
||||
FixedBend(FixedBendIndex),
|
||||
LooseBend(LooseBendIndex),
|
||||
}
|
||||
|
||||
impl From<BinavvertexNodeIndex> for PrimitiveIndex {
|
||||
fn from(vertex: BinavvertexNodeIndex) -> Self {
|
||||
match vertex {
|
||||
BinavvertexNodeIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot),
|
||||
BinavvertexNodeIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend),
|
||||
BinavvertexNodeIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||
enum TrianvertexNodeIndex {
|
||||
|
|
@ -39,30 +48,19 @@ enum TrianvertexNodeIndex {
|
|||
FixedBend(FixedBendIndex),
|
||||
}
|
||||
|
||||
impl From<NavvertexNodeIndex> for PrimitiveIndex {
|
||||
fn from(vertex: NavvertexNodeIndex) -> Self {
|
||||
match vertex {
|
||||
NavvertexNodeIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot),
|
||||
NavvertexNodeIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend),
|
||||
NavvertexNodeIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TrianvertexNodeIndex> for NavvertexNodeIndex {
|
||||
impl From<TrianvertexNodeIndex> for BinavvertexNodeIndex {
|
||||
fn from(vertex: TrianvertexNodeIndex) -> Self {
|
||||
match vertex {
|
||||
TrianvertexNodeIndex::FixedDot(dot) => NavvertexNodeIndex::FixedDot(dot),
|
||||
TrianvertexNodeIndex::FixedBend(bend) => NavvertexNodeIndex::FixedBend(bend),
|
||||
TrianvertexNodeIndex::FixedDot(dot) => BinavvertexNodeIndex::FixedDot(dot),
|
||||
TrianvertexNodeIndex::FixedBend(bend) => BinavvertexNodeIndex::FixedBend(bend),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct TrianvertexWeight {
|
||||
node: TrianvertexNodeIndex,
|
||||
rails: Vec<LooseBendIndex>,
|
||||
pos: Point,
|
||||
pub node: TrianvertexNodeIndex,
|
||||
pub pos: Point,
|
||||
}
|
||||
|
||||
impl GetTrianvertexNodeIndex<TrianvertexNodeIndex> for TrianvertexWeight {
|
||||
|
|
@ -79,11 +77,8 @@ impl HasPosition for TrianvertexWeight {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Navmesh {
|
||||
triangulation: Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()>,
|
||||
navvertex_to_trianvertex: Vec<Option<TrianvertexNodeIndex>>,
|
||||
source: FixedDotIndex,
|
||||
target: FixedDotIndex,
|
||||
pub struct NavvertexWeight {
|
||||
pub node: BinavvertexNodeIndex,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
|
|
@ -92,20 +87,23 @@ pub enum NavmeshError {
|
|||
Insertion(#[from] InsertionError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Navmesh {
|
||||
graph: UnGraph<NavvertexWeight, (), usize>,
|
||||
source: FixedDotIndex,
|
||||
source_vertex: NodeIndex<usize>,
|
||||
target: FixedDotIndex,
|
||||
target_vertex: NodeIndex<usize>,
|
||||
}
|
||||
|
||||
impl Navmesh {
|
||||
pub fn new(
|
||||
layout: &Layout<impl RulesTrait>,
|
||||
source: FixedDotIndex,
|
||||
target: FixedDotIndex,
|
||||
) -> Result<Self, NavmeshError> {
|
||||
let mut this = Self {
|
||||
triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()),
|
||||
navvertex_to_trianvertex: Vec::new(),
|
||||
source,
|
||||
target,
|
||||
};
|
||||
this.navvertex_to_trianvertex
|
||||
.resize(layout.drawing().geometry().graph().node_bound(), None);
|
||||
let mut triangulation: Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()> =
|
||||
Triangulation::new(layout.drawing().geometry().graph().node_bound());
|
||||
|
||||
let layer = layout.drawing().primitive(source).layer();
|
||||
let maybe_net = layout.drawing().primitive(source).maybe_net();
|
||||
|
|
@ -120,16 +118,14 @@ impl Navmesh {
|
|||
{
|
||||
match node {
|
||||
PrimitiveIndex::FixedDot(dot) => {
|
||||
this.triangulation.add_vertex(TrianvertexWeight {
|
||||
triangulation.add_vertex(TrianvertexWeight {
|
||||
node: dot.into(),
|
||||
rails: vec![],
|
||||
pos: primitive.shape().center(),
|
||||
})?;
|
||||
}
|
||||
PrimitiveIndex::FixedBend(bend) => {
|
||||
this.triangulation.add_vertex(TrianvertexWeight {
|
||||
triangulation.add_vertex(TrianvertexWeight {
|
||||
node: bend.into(),
|
||||
rails: vec![],
|
||||
pos: primitive.shape().center(),
|
||||
})?;
|
||||
}
|
||||
|
|
@ -139,185 +135,48 @@ impl Navmesh {
|
|||
}
|
||||
}
|
||||
|
||||
for node in layout.drawing().layer_primitive_nodes(layer) {
|
||||
// Add rails as vertices. This is how the navmesh differs from the triangulation.
|
||||
match node {
|
||||
PrimitiveIndex::LooseBend(bend) => {
|
||||
this.triangulation
|
||||
.weight_mut(layout.drawing().primitive(bend).core().into())
|
||||
.rails
|
||||
.push(bend.into());
|
||||
this.navvertex_to_trianvertex[bend.petgraph_index().index()] =
|
||||
Some(layout.drawing().primitive(bend).core().into());
|
||||
}
|
||||
_ => (),
|
||||
let mut graph: UnGraph<NavvertexWeight, (), usize> = UnGraph::default();
|
||||
let mut source_vertex = None;
|
||||
let mut target_vertex = None;
|
||||
|
||||
for trianvertex in triangulation.node_identifiers() {
|
||||
let navvertex = graph.add_node(NavvertexWeight {
|
||||
node: trianvertex.into(),
|
||||
});
|
||||
|
||||
if trianvertex == source.into() {
|
||||
source_vertex = Some(navvertex);
|
||||
} else if trianvertex == target.into() {
|
||||
target_vertex = Some(navvertex);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(this)
|
||||
Ok(Self {
|
||||
graph,
|
||||
source,
|
||||
source_vertex: source_vertex.unwrap(),
|
||||
target,
|
||||
target_vertex: target_vertex.unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
fn trianvertex(&self, vertex: NavvertexNodeIndex) -> TrianvertexNodeIndex {
|
||||
match vertex {
|
||||
NavvertexNodeIndex::FixedDot(dot) => TrianvertexNodeIndex::FixedDot(dot),
|
||||
NavvertexNodeIndex::FixedBend(bend) => TrianvertexNodeIndex::FixedBend(bend),
|
||||
NavvertexNodeIndex::LooseBend(bend) => {
|
||||
self.navvertex_to_trianvertex[bend.petgraph_index().index()].unwrap()
|
||||
}
|
||||
}
|
||||
pub fn graph(&self) -> &UnGraph<NavvertexWeight, (), usize> {
|
||||
&self.graph
|
||||
}
|
||||
|
||||
pub fn source(&self) -> FixedDotIndex {
|
||||
self.source
|
||||
}
|
||||
|
||||
pub fn source_vertex(&self) -> NodeIndex<usize> {
|
||||
self.source_vertex
|
||||
}
|
||||
|
||||
pub fn target(&self) -> FixedDotIndex {
|
||||
self.target
|
||||
}
|
||||
}
|
||||
|
||||
impl visit::GraphBase for Navmesh {
|
||||
type NodeId = NavvertexNodeIndex;
|
||||
type EdgeId = (NavvertexNodeIndex, NavvertexNodeIndex);
|
||||
}
|
||||
|
||||
impl visit::Data for Navmesh {
|
||||
type NodeWeight = ();
|
||||
type EdgeWeight = ();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NavmeshEdgeReference {
|
||||
from: NavvertexNodeIndex,
|
||||
to: NavvertexNodeIndex,
|
||||
}
|
||||
|
||||
impl visit::EdgeRef for NavmeshEdgeReference {
|
||||
type NodeId = NavvertexNodeIndex;
|
||||
type EdgeId = (NavvertexNodeIndex, NavvertexNodeIndex);
|
||||
type Weight = ();
|
||||
|
||||
fn source(&self) -> Self::NodeId {
|
||||
self.from
|
||||
}
|
||||
|
||||
fn target(&self) -> Self::NodeId {
|
||||
self.to
|
||||
}
|
||||
|
||||
fn weight(&self) -> &Self::Weight {
|
||||
&()
|
||||
}
|
||||
|
||||
fn id(&self) -> Self::EdgeId {
|
||||
(self.from, self.to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> visit::IntoNeighbors for &'a Navmesh {
|
||||
type Neighbors = Box<dyn Iterator<Item = NavvertexNodeIndex> + 'a>;
|
||||
|
||||
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
||||
Box::new(
|
||||
self.triangulation
|
||||
.neighbors(self.trianvertex(vertex))
|
||||
.flat_map(|neighbor| {
|
||||
iter::once(neighbor.into()).chain(
|
||||
self.triangulation
|
||||
.weight(neighbor)
|
||||
.rails
|
||||
.iter()
|
||||
.map(|index| NavvertexNodeIndex::from(*index)),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn edge_with_near_edges(
|
||||
triangulation: &Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()>,
|
||||
edge: TriangulationEdgeReference<TrianvertexNodeIndex, ()>,
|
||||
) -> impl Iterator<Item = NavmeshEdgeReference> {
|
||||
let mut from_vertices = vec![edge.source().into()];
|
||||
|
||||
// Append rails to the source.
|
||||
from_vertices.extend(
|
||||
triangulation
|
||||
.weight(edge.source())
|
||||
.rails
|
||||
.iter()
|
||||
.map(|bend| NavvertexNodeIndex::from(*bend)),
|
||||
);
|
||||
|
||||
let mut to_vertices = vec![edge.target().into()];
|
||||
|
||||
// Append rails to the target.
|
||||
to_vertices.extend(
|
||||
triangulation
|
||||
.weight(edge.target())
|
||||
.rails
|
||||
.iter()
|
||||
.map(|bend| NavvertexNodeIndex::from(*bend)),
|
||||
);
|
||||
|
||||
// Return cartesian product.
|
||||
from_vertices
|
||||
.into_iter()
|
||||
.cartesian_product(to_vertices.into_iter())
|
||||
.map(|pair| NavmeshEdgeReference {
|
||||
from: pair.0,
|
||||
to: pair.1.into(),
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> visit::IntoEdgeReferences for &'a Navmesh {
|
||||
type EdgeRef = NavmeshEdgeReference;
|
||||
type EdgeReferences = Box<dyn Iterator<Item = NavmeshEdgeReference> + 'a>;
|
||||
|
||||
fn edge_references(self) -> Self::EdgeReferences {
|
||||
Box::new(
|
||||
self.triangulation
|
||||
.edge_references()
|
||||
.flat_map(move |edge| edge_with_near_edges(&self.triangulation, edge)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn vertex_edges(
|
||||
triangulation: &Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()>,
|
||||
from: NavvertexNodeIndex,
|
||||
to: TrianvertexNodeIndex,
|
||||
) -> impl Iterator<Item = NavmeshEdgeReference> {
|
||||
let from_vertices = vec![from];
|
||||
let mut to_vertices = vec![to.into()];
|
||||
|
||||
// Append rails to the target.
|
||||
to_vertices.extend(
|
||||
triangulation
|
||||
.weight(to)
|
||||
.rails
|
||||
.iter()
|
||||
.map(|bend| NavvertexNodeIndex::from(*bend)),
|
||||
);
|
||||
|
||||
// Return cartesian product.
|
||||
from_vertices
|
||||
.into_iter()
|
||||
.cartesian_product(to_vertices.into_iter())
|
||||
.map(|pair| NavmeshEdgeReference {
|
||||
from: pair.0,
|
||||
to: pair.1,
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> visit::IntoEdges for &'a Navmesh {
|
||||
type Edges = Box<dyn Iterator<Item = NavmeshEdgeReference> + 'a>;
|
||||
|
||||
fn edges(self, vertex: Self::NodeId) -> Self::Edges {
|
||||
Box::new(
|
||||
self.triangulation
|
||||
.edges(self.trianvertex(vertex))
|
||||
.flat_map(move |edge| vertex_edges(&self.triangulation, vertex, edge.target())),
|
||||
)
|
||||
pub fn target_vertex(&self) -> NodeIndex<usize> {
|
||||
self.target_vertex
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use geo::EuclideanDistance;
|
||||
use petgraph::visit::EdgeRef;
|
||||
use petgraph::{
|
||||
graph::{EdgeReference, NodeIndex, UnGraph},
|
||||
visit::EdgeRef,
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -11,11 +14,12 @@ use crate::{
|
|||
rules::RulesTrait,
|
||||
},
|
||||
geometry::shape::ShapeTrait,
|
||||
graph::GetPetgraphIndex,
|
||||
layout::Layout,
|
||||
router::{
|
||||
astar::{astar, AstarError, AstarStrategy, PathTracker},
|
||||
draw::DrawException,
|
||||
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexNodeIndex},
|
||||
navmesh::{BinavvertexNodeIndex, Navmesh, NavmeshError, NavvertexWeight},
|
||||
tracer::{Trace, Tracer},
|
||||
},
|
||||
};
|
||||
|
|
@ -35,55 +39,75 @@ pub struct Router<'a, R: RulesTrait> {
|
|||
struct RouterAstarStrategy<'a, R: RulesTrait> {
|
||||
tracer: Tracer<'a, R>,
|
||||
trace: Trace,
|
||||
to: FixedDotIndex,
|
||||
target: FixedDotIndex,
|
||||
}
|
||||
|
||||
impl<'a, R: RulesTrait> RouterAstarStrategy<'a, R> {
|
||||
pub fn new(tracer: Tracer<'a, R>, trace: Trace, to: FixedDotIndex) -> Self {
|
||||
Self { tracer, trace, to }
|
||||
pub fn new(tracer: Tracer<'a, R>, trace: Trace, target: FixedDotIndex) -> Self {
|
||||
Self {
|
||||
tracer,
|
||||
trace,
|
||||
target,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: RulesTrait> AstarStrategy<&Navmesh, f64, BandFirstSegIndex>
|
||||
impl<'a, R: RulesTrait> AstarStrategy<&UnGraph<NavvertexWeight, (), usize>, f64, BandFirstSegIndex>
|
||||
for RouterAstarStrategy<'a, R>
|
||||
{
|
||||
fn is_goal(
|
||||
&mut self,
|
||||
vertex: NavvertexNodeIndex,
|
||||
tracker: &PathTracker<&Navmesh>,
|
||||
graph: &&UnGraph<NavvertexWeight, (), usize>,
|
||||
vertex: NodeIndex<usize>,
|
||||
tracker: &PathTracker<&UnGraph<NavvertexWeight, (), usize>>,
|
||||
) -> Option<BandFirstSegIndex> {
|
||||
let new_path = tracker.reconstruct_path_to(vertex);
|
||||
/*.into_iter()
|
||||
.map(|ni| graph.node_weight(ni).unwrap().node)
|
||||
.collect();*/
|
||||
let width = self.trace.width;
|
||||
|
||||
self.tracer
|
||||
.rework_path(&mut self.trace, &new_path, width)
|
||||
.rework_path(*graph, &mut self.trace, &new_path[..], width)
|
||||
.unwrap();
|
||||
|
||||
self.tracer.finish(&mut self.trace, self.to, width).ok()
|
||||
self.tracer
|
||||
.finish(*graph, &mut self.trace, self.target, width)
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn edge_cost(&mut self, edge: NavmeshEdgeReference) -> Option<f64> {
|
||||
if edge.target() == self.to.into() {
|
||||
fn edge_cost(
|
||||
&mut self,
|
||||
graph: &&UnGraph<NavvertexWeight, (), usize>,
|
||||
edge: EdgeReference<(), usize>,
|
||||
) -> Option<f64> {
|
||||
if edge.target() == self.target.petgraph_index() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let before_probe_length = 0.0; //self.tracer.layout.band_length(self.trace.head.face());
|
||||
|
||||
let width = self.trace.width;
|
||||
let result = self.tracer.step(&mut self.trace, edge.target(), width);
|
||||
let result = self
|
||||
.tracer
|
||||
.step(*graph, &mut self.trace, edge.target(), width);
|
||||
|
||||
let probe_length = 0.0; //self.tracer.layout.band_length(self.trace.head.face());
|
||||
|
||||
if result.is_ok() {
|
||||
self.tracer.undo_step(&mut self.trace);
|
||||
self.tracer.undo_step(*graph, &mut self.trace);
|
||||
Some(probe_length - before_probe_length)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn estimate_cost(&mut self, vertex: NavvertexNodeIndex) -> f64 {
|
||||
let start_point = PrimitiveIndex::from(vertex)
|
||||
fn estimate_cost(
|
||||
&mut self,
|
||||
graph: &&UnGraph<NavvertexWeight, (), usize>,
|
||||
vertex: NodeIndex<usize>,
|
||||
) -> f64 {
|
||||
let start_point = PrimitiveIndex::from(graph.node_weight(vertex).unwrap().node)
|
||||
.primitive(self.tracer.layout.drawing())
|
||||
.shape()
|
||||
.center();
|
||||
|
|
@ -91,7 +115,7 @@ impl<'a, R: RulesTrait> AstarStrategy<&Navmesh, f64, BandFirstSegIndex>
|
|||
.tracer
|
||||
.layout
|
||||
.drawing()
|
||||
.primitive(self.to)
|
||||
.primitive(self.target)
|
||||
.shape()
|
||||
.center();
|
||||
|
||||
|
|
@ -114,15 +138,18 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
|||
}
|
||||
|
||||
pub fn route_band(&mut self, width: f64) -> Result<BandFirstSegIndex, RouterError> {
|
||||
let from = self.navmesh.source();
|
||||
let to = self.navmesh.target();
|
||||
let mut tracer = Tracer::new(self.layout);
|
||||
let trace = tracer.start(from, width);
|
||||
let trace = tracer.start(
|
||||
self.navmesh.graph(),
|
||||
self.navmesh.source(),
|
||||
self.navmesh.source_vertex(),
|
||||
width,
|
||||
);
|
||||
|
||||
let (_cost, _path, band) = astar(
|
||||
&self.navmesh,
|
||||
from.into(),
|
||||
&mut RouterAstarStrategy::new(tracer, trace, to),
|
||||
self.navmesh.graph(),
|
||||
self.navmesh.source_vertex(),
|
||||
&mut RouterAstarStrategy::new(tracer, trace, self.navmesh.target()),
|
||||
)?;
|
||||
|
||||
Ok(band)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,25 @@
|
|||
use contracts::debug_ensures;
|
||||
use contracts::{debug_ensures, debug_requires};
|
||||
use petgraph::graph::{NodeIndex, UnGraph};
|
||||
|
||||
use crate::{
|
||||
drawing::{
|
||||
band::BandFirstSegIndex,
|
||||
bend::LooseBendIndex,
|
||||
dot::FixedDotIndex,
|
||||
graph::PrimitiveIndex,
|
||||
guide::{BareHead, CaneHead, Head},
|
||||
rules::RulesTrait,
|
||||
},
|
||||
layout::Layout,
|
||||
router::{
|
||||
draw::{Draw, DrawException},
|
||||
navmesh::NavvertexNodeIndex,
|
||||
navmesh::{BinavvertexNodeIndex, NavvertexWeight},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Trace {
|
||||
pub path: Vec<NavvertexNodeIndex>,
|
||||
pub path: Vec<NodeIndex<usize>>,
|
||||
pub head: Head,
|
||||
pub width: f64,
|
||||
}
|
||||
|
|
@ -32,28 +34,37 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
Tracer { layout }
|
||||
}
|
||||
|
||||
pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace {
|
||||
pub fn start(
|
||||
&mut self,
|
||||
_graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
source: FixedDotIndex,
|
||||
source_vertex: NodeIndex<usize>,
|
||||
width: f64,
|
||||
) -> Trace {
|
||||
Trace {
|
||||
path: vec![from.into()],
|
||||
head: BareHead { dot: from }.into(),
|
||||
path: vec![source_vertex],
|
||||
head: BareHead { dot: source }.into(),
|
||||
width,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
trace: &mut Trace,
|
||||
into: FixedDotIndex,
|
||||
target: FixedDotIndex,
|
||||
width: f64,
|
||||
) -> Result<BandFirstSegIndex, DrawException> {
|
||||
Draw::new(self.layout).finish_in_dot(trace.head, into, width)
|
||||
Draw::new(self.layout).finish_in_dot(trace.head, target, width)
|
||||
}
|
||||
|
||||
#[debug_requires(path[0] == trace.path[0])]
|
||||
#[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())]
|
||||
pub fn rework_path(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
trace: &mut Trace,
|
||||
path: &[NavvertexNodeIndex],
|
||||
path: &[NodeIndex<usize>],
|
||||
width: f64,
|
||||
) -> Result<(), DrawException> {
|
||||
let prefix_length = trace
|
||||
|
|
@ -64,20 +75,21 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
.count();
|
||||
|
||||
let length = trace.path.len();
|
||||
self.undo_path(trace, length - prefix_length);
|
||||
self.path(trace, &path[prefix_length..], width)
|
||||
self.undo_path(graph, trace, length - prefix_length);
|
||||
self.path(graph, trace, &path[prefix_length..], width)
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() + path.len()))]
|
||||
pub fn path(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
trace: &mut Trace,
|
||||
path: &[NavvertexNodeIndex],
|
||||
path: &[NodeIndex<usize>],
|
||||
width: f64,
|
||||
) -> Result<(), DrawException> {
|
||||
for (i, vertex) in path.iter().enumerate() {
|
||||
if let Err(err) = self.step(trace, *vertex, width) {
|
||||
self.undo_path(trace, i);
|
||||
if let Err(err) = self.step(graph, trace, *vertex, width) {
|
||||
self.undo_path(graph, trace, i);
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
|
@ -86,21 +98,28 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
}
|
||||
|
||||
#[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))]
|
||||
pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) {
|
||||
pub fn undo_path(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
trace: &mut Trace,
|
||||
step_count: usize,
|
||||
) {
|
||||
for _ in 0..step_count {
|
||||
self.undo_step(trace);
|
||||
self.undo_step(graph, trace);
|
||||
}
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> matches!(trace.head, Head::Bare(..)))]
|
||||
#[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() + 1))]
|
||||
#[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))]
|
||||
pub fn step(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
trace: &mut Trace,
|
||||
to: NavvertexNodeIndex,
|
||||
to: NodeIndex<usize>,
|
||||
width: f64,
|
||||
) -> Result<(), DrawException> {
|
||||
trace.head = self.wrap(trace.head, to, width)?.into();
|
||||
trace.head = self.wrap(graph, trace.head, to, width)?.into();
|
||||
trace.path.push(to);
|
||||
|
||||
Ok::<(), DrawException>(())
|
||||
|
|
@ -108,21 +127,25 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
|
||||
fn wrap(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
head: Head,
|
||||
around: NavvertexNodeIndex,
|
||||
around: NodeIndex<usize>,
|
||||
width: f64,
|
||||
) -> Result<CaneHead, DrawException> {
|
||||
match around {
|
||||
NavvertexNodeIndex::FixedDot(dot) => self.wrap_around_fixed_dot(head, dot, width),
|
||||
NavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
|
||||
NavvertexNodeIndex::LooseBend(loose_bend) => {
|
||||
self.wrap_around_loose_bend(head, loose_bend, width)
|
||||
match self.binavvertex(graph, around) {
|
||||
BinavvertexNodeIndex::FixedDot(dot) => {
|
||||
self.wrap_around_fixed_dot(graph, head, dot, width)
|
||||
}
|
||||
BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
|
||||
BinavvertexNodeIndex::LooseBend(loose_bend) => {
|
||||
self.wrap_around_loose_bend(graph, head, loose_bend, width)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_around_fixed_dot(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
head: Head,
|
||||
around: FixedDotIndex,
|
||||
width: f64,
|
||||
|
|
@ -133,6 +156,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
|
||||
fn wrap_around_loose_bend(
|
||||
&mut self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
head: Head,
|
||||
around: LooseBendIndex,
|
||||
width: f64,
|
||||
|
|
@ -143,8 +167,8 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
}
|
||||
|
||||
#[debug_ensures(trace.path.len() == old(trace.path.len() - 1))]
|
||||
pub fn undo_step(&mut self, trace: &mut Trace) {
|
||||
if let Head::Cane(head) = trace.head {
|
||||
pub fn undo_step(&mut self, graph: &UnGraph<NavvertexWeight, (), usize>, trace: &mut Trace) {
|
||||
if let Head::Cane(head) = dbg!(trace.head) {
|
||||
trace.head = Draw::new(self.layout).undo_cane(head).unwrap();
|
||||
} else {
|
||||
panic!();
|
||||
|
|
@ -152,4 +176,20 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
|
||||
trace.path.pop();
|
||||
}
|
||||
|
||||
fn binavvertex(
|
||||
&self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
vertex: NodeIndex<usize>,
|
||||
) -> BinavvertexNodeIndex {
|
||||
graph.node_weight(vertex).unwrap().node
|
||||
}
|
||||
|
||||
fn primitive(
|
||||
&self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
vertex: NodeIndex<usize>,
|
||||
) -> PrimitiveIndex {
|
||||
self.binavvertex(graph, vertex).into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue