mirror of https://codeberg.org/topola/topola.git
feat(router/navmesh): Reduce number of navedges
This provides a speedup, but may break squeezing through under bends in some corner cases.
This commit is contained in:
parent
63e1f7f25a
commit
1694227135
|
|
@ -2,10 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use std::iter::Skip;
|
|
||||||
|
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use itertools::{Itertools, Permutations};
|
|
||||||
use specctra_core::mesadata::AccessMesadata;
|
use specctra_core::mesadata::AccessMesadata;
|
||||||
|
|
||||||
use crate::autorouter::{
|
use crate::autorouter::{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
graph::{GetMaybeNet, MakePrimitiveRef},
|
graph::{GetMaybeNet, MakePrimitiveRef},
|
||||||
primitive::MakePrimitiveShape,
|
primitive::MakePrimitiveShape,
|
||||||
|
seg::SeqLooseSegIndex,
|
||||||
Collision, Infringement,
|
Collision, Infringement,
|
||||||
},
|
},
|
||||||
geometry::{
|
geometry::{
|
||||||
|
|
@ -105,17 +106,24 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
|
||||||
v.push(joints.0.into());
|
v.push(joints.0.into());
|
||||||
v.push(joints.1.into());
|
v.push(joints.1.into());
|
||||||
|
|
||||||
if let Some(seg0) = self.primitive(joints.0).seg() {
|
v.extend(
|
||||||
v.push(seg0.into());
|
self.collect_bend_bow_segs(bend)
|
||||||
}
|
.map(Into::<PrimitiveIndex>::into),
|
||||||
|
);
|
||||||
if let Some(seg1) = self.primitive(joints.1).seg() {
|
|
||||||
v.push(seg1.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn collect_bend_bow_segs(
|
||||||
|
&self,
|
||||||
|
bend: LooseBendIndex,
|
||||||
|
) -> impl Iterator<Item = SeqLooseSegIndex> {
|
||||||
|
let joints = self.primitive(bend).joints();
|
||||||
|
self.primitive(joints.0)
|
||||||
|
.seg()
|
||||||
|
.into_iter()
|
||||||
|
.chain(self.primitive(joints.1).seg().into_iter())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cut(
|
pub fn cut(
|
||||||
&self,
|
&self,
|
||||||
line: Line,
|
line: Line,
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,7 @@ impl Navmesh {
|
||||||
|
|
||||||
for prenavedge in prenavmesh.triangulation().edge_references() {
|
for prenavedge in prenavmesh.triangulation().edge_references() {
|
||||||
Self::add_prenavedge_to_repr_as_quadrinavedges(
|
Self::add_prenavedge_to_repr_as_quadrinavedges(
|
||||||
|
layout,
|
||||||
&mut graph,
|
&mut graph,
|
||||||
&prenavnode_to_navnodes,
|
&prenavnode_to_navnodes,
|
||||||
&overlapping_prenavnodes_unions,
|
&overlapping_prenavnodes_unions,
|
||||||
|
|
@ -266,6 +267,7 @@ impl Navmesh {
|
||||||
// quadrinavedges exist for every one of them.
|
// quadrinavedges exist for every one of them.
|
||||||
for constraint in prenavmesh.constraints() {
|
for constraint in prenavmesh.constraints() {
|
||||||
Self::add_prenavedge_to_repr_as_quadrinavedges(
|
Self::add_prenavedge_to_repr_as_quadrinavedges(
|
||||||
|
layout,
|
||||||
&mut graph,
|
&mut graph,
|
||||||
&prenavnode_to_navnodes,
|
&prenavnode_to_navnodes,
|
||||||
&overlapping_prenavnodes_unions,
|
&overlapping_prenavnodes_unions,
|
||||||
|
|
@ -364,26 +366,27 @@ impl Navmesh {
|
||||||
PrenavmeshNodeIndex,
|
PrenavmeshNodeIndex,
|
||||||
Vec<(NodeIndex<usize>, NodeIndex<usize>)>,
|
Vec<(NodeIndex<usize>, NodeIndex<usize>)>,
|
||||||
>,
|
>,
|
||||||
trianvertex: PrenavmeshNodeIndex,
|
prenavnode: PrenavmeshNodeIndex,
|
||||||
node: BinavnodeNodeIndex,
|
binavnode: BinavnodeNodeIndex,
|
||||||
) {
|
) {
|
||||||
let navnode1 = graph.add_node(NavnodeWeight {
|
let navnode1 = graph.add_node(NavnodeWeight {
|
||||||
binavnode: node,
|
binavnode,
|
||||||
maybe_sense: Some(RotationSense::Counterclockwise),
|
maybe_sense: Some(RotationSense::Counterclockwise),
|
||||||
});
|
});
|
||||||
|
|
||||||
let navnode2 = graph.add_node(NavnodeWeight {
|
let navnode2 = graph.add_node(NavnodeWeight {
|
||||||
binavnode: node,
|
binavnode,
|
||||||
maybe_sense: Some(RotationSense::Clockwise),
|
maybe_sense: Some(RotationSense::Clockwise),
|
||||||
});
|
});
|
||||||
|
|
||||||
prenavnode_to_navnodes
|
prenavnode_to_navnodes
|
||||||
.get_mut(&trianvertex)
|
.get_mut(&prenavnode)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push((navnode1, navnode2));
|
.push((navnode1, navnode2));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_prenavedge_to_repr_as_quadrinavedges(
|
fn add_prenavedge_to_repr_as_quadrinavedges(
|
||||||
|
layout: &Layout<impl AccessRules>,
|
||||||
graph: &mut UnGraph<NavnodeWeight, (), usize>,
|
graph: &mut UnGraph<NavnodeWeight, (), usize>,
|
||||||
prenavnode_to_navnodes: &BTreeMap<
|
prenavnode_to_navnodes: &BTreeMap<
|
||||||
PrenavmeshNodeIndex,
|
PrenavmeshNodeIndex,
|
||||||
|
|
@ -403,6 +406,7 @@ impl Navmesh {
|
||||||
));
|
));
|
||||||
|
|
||||||
Self::add_prenavedge_as_quadrinavedges(
|
Self::add_prenavedge_as_quadrinavedges(
|
||||||
|
layout,
|
||||||
graph,
|
graph,
|
||||||
prenavnode_to_navnodes,
|
prenavnode_to_navnodes,
|
||||||
from_prenavnode_repr,
|
from_prenavnode_repr,
|
||||||
|
|
@ -411,6 +415,7 @@ impl Navmesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_prenavedge_as_quadrinavedges(
|
fn add_prenavedge_as_quadrinavedges(
|
||||||
|
layout: &Layout<impl AccessRules>,
|
||||||
graph: &mut UnGraph<NavnodeWeight, (), usize>,
|
graph: &mut UnGraph<NavnodeWeight, (), usize>,
|
||||||
prenavnode_to_navnodes: &BTreeMap<
|
prenavnode_to_navnodes: &BTreeMap<
|
||||||
PrenavmeshNodeIndex,
|
PrenavmeshNodeIndex,
|
||||||
|
|
@ -420,15 +425,58 @@ impl Navmesh {
|
||||||
to_prenavnode: PrenavmeshNodeIndex,
|
to_prenavnode: PrenavmeshNodeIndex,
|
||||||
) {
|
) {
|
||||||
for (from_navnode1, from_navnode2) in prenavnode_to_navnodes[&from_prenavnode].iter() {
|
for (from_navnode1, from_navnode2) in prenavnode_to_navnodes[&from_prenavnode].iter() {
|
||||||
for (to_navnode1, to_navnode2) in prenavnode_to_navnodes[&to_prenavnode].iter() {
|
let from_binavnode = graph.node_weight(*from_navnode1).unwrap().binavnode;
|
||||||
|
|
||||||
|
if let Some((to_navnode1, to_navnode2)) = prenavnode_to_navnodes[&to_prenavnode]
|
||||||
|
.iter()
|
||||||
|
.find(|(to_navnode1, _)| {
|
||||||
|
let to_binavnode = graph.node_weight(*to_navnode1).unwrap().binavnode;
|
||||||
|
|
||||||
|
Self::are_binavnodes_joined(layout, from_binavnode, to_binavnode)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
// Add binavedge.
|
||||||
graph.update_edge(*from_navnode1, *to_navnode1, ());
|
graph.update_edge(*from_navnode1, *to_navnode1, ());
|
||||||
|
graph.update_edge(*from_navnode2, *to_navnode2, ());
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (to_navnode1, to_navnode2) in prenavnode_to_navnodes[&to_prenavnode].iter() {
|
||||||
|
// Add binavedge.
|
||||||
|
graph.update_edge(*from_navnode1, *to_navnode1, ());
|
||||||
|
graph.update_edge(*from_navnode2, *to_navnode2, ());
|
||||||
|
|
||||||
|
// Add two more navedges to upgrade the binavedge to form a
|
||||||
|
// quadrinavedge.
|
||||||
graph.update_edge(*from_navnode1, *to_navnode2, ());
|
graph.update_edge(*from_navnode1, *to_navnode2, ());
|
||||||
graph.update_edge(*from_navnode2, *to_navnode1, ());
|
graph.update_edge(*from_navnode2, *to_navnode1, ());
|
||||||
graph.update_edge(*from_navnode2, *to_navnode2, ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn are_binavnodes_joined(
|
||||||
|
layout: &Layout<impl AccessRules>,
|
||||||
|
from_binavnode: BinavnodeNodeIndex,
|
||||||
|
to_binavnode: BinavnodeNodeIndex,
|
||||||
|
) -> bool {
|
||||||
|
let BinavnodeNodeIndex::LooseBend(from_bend) = from_binavnode else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let BinavnodeNodeIndex::LooseBend(to_bend) = to_binavnode else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let from_bend_bow_segs: Vec<_> =
|
||||||
|
layout.drawing().collect_bend_bow_segs(from_bend).collect();
|
||||||
|
let to_bend_bow_segs: Vec<_> = layout.drawing().collect_bend_bow_segs(to_bend).collect();
|
||||||
|
|
||||||
|
from_bend_bow_segs
|
||||||
|
.iter()
|
||||||
|
.any(|seg| to_bend_bow_segs.contains(seg))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the origin node.
|
/// Returns the origin node.
|
||||||
pub fn origin(&self) -> FixedDotIndex {
|
pub fn origin(&self) -> FixedDotIndex {
|
||||||
self.origin
|
self.origin
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
graph::GenericIndex,
|
graph::GenericIndex,
|
||||||
layout::{poly::PolyWeight, Layout},
|
layout::{poly::PolyWeight, Layout},
|
||||||
stepper::{Abort, EstimateProgress},
|
stepper::Abort,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,13 @@ impl<
|
||||||
> 0)
|
> 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exists_constraint(&self, from: I, to: I) -> bool {
|
||||||
|
self.cdt.exists_constraint(
|
||||||
|
self.trianvertex_to_handle[from].unwrap(),
|
||||||
|
self.trianvertex_to_handle[to].unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn intersects_constraint(&self, from: &VW, to: &VW) -> bool {
|
pub fn intersects_constraint(&self, from: &VW, to: &VW) -> bool {
|
||||||
self.cdt
|
self.cdt
|
||||||
.intersects_constraint(from.position(), to.position())
|
.intersects_constraint(from.position(), to.position())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue