router: calculate lengths and estimate costs for A* search

This commit is contained in:
Mikolaj Wielgus 2024-01-24 00:25:53 +00:00
parent bc72aa62d0
commit cded5eda7f
5 changed files with 76 additions and 14 deletions

View File

@ -1,10 +1,11 @@
use crate::{ use crate::{
connectivity::{BandIndex, BandWeight, ConnectivityWeight, GetNet}, connectivity::{BandIndex, BandWeight, ConnectivityWeight, GetNet},
geometry::{DotIndex, FixedDotIndex}, geometry::{DotIndex, FixedDotIndex, GeometryIndex, MakePrimitive},
graph::GetNodeIndex, graph::GetNodeIndex,
layout::Layout, layout::Layout,
loose::{GetNextLoose, LooseIndex}, loose::{GetNextLoose, LooseIndex},
primitive::{GetEnds, GetOtherEnd}, primitive::{GetEnds, GetOtherEnd, MakeShape},
shape::ShapeTrait,
}; };
pub struct Band<'a> { pub struct Band<'a> {
@ -60,6 +61,25 @@ impl<'a> Band<'a> {
_ => unreachable!(), _ => unreachable!(),
} }
} }
pub fn length(&self) -> f64 {
let mut maybe_loose = self.layout.primitive(self.from()).first_loose(self.index);
let mut prev = None;
let mut length = 0.0;
while let Some(loose) = maybe_loose {
length += GeometryIndex::from(loose)
.primitive(self.layout)
.shape()
.length();
let prev_prev = prev;
prev = maybe_loose;
maybe_loose = self.layout.loose(loose).next_loose(prev_prev);
}
length
}
} }
impl<'a> GetNet for Band<'a> { impl<'a> GetNet for Band<'a> {

View File

@ -496,8 +496,8 @@ fn main() -> Result<(), anyhow::Error> {
let _ = router.route_band( let _ = router.route_band(
dot_start, dot_start,
dot_end, dot_end,
&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
)?; )?;
render_times( render_times(
@ -528,8 +528,8 @@ fn main() -> Result<(), anyhow::Error> {
let band2 = router.route_band( let band2 = router.route_band(
dot_start2, dot_start2,
dot_end2, dot_end2,
&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
)?; )?;
render_times( render_times(
@ -549,8 +549,8 @@ fn main() -> Result<(), anyhow::Error> {
let band3 = router.route_band( let band3 = router.route_band(
dot_start3, dot_start3,
dot_end3, dot_end3,
&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
)?; )?;
render_times( render_times(

View File

@ -33,6 +33,16 @@ pub enum TriangulationVertexIndex {
FixedBend(FixedBendIndex), FixedBend(FixedBendIndex),
} }
impl From<VertexIndex> for GeometryIndex {
fn from(vertex: VertexIndex) -> Self {
match vertex {
VertexIndex::FixedDot(dot) => GeometryIndex::FixedDot(dot),
VertexIndex::FixedBend(bend) => GeometryIndex::FixedBend(bend),
VertexIndex::LooseBend(bend) => GeometryIndex::LooseBend(bend),
}
}
}
impl From<TriangulationVertexIndex> for VertexIndex { impl From<TriangulationVertexIndex> for VertexIndex {
fn from(vertex: TriangulationVertexIndex) -> Self { fn from(vertex: TriangulationVertexIndex) -> Self {
match vertex { match vertex {

View File

@ -1,4 +1,5 @@
use geo::geometry::Point; use geo::geometry::Point;
use geo::EuclideanDistance;
use petgraph::visit::EdgeRef; use petgraph::visit::EdgeRef;
use spade::InsertionError; use spade::InsertionError;
use thiserror::Error; use thiserror::Error;
@ -6,14 +7,16 @@ use thiserror::Error;
use crate::astar::{astar, AstarStrategy, PathTracker}; use crate::astar::{astar, AstarStrategy, PathTracker};
use crate::connectivity::{BandIndex, GetNet}; use crate::connectivity::{BandIndex, GetNet};
use crate::draw::DrawException; use crate::draw::DrawException;
use crate::geometry::{FixedDotIndex, FixedDotWeight}; use crate::geometry::{FixedDotIndex, FixedDotWeight, GeometryIndex, MakePrimitive};
use crate::guide::HeadTrait; use crate::guide::HeadTrait;
use crate::layout::Layout; use crate::layout::Layout;
use crate::math::Circle; use crate::math::Circle;
use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex}; use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
use crate::primitive::MakeShape;
use crate::rules::Rules; use crate::rules::Rules;
use crate::shape::ShapeTrait;
use crate::tracer::{Trace, Tracer}; use crate::tracer::{Trace, Tracer};
#[derive(Error, Debug, Clone, Copy)] #[derive(Error, Debug, Clone, Copy)]
@ -70,7 +73,7 @@ impl<'a, RO: RouterObserver> RouterAstarStrategy<'a, RO> {
} }
} }
impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'a, RO> { impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, f64> for RouterAstarStrategy<'a, RO> {
fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool { fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool {
let new_path = tracker.reconstruct_path_to(vertex); let new_path = tracker.reconstruct_path_to(vertex);
@ -82,27 +85,36 @@ impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'
self.tracer.finish(&mut self.trace, self.to, 5.0).is_ok() self.tracer.finish(&mut self.trace, self.to, 5.0).is_ok()
} }
fn edge_cost(&mut self, edge: MeshEdgeReference) -> Option<u64> { fn edge_cost(&mut self, edge: MeshEdgeReference) -> Option<f64> {
self.observer.before_probe(&self.tracer, &self.trace, edge); self.observer.before_probe(&self.tracer, &self.trace, edge);
if edge.target() == self.to.into() { if edge.target() == self.to.into() {
return None; return None;
} }
let before_probe_length = self.tracer.layout.band(self.trace.head.band()).length();
let result = self.tracer.step(&mut self.trace, edge.target(), 5.0); let result = self.tracer.step(&mut self.trace, edge.target(), 5.0);
self.observer self.observer
.on_probe(&self.tracer, &self.trace, edge, result); .on_probe(&self.tracer, &self.trace, edge, result);
let probe_length = self.tracer.layout.band(self.trace.head.band()).length();
if result.is_ok() { if result.is_ok() {
self.tracer.undo_step(&mut self.trace); self.tracer.undo_step(&mut self.trace);
Some(1) Some(probe_length - before_probe_length)
} else { } else {
None None
} }
} }
fn estimate_cost(&mut self, vertex: VertexIndex) -> u64 { fn estimate_cost(&mut self, vertex: VertexIndex) -> f64 {
self.observer.on_estimate(&self.tracer, vertex); self.observer.on_estimate(&self.tracer, vertex);
0 let start_point = GeometryIndex::from(vertex)
.primitive(self.tracer.layout)
.shape()
.center();
let end_point = self.tracer.layout.primitive(self.to).shape().center();
end_point.euclidean_distance(&start_point)
} }
} }

View File

@ -11,6 +11,7 @@ pub trait ShapeTrait {
fn intersects(&self, other: &Shape) -> bool; fn intersects(&self, other: &Shape) -> bool;
fn envelope(&self) -> AABB<[f64; 2]>; fn envelope(&self) -> AABB<[f64; 2]>;
fn width(&self) -> f64; fn width(&self) -> f64;
fn length(&self) -> f64;
} }
#[enum_dispatch(ShapeTrait)] #[enum_dispatch(ShapeTrait)]
@ -72,6 +73,10 @@ impl ShapeTrait for DotShape {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.c.r * 2.0 self.c.r * 2.0
} }
fn length(&self) -> f64 {
0.0
}
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -151,6 +156,10 @@ impl ShapeTrait for SegShape {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.width self.width
} }
fn length(&self) -> f64 {
self.to.euclidean_distance(&self.from)
}
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -247,6 +256,17 @@ impl ShapeTrait for BendShape {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.width self.width
} }
fn length(&self) -> f64 {
// We obtain the angle from the law of cosines and multiply with radius to get the length.
let d = self.to.euclidean_distance(&self.from);
if d > 0.0 {
(1.0 - d * d / (2.0 * d * d)).acos()
} else {
0.0
}
}
} }
impl RTreeObject for Shape { impl RTreeObject for Shape {