mirror of https://codeberg.org/topola/topola.git
egui,autorouter,router: display infringement shapes (aka. "ghosts")
This commit is contained in:
parent
727eb37c6e
commit
b6cb89c017
|
|
@ -1,14 +1,16 @@
|
|||
use petgraph::graph::EdgeIndex;
|
||||
|
||||
use crate::{
|
||||
autorouter::{
|
||||
invoker::{GetMaybeNavmesh, GetMaybeTrace},
|
||||
Autorouter, AutorouterError, AutorouterStatus,
|
||||
},
|
||||
board::mesadata::AccessMesadata,
|
||||
geometry::primitive::PrimitiveShape,
|
||||
router::{navmesh::Navmesh, route::Route, trace::Trace, Router, RouterStatus},
|
||||
};
|
||||
|
||||
use super::{
|
||||
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace},
|
||||
Autorouter, AutorouterError, AutorouterStatus,
|
||||
};
|
||||
|
||||
pub struct Autoroute {
|
||||
ratlines_iter: Box<dyn Iterator<Item = EdgeIndex<usize>>>,
|
||||
route: Option<Route>,
|
||||
|
|
@ -83,14 +85,6 @@ impl Autoroute {
|
|||
|
||||
Ok(AutorouterStatus::Running)
|
||||
}
|
||||
|
||||
pub fn navmesh(&self) -> Option<&Navmesh> {
|
||||
self.route.as_ref().map(|route| route.navmesh())
|
||||
}
|
||||
|
||||
pub fn trace(&self) -> Option<&Trace> {
|
||||
self.route.as_ref().map(|route| route.trace())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetMaybeNavmesh for Autoroute {
|
||||
|
|
@ -104,3 +98,9 @@ impl GetMaybeTrace for Autoroute {
|
|||
self.route.as_ref().map(|route| route.trace())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetGhosts for Autoroute {
|
||||
fn ghosts(&self) -> &[PrimitiveShape] {
|
||||
self.route.as_ref().map_or(&[], |route| route.ghosts())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use crate::{
|
|||
Autorouter, AutorouterError, AutorouterStatus,
|
||||
},
|
||||
board::mesadata::AccessMesadata,
|
||||
drawing::graph::PrimitiveIndex,
|
||||
geometry::primitive::PrimitiveShape,
|
||||
layout::via::ViaWeight,
|
||||
router::{navmesh::Navmesh, trace::Trace},
|
||||
};
|
||||
|
|
@ -26,6 +28,11 @@ pub trait GetMaybeTrace {
|
|||
fn maybe_trace(&self) -> Option<&Trace>;
|
||||
}
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait GetGhosts {
|
||||
fn ghosts(&self) -> &[PrimitiveShape];
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum InvokerError {
|
||||
#[error(transparent)]
|
||||
|
|
@ -46,7 +53,7 @@ pub enum Command {
|
|||
PlaceVia(ViaWeight),
|
||||
}
|
||||
|
||||
#[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace)]
|
||||
#[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts)]
|
||||
pub enum Execute {
|
||||
Autoroute(Autoroute),
|
||||
PlaceVia(PlaceVia),
|
||||
|
|
@ -129,6 +136,12 @@ impl GetMaybeTrace for ExecuteWithStatus {
|
|||
}
|
||||
}
|
||||
|
||||
impl GetGhosts for ExecuteWithStatus {
|
||||
fn ghosts(&self) -> &[PrimitiveShape] {
|
||||
self.execute.ghosts()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Invoker<M: AccessMesadata> {
|
||||
autorouter: Autorouter<M>,
|
||||
history: History,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
use crate::{
|
||||
autorouter::{
|
||||
invoker::{GetMaybeNavmesh, GetMaybeTrace},
|
||||
Autorouter, AutorouterError,
|
||||
},
|
||||
board::mesadata::AccessMesadata,
|
||||
drawing::graph::PrimitiveIndex,
|
||||
geometry::primitive::PrimitiveShape,
|
||||
layout::via::ViaWeight,
|
||||
router::{navmesh::Navmesh, trace::Trace},
|
||||
};
|
||||
|
||||
use super::{
|
||||
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace},
|
||||
Autorouter, AutorouterError,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlaceVia {
|
||||
weight: ViaWeight,
|
||||
|
|
@ -37,3 +40,9 @@ impl GetMaybeTrace for PlaceVia {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl GetGhosts for PlaceVia {
|
||||
fn ghosts(&self) -> &[PrimitiveShape] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ use petgraph::{
|
|||
visit::{EdgeRef, IntoEdgeReferences},
|
||||
};
|
||||
use topola::{
|
||||
autorouter::invoker::{Command, ExecuteWithStatus, GetMaybeNavmesh, GetMaybeTrace, Invoker},
|
||||
autorouter::invoker::{
|
||||
Command, ExecuteWithStatus, GetGhosts, GetMaybeNavmesh, GetMaybeTrace, Invoker,
|
||||
},
|
||||
board::mesadata::AccessMesadata,
|
||||
drawing::{
|
||||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
|
|
@ -213,11 +215,11 @@ impl Viewport {
|
|||
}
|
||||
}
|
||||
|
||||
/*for ghost in shared_data.ghosts.iter() {
|
||||
painter.paint_primitive(&ghost, egui::Color32::from_rgb(75, 75, 150));
|
||||
}*/
|
||||
|
||||
if let Some(execute) = maybe_execute {
|
||||
for ghost in execute.ghosts().iter() {
|
||||
painter.paint_primitive(&ghost, egui::Color32::from_rgb(75, 75, 150));
|
||||
}
|
||||
|
||||
if let Some(navmesh) = execute.maybe_navmesh() {
|
||||
if let (origin, destination) = (navmesh.origin(), navmesh.destination()) {
|
||||
painter.paint_dot(
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub trait AstarStrategy<G, K, PS, PE, R>
|
||||
pub trait AstarStrategy<G, K, R>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
|
|
@ -108,7 +108,7 @@ where
|
|||
&mut self,
|
||||
graph: &'a G,
|
||||
edge: <&'a G as IntoEdgeReferences>::EdgeRef,
|
||||
) -> Result<(K, PS), PE>;
|
||||
) -> Option<K>;
|
||||
fn estimate_cost(&mut self, graph: &G, node: G::NodeId) -> K;
|
||||
}
|
||||
|
||||
|
|
@ -140,14 +140,14 @@ pub enum AstarError {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AstarStatus<G, K, PS, PE, R>
|
||||
pub enum AstarStatus<G, K, R>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
Probed(Result<PS, PE>),
|
||||
Probed,
|
||||
Visited,
|
||||
Finished(K, Vec<G::NodeId>, R),
|
||||
}
|
||||
|
|
@ -159,11 +159,7 @@ where
|
|||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
pub fn new<PS, PE, R>(
|
||||
graph: G,
|
||||
start: G::NodeId,
|
||||
strategy: &mut impl AstarStrategy<G, K, PS, PE, R>,
|
||||
) -> Self {
|
||||
pub fn new<R>(graph: G, start: G::NodeId, strategy: &mut impl AstarStrategy<G, K, R>) -> Self {
|
||||
let mut this = Self {
|
||||
graph,
|
||||
visit_next: BinaryHeap::new(),
|
||||
|
|
@ -183,10 +179,10 @@ where
|
|||
this
|
||||
}
|
||||
|
||||
pub fn step<PS, PE, R>(
|
||||
pub fn step<R>(
|
||||
&mut self,
|
||||
strategy: &mut impl AstarStrategy<G, K, PS, PE, R>,
|
||||
) -> Result<AstarStatus<G, K, PS, PE, R>, AstarError> {
|
||||
strategy: &mut impl AstarStrategy<G, K, R>,
|
||||
) -> Result<AstarStatus<G, K, R>, AstarError> {
|
||||
if let Some(curr_node) = self.maybe_curr_node {
|
||||
if let Some(edge_id) = self.edge_ids.pop_front() {
|
||||
// This lookup can be unwrapped without fear of panic since the node was
|
||||
|
|
@ -194,8 +190,7 @@ where
|
|||
let node_score = self.scores[&curr_node];
|
||||
let edge = (&self.graph).edge_ref(edge_id);
|
||||
|
||||
match strategy.probe(&self.graph, edge) {
|
||||
Ok((edge_cost, probe_status)) => {
|
||||
if let Some(edge_cost) = strategy.probe(&self.graph, edge) {
|
||||
let next = edge.target();
|
||||
let next_score = node_score + edge_cost;
|
||||
|
||||
|
|
@ -204,7 +199,7 @@ where
|
|||
// No need to add neighbors that we have already reached through a
|
||||
// shorter path than now.
|
||||
if *entry.get() <= next_score {
|
||||
return Ok(AstarStatus::Probed(Ok(probe_status)));
|
||||
return Ok(AstarStatus::Probed);
|
||||
}
|
||||
entry.insert(next_score);
|
||||
}
|
||||
|
|
@ -217,15 +212,13 @@ where
|
|||
let next_estimate_score =
|
||||
next_score + strategy.estimate_cost(&self.graph, next);
|
||||
self.visit_next.push(MinScored(next_estimate_score, next));
|
||||
}
|
||||
|
||||
return Ok(AstarStatus::Probed(Ok(probe_status)));
|
||||
return Ok(AstarStatus::Probed);
|
||||
}
|
||||
Err(probe_err) => return Ok(AstarStatus::Probed(Err(probe_err))),
|
||||
}
|
||||
} else {
|
||||
|
||||
self.maybe_curr_node = None;
|
||||
}
|
||||
}
|
||||
|
||||
let Some(MinScored(estimate_score, node)) = self.visit_next.pop() else {
|
||||
return Err(AstarError::NotFound);
|
||||
|
|
@ -258,10 +251,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn astar<G, K, PS, PE, R>(
|
||||
pub fn astar<G, K, R>(
|
||||
graph: G,
|
||||
start: G::NodeId,
|
||||
strategy: &mut impl AstarStrategy<G, K, PS, PE, R>,
|
||||
strategy: &mut impl AstarStrategy<G, K, R>,
|
||||
) -> Result<(K, Vec<G::NodeId>, R), AstarError>
|
||||
where
|
||||
G: GraphBase,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@ use crate::{
|
|||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
},
|
||||
geometry::{primitive::AccessPrimitiveShape, shape::AccessShape},
|
||||
geometry::{
|
||||
primitive::{AccessPrimitiveShape, PrimitiveShape},
|
||||
shape::AccessShape,
|
||||
},
|
||||
graph::GetPetgraphIndex,
|
||||
layout::Layout,
|
||||
router::{
|
||||
|
|
@ -33,6 +36,7 @@ use crate::{
|
|||
pub struct Route {
|
||||
astar: Astar<Navmesh, f64>,
|
||||
trace: Trace,
|
||||
ghosts: Vec<PrimitiveShape>,
|
||||
}
|
||||
|
||||
impl Route {
|
||||
|
|
@ -60,8 +64,13 @@ impl Route {
|
|||
|
||||
let mut strategy = RouterAstarStrategy::new(tracer, &mut trace, target);
|
||||
let astar = Astar::new(navmesh, source_navvertex, &mut strategy);
|
||||
let ghosts = vec![];
|
||||
|
||||
Self { astar, trace }
|
||||
Self {
|
||||
astar,
|
||||
trace,
|
||||
ghosts,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(
|
||||
|
|
@ -72,10 +81,13 @@ impl Route {
|
|||
let target = self.astar.graph.destination();
|
||||
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
|
||||
|
||||
match self.astar.step(&mut strategy)? {
|
||||
AstarStatus::Probed(..) | AstarStatus::Visited => Ok(RouterStatus::Running),
|
||||
let result = match self.astar.step(&mut strategy)? {
|
||||
AstarStatus::Probed | AstarStatus::Visited => Ok(RouterStatus::Running),
|
||||
AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)),
|
||||
}
|
||||
};
|
||||
|
||||
self.ghosts = strategy.ghosts;
|
||||
result
|
||||
}
|
||||
|
||||
pub fn navmesh(&self) -> &Navmesh {
|
||||
|
|
@ -85,4 +97,8 @@ impl Route {
|
|||
pub fn trace(&self) -> &Trace {
|
||||
&self.trace
|
||||
}
|
||||
|
||||
pub fn ghosts(&self) -> &[PrimitiveShape] {
|
||||
&self.ghosts
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,20 +10,23 @@ use crate::{
|
|||
head::{GetFace, Head},
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
Collision, Infringement, LayoutException,
|
||||
},
|
||||
geometry::{
|
||||
primitive::AccessPrimitiveShape,
|
||||
primitive::{AccessPrimitiveShape, PrimitiveShape},
|
||||
shape::{AccessShape, MeasureLength},
|
||||
},
|
||||
graph::GetPetgraphIndex,
|
||||
layout::Layout,
|
||||
router::{
|
||||
astar::{AstarError, AstarStatus, AstarStrategy, PathTracker},
|
||||
};
|
||||
|
||||
use super::{
|
||||
astar::{AstarError, AstarStrategy, PathTracker},
|
||||
draw::DrawException,
|
||||
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
|
||||
route::Route,
|
||||
trace::Trace,
|
||||
tracer::Tracer,
|
||||
},
|
||||
tracer::{Tracer, TracerException},
|
||||
};
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
|
|
@ -44,6 +47,7 @@ pub struct RouterAstarStrategy<'a, R: AccessRules> {
|
|||
pub tracer: Tracer<'a, R>,
|
||||
pub trace: &'a mut Trace,
|
||||
pub target: FixedDotIndex,
|
||||
pub ghosts: Vec<PrimitiveShape>,
|
||||
}
|
||||
|
||||
impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
|
||||
|
|
@ -52,6 +56,7 @@ impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
|
|||
tracer,
|
||||
trace,
|
||||
target,
|
||||
ghosts: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +76,7 @@ impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, (), (), BandFirstSegIndex>
|
||||
impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandFirstSegIndex>
|
||||
for RouterAstarStrategy<'a, R>
|
||||
{
|
||||
fn is_goal(
|
||||
|
|
@ -92,9 +97,9 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, (), (), BandFirstSegIndex>
|
|||
.ok()
|
||||
}
|
||||
|
||||
fn probe(&mut self, navmesh: &Navmesh, edge: NavmeshEdgeReference) -> Result<(f64, ()), ()> {
|
||||
fn probe(&mut self, navmesh: &Navmesh, edge: NavmeshEdgeReference) -> Option<f64> {
|
||||
if edge.target().petgraph_index() == self.target.petgraph_index() {
|
||||
return Err(());
|
||||
return None;
|
||||
}
|
||||
|
||||
let prev_bihead_length = self.bihead_length();
|
||||
|
|
@ -106,11 +111,32 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, (), (), BandFirstSegIndex>
|
|||
|
||||
let probe_length = self.bihead_length() - prev_bihead_length;
|
||||
|
||||
if result.is_ok() {
|
||||
match result {
|
||||
Ok(..) => {
|
||||
self.trace.undo_step(&mut self.tracer);
|
||||
Ok((probe_length, ()))
|
||||
} else {
|
||||
Err(())
|
||||
Some(probe_length)
|
||||
}
|
||||
Err(err) => {
|
||||
if let TracerException::CannotDraw(draw_err) = err {
|
||||
let layout_err = match draw_err {
|
||||
DrawException::NoTangents(..) => return None,
|
||||
DrawException::CannotFinishIn(.., layout_err) => layout_err,
|
||||
DrawException::CannotWrapAround(.., layout_err) => layout_err,
|
||||
};
|
||||
|
||||
let (ghost, ..) = match layout_err {
|
||||
LayoutException::NoTangents(..) => return None,
|
||||
LayoutException::Infringement(Infringement(ghost, obstacle)) => {
|
||||
(ghost, obstacle)
|
||||
}
|
||||
LayoutException::Collision(Collision(ghost, obstacle)) => (ghost, obstacle),
|
||||
LayoutException::AlreadyConnected(..) => return None,
|
||||
};
|
||||
|
||||
self.ghosts = vec![ghost];
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue