mirror of https://codeberg.org/topola/topola.git
router: calculate lengths and estimate costs for A* search
This commit is contained in:
parent
bc72aa62d0
commit
cded5eda7f
24
src/band.rs
24
src/band.rs
|
|
@ -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> {
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -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(
|
||||||
|
|
|
||||||
10
src/mesh.rs
10
src/mesh.rs
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
20
src/shape.rs
20
src/shape.rs
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue