mirror of https://codeberg.org/topola/topola.git
refactor(geometry/geometry): Replace `NodeIndex<usize>` with just `usize`
This is a step towards ceasing to use Petgraph as internal storage for geometry.
This commit is contained in:
parent
6a2102e0a2
commit
e0cfc521ef
|
|
@ -8,7 +8,6 @@ use enum_dispatch::enum_dispatch;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
use petgraph::{
|
use petgraph::{
|
||||||
data::Element,
|
data::Element,
|
||||||
graph::NodeIndex,
|
|
||||||
prelude::StableUnGraph,
|
prelude::StableUnGraph,
|
||||||
unionfind::UnionFind,
|
unionfind::UnionFind,
|
||||||
visit::{EdgeRef, IntoEdgeReferences, NodeIndexable},
|
visit::{EdgeRef, IntoEdgeReferences, NodeIndexable},
|
||||||
|
|
@ -78,7 +77,7 @@ impl Ratsnest {
|
||||||
let mut unionfind = UnionFind::new(layout.drawing().geometry().graph().node_bound());
|
let mut unionfind = UnionFind::new(layout.drawing().geometry().graph().node_bound());
|
||||||
|
|
||||||
for edge in layout.drawing().geometry().graph().edge_references() {
|
for edge in layout.drawing().geometry().graph().edge_references() {
|
||||||
unionfind.union(edge.source(), edge.target());
|
unionfind.union(edge.source().index(), edge.target().index());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ use crate::{
|
||||||
graph::{GenericIndex, GetIndex},
|
graph::{GenericIndex, GetIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
|
|
||||||
#[enum_dispatch(GetIndex, MakePrimitiveRef)]
|
#[enum_dispatch(GetIndex, MakePrimitiveRef)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub enum BendIndex {
|
pub enum BendIndex {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
|
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
graph::{GetMaybeNet, MakePrimitiveRef, PrimitiveIndex, PrimitiveWeight},
|
graph::{GetMaybeNet, MakePrimitiveRef, PrimitiveIndex, PrimitiveWeight},
|
||||||
|
|
|
||||||
|
|
@ -570,7 +570,7 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
|
||||||
let core = *self
|
let core = *self
|
||||||
.recording_geometry_with_rtree
|
.recording_geometry_with_rtree
|
||||||
.graph()
|
.graph()
|
||||||
.neighbors(inner.index())
|
.neighbors(inner.index().into())
|
||||||
.filter(|ni| {
|
.filter(|ni| {
|
||||||
matches!(
|
matches!(
|
||||||
self.recording_geometry_with_rtree
|
self.recording_geometry_with_rtree
|
||||||
|
|
@ -578,14 +578,14 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
|
||||||
.edge_weight(
|
.edge_weight(
|
||||||
self.recording_geometry_with_rtree
|
self.recording_geometry_with_rtree
|
||||||
.graph()
|
.graph()
|
||||||
.find_edge(inner.index(), *ni)
|
.find_edge(inner.index().into(), *ni)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
GeometryLabel::Core
|
GeometryLabel::Core
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(FixedDotIndex::new)
|
.map(|node| FixedDotIndex::new(node.index()))
|
||||||
.collect::<Vec<FixedDotIndex>>()
|
.collect::<Vec<FixedDotIndex>>()
|
||||||
.first()
|
.first()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use petgraph::{stable_graph::NodeIndex, visit::Walker};
|
use petgraph::visit::Walker;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::GetLayer,
|
geometry::GetLayer,
|
||||||
|
|
@ -115,7 +114,7 @@ pub enum PrimitiveWeight {
|
||||||
impl crate::geometry::Retag for PrimitiveWeight {
|
impl crate::geometry::Retag for PrimitiveWeight {
|
||||||
type Index = PrimitiveIndex;
|
type Index = PrimitiveIndex;
|
||||||
|
|
||||||
fn retag(&self, index: NodeIndex<usize>) -> PrimitiveIndex {
|
fn retag(&self, index: usize) -> PrimitiveIndex {
|
||||||
macro_rules! match_self {
|
macro_rules! match_self {
|
||||||
($self:expr, $($kind:ident),*,) => {{
|
($self:expr, $($kind:ident),*,) => {{
|
||||||
match $self {
|
match $self {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::Drawing,
|
drawing::Drawing,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
|
|
@ -200,7 +199,7 @@ impl<'a, W, CW, Cel, R> GenericPrimitive<'a, W, CW, Cel, R> {
|
||||||
.drawing
|
.drawing
|
||||||
.geometry()
|
.geometry()
|
||||||
.graph()
|
.graph()
|
||||||
.node_weight(self.index.index())
|
.node_weight(self.index.index().into())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
{
|
{
|
||||||
*weight
|
*weight
|
||||||
|
|
@ -226,7 +225,7 @@ impl<W, CW, Cel, R> GetDrawing for GenericPrimitive<'_, W, CW, Cel, R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W, CW, Cel, R> GetIndex for GenericPrimitive<'_, W, CW, Cel, R> {
|
impl<W, CW, Cel, R> GetIndex for GenericPrimitive<'_, W, CW, Cel, R> {
|
||||||
fn index(&self) -> NodeIndex<usize> {
|
fn index(&self) -> usize {
|
||||||
self.index.index()
|
self.index.index()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@ use crate::{
|
||||||
graph::{GenericIndex, GetIndex},
|
graph::{GenericIndex, GetIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
|
|
||||||
#[enum_dispatch(GetIndex, MakePrimitiveRef)]
|
#[enum_dispatch(GetIndex, MakePrimitiveRef)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
|
||||||
pub enum SegIndex {
|
pub enum SegIndex {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use core::marker::PhantomData;
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
use petgraph::{
|
use petgraph::{
|
||||||
stable_graph::{NodeIndex, StableDiGraph},
|
stable_graph::StableDiGraph,
|
||||||
visit::{EdgeRef, Walker},
|
visit::{EdgeRef, Walker},
|
||||||
Direction::{Incoming, Outgoing},
|
Direction::{Incoming, Outgoing},
|
||||||
};
|
};
|
||||||
|
|
@ -31,7 +31,7 @@ use crate::{
|
||||||
|
|
||||||
pub trait Retag {
|
pub trait Retag {
|
||||||
type Index: Sized + GetIndex + PartialEq + Copy;
|
type Index: Sized + GetIndex + PartialEq + Copy;
|
||||||
fn retag(&self, index: NodeIndex<usize>) -> Self::Index;
|
fn retag(&self, index: usize) -> Self::Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[enum_dispatch]
|
#[enum_dispatch]
|
||||||
|
|
@ -75,7 +75,7 @@ pub enum GenericNode<P, C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: GetIndex, C: GetIndex> GetIndex for GenericNode<P, C> {
|
impl<P: GetIndex, C: GetIndex> GetIndex for GenericNode<P, C> {
|
||||||
fn index(&self) -> NodeIndex<usize> {
|
fn index(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::Primitive(x) => x.index(),
|
Self::Primitive(x) => x.index(),
|
||||||
Self::Compound(x) => x.index(),
|
Self::Compound(x) => x.index(),
|
||||||
|
|
@ -149,11 +149,11 @@ impl<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI> Geometry<PW, DW, SW, BW, CW, Cel,
|
||||||
&self.graph
|
&self.graph
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primitive_weight(&self, index: NodeIndex<usize>) -> PW
|
fn primitive_weight(&self, index: usize) -> PW
|
||||||
where
|
where
|
||||||
PW: Copy,
|
PW: Copy,
|
||||||
{
|
{
|
||||||
if let GenericNode::Primitive(weight) = self.graph.node_weight(index).unwrap() {
|
if let GenericNode::Primitive(weight) = self.graph.node_weight(index.into()).unwrap() {
|
||||||
*weight
|
*weight
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
@ -175,7 +175,11 @@ impl<
|
||||||
> Geometry<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
> Geometry<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
{
|
{
|
||||||
pub fn add_dot<W: AccessDotWeight + Into<PW>>(&mut self, weight: W) -> GenericIndex<W> {
|
pub fn add_dot<W: AccessDotWeight + Into<PW>>(&mut self, weight: W) -> GenericIndex<W> {
|
||||||
GenericIndex::<W>::new(self.graph.add_node(GenericNode::Primitive(weight.into())))
|
GenericIndex::<W>::new(
|
||||||
|
self.graph
|
||||||
|
.add_node(GenericNode::Primitive(weight.into()))
|
||||||
|
.index(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_dot_at_index<W: AccessDotWeight + Into<PW>>(
|
pub(super) fn add_dot_at_index<W: AccessDotWeight + Into<PW>>(
|
||||||
|
|
@ -184,7 +188,7 @@ impl<
|
||||||
weight: W,
|
weight: W,
|
||||||
) {
|
) {
|
||||||
self.graph
|
self.graph
|
||||||
.update_node(dot.index(), GenericNode::Primitive(weight.into()));
|
.update_node(dot.index().into(), GenericNode::Primitive(weight.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_seg<W: AccessSegWeight + Into<PW>>(
|
pub fn add_seg<W: AccessSegWeight + Into<PW>>(
|
||||||
|
|
@ -193,8 +197,11 @@ impl<
|
||||||
to: DI,
|
to: DI,
|
||||||
weight: W,
|
weight: W,
|
||||||
) -> GenericIndex<W> {
|
) -> GenericIndex<W> {
|
||||||
let seg =
|
let seg = GenericIndex::<W>::new(
|
||||||
GenericIndex::<W>::new(self.graph.add_node(GenericNode::Primitive(weight.into())));
|
self.graph
|
||||||
|
.add_node(GenericNode::Primitive(weight.into()))
|
||||||
|
.index(),
|
||||||
|
);
|
||||||
self.init_seg_joints(seg, from, to);
|
self.init_seg_joints(seg, from, to);
|
||||||
seg
|
seg
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +214,7 @@ impl<
|
||||||
weight: W,
|
weight: W,
|
||||||
) {
|
) {
|
||||||
self.graph
|
self.graph
|
||||||
.update_node(seg.index(), GenericNode::Primitive(weight.into()));
|
.update_node(seg.index().into(), GenericNode::Primitive(weight.into()));
|
||||||
self.init_seg_joints(seg, from, to);
|
self.init_seg_joints(seg, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,10 +224,13 @@ impl<
|
||||||
from: DI,
|
from: DI,
|
||||||
to: DI,
|
to: DI,
|
||||||
) {
|
) {
|
||||||
|
self.graph.update_edge(
|
||||||
|
from.index().into(),
|
||||||
|
seg.index().into(),
|
||||||
|
GeometryLabel::Joined,
|
||||||
|
);
|
||||||
self.graph
|
self.graph
|
||||||
.update_edge(from.index(), seg.index(), GeometryLabel::Joined);
|
.update_edge(seg.index().into(), to.index().into(), GeometryLabel::Joined);
|
||||||
self.graph
|
|
||||||
.update_edge(seg.index(), to.index(), GeometryLabel::Joined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_joined_with<I>(&self, seg: I, node: GenericNode<PI, GenericIndex<CW>>) -> bool
|
pub fn is_joined_with<I>(&self, seg: I, node: GenericNode<PI, GenericIndex<CW>>) -> bool
|
||||||
|
|
@ -232,7 +242,7 @@ impl<
|
||||||
match node {
|
match node {
|
||||||
GenericNode::Primitive(prim) => self
|
GenericNode::Primitive(prim) => self
|
||||||
.graph
|
.graph
|
||||||
.find_edge_undirected(seg.index(), prim.index())
|
.find_edge_undirected(seg.index().into(), prim.index().into())
|
||||||
.map_or(false, |(eidx, _direction)| {
|
.map_or(false, |(eidx, _direction)| {
|
||||||
matches!(self.graph.edge_weight(eidx).unwrap(), GeometryLabel::Joined)
|
matches!(self.graph.edge_weight(eidx).unwrap(), GeometryLabel::Joined)
|
||||||
}),
|
}),
|
||||||
|
|
@ -249,8 +259,11 @@ impl<
|
||||||
core: DI,
|
core: DI,
|
||||||
weight: W,
|
weight: W,
|
||||||
) -> GenericIndex<W> {
|
) -> GenericIndex<W> {
|
||||||
let bend =
|
let bend = GenericIndex::<W>::new(
|
||||||
GenericIndex::<W>::new(self.graph.add_node(GenericNode::Primitive(weight.into())));
|
self.graph
|
||||||
|
.add_node(GenericNode::Primitive(weight.into()))
|
||||||
|
.index(),
|
||||||
|
);
|
||||||
self.init_bend_joints_and_core(bend, from, to, core);
|
self.init_bend_joints_and_core(bend, from, to, core);
|
||||||
bend
|
bend
|
||||||
}
|
}
|
||||||
|
|
@ -264,13 +277,13 @@ impl<
|
||||||
weight: W,
|
weight: W,
|
||||||
) {
|
) {
|
||||||
self.graph
|
self.graph
|
||||||
.update_node(bend.index(), GenericNode::Primitive(weight.into()));
|
.update_node(bend.index().into(), GenericNode::Primitive(weight.into()));
|
||||||
self.init_bend_joints_and_core(bend, from, to, core);
|
self.init_bend_joints_and_core(bend, from, to, core);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_compound_at_index(&mut self, compound: GenericIndex<CW>, weight: CW) {
|
pub(super) fn add_compound_at_index(&mut self, compound: GenericIndex<CW>, weight: CW) {
|
||||||
self.graph
|
self.graph
|
||||||
.update_node(compound.index(), GenericNode::Compound(weight));
|
.update_node(compound.index().into(), GenericNode::Compound(weight));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_bend_joints_and_core<W: AccessBendWeight + Into<PW>>(
|
fn init_bend_joints_and_core<W: AccessBendWeight + Into<PW>>(
|
||||||
|
|
@ -280,58 +293,80 @@ impl<
|
||||||
to: DI,
|
to: DI,
|
||||||
core: DI,
|
core: DI,
|
||||||
) {
|
) {
|
||||||
self.graph
|
self.graph.update_edge(
|
||||||
.update_edge(from.index(), bend.index(), GeometryLabel::Joined);
|
from.index().into(),
|
||||||
self.graph
|
bend.index().into(),
|
||||||
.update_edge(bend.index(), to.index(), GeometryLabel::Joined);
|
GeometryLabel::Joined,
|
||||||
self.graph
|
);
|
||||||
.update_edge(bend.index(), core.index(), GeometryLabel::Core);
|
self.graph.update_edge(
|
||||||
|
bend.index().into(),
|
||||||
|
to.index().into(),
|
||||||
|
GeometryLabel::Joined,
|
||||||
|
);
|
||||||
|
self.graph.update_edge(
|
||||||
|
bend.index().into(),
|
||||||
|
core.index().into(),
|
||||||
|
GeometryLabel::Core,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_primitive(&mut self, primitive: PI) {
|
pub fn remove_primitive(&mut self, primitive: PI) {
|
||||||
debug_assert!(self.graph.remove_node(primitive.index()).is_some());
|
debug_assert!(self.graph.remove_node(primitive.index().into()).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_dot(&mut self, dot: DI, to: Point) {
|
pub fn move_dot(&mut self, dot: DI, to: Point) {
|
||||||
let mut weight = self.dot_weight(dot);
|
let mut weight = self.dot_weight(dot);
|
||||||
weight.set_pos(to);
|
weight.set_pos(to);
|
||||||
*self.graph.node_weight_mut(dot.index()).unwrap() = GenericNode::Primitive(weight.into());
|
*self.graph.node_weight_mut(dot.index().into()).unwrap() =
|
||||||
|
GenericNode::Primitive(weight.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift_bend(&mut self, bend: BI, offset: f64) {
|
pub fn shift_bend(&mut self, bend: BI, offset: f64) {
|
||||||
let mut weight = self.bend_weight(bend);
|
let mut weight = self.bend_weight(bend);
|
||||||
weight.set_offset(offset);
|
weight.set_offset(offset);
|
||||||
*self.graph.node_weight_mut(bend.index()).unwrap() = GenericNode::Primitive(weight.into());
|
*self.graph.node_weight_mut(bend.index().into()).unwrap() =
|
||||||
|
GenericNode::Primitive(weight.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flip_bend(&mut self, bend: BI) {
|
pub fn flip_bend(&mut self, bend: BI) {
|
||||||
let (from, to) = self.bend_joints(bend);
|
let (from, to) = self.bend_joints(bend);
|
||||||
let from_edge_weight = self
|
let from_edge_weight = self
|
||||||
.graph
|
.graph
|
||||||
.remove_edge(self.graph.find_edge(from.index(), bend.index()).unwrap())
|
.remove_edge(
|
||||||
|
self.graph
|
||||||
|
.find_edge(from.index().into(), bend.index().into())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let to_edge_weight = self
|
let to_edge_weight = self
|
||||||
.graph
|
.graph
|
||||||
.remove_edge(self.graph.find_edge(bend.index(), to.index()).unwrap())
|
.remove_edge(
|
||||||
|
self.graph
|
||||||
|
.find_edge(bend.index().into(), to.index().into())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.graph
|
self.graph
|
||||||
.update_edge(from.index(), bend.index(), to_edge_weight);
|
.update_edge(from.index().into(), bend.index().into(), to_edge_weight);
|
||||||
self.graph
|
self.graph
|
||||||
.update_edge(bend.index(), to.index(), from_edge_weight);
|
.update_edge(bend.index().into(), to.index().into(), from_edge_weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option<BI>) {
|
pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option<BI>) {
|
||||||
if let Some(old_inner_edge) = self
|
if let Some(old_inner_edge) = self
|
||||||
.graph
|
.graph
|
||||||
.edges_directed(bend.index(), Incoming)
|
.edges_directed(bend.index().into(), Incoming)
|
||||||
.find(|edge| matches!(edge.weight(), GeometryLabel::Outer))
|
.find(|edge| matches!(edge.weight(), GeometryLabel::Outer))
|
||||||
{
|
{
|
||||||
debug_assert!(self.graph.remove_edge(old_inner_edge.id()).is_some());
|
debug_assert!(self.graph.remove_edge(old_inner_edge.id()).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(new_inner) = maybe_new_inner {
|
if let Some(new_inner) = maybe_new_inner {
|
||||||
self.graph
|
self.graph.update_edge(
|
||||||
.update_edge(new_inner.index(), bend.index(), GeometryLabel::Outer);
|
new_inner.index().into(),
|
||||||
|
bend.index().into(),
|
||||||
|
GeometryLabel::Outer,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,7 +385,7 @@ impl<
|
||||||
PrimitiveShape::Seg(SegShape {
|
PrimitiveShape::Seg(SegShape {
|
||||||
from: self.dot_weight(from).pos(),
|
from: self.dot_weight(from).pos(),
|
||||||
to: self.dot_weight(to).pos(),
|
to: self.dot_weight(to).pos(),
|
||||||
width: self.primitive_weight(seg.index()).width(),
|
width: self.primitive_weight(seg.index().into()).width(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,7 +399,7 @@ impl<
|
||||||
pos: core_weight.pos(),
|
pos: core_weight.pos(),
|
||||||
r: self.inner_radius(bend),
|
r: self.inner_radius(bend),
|
||||||
},
|
},
|
||||||
width: self.primitive_weight(bend.index()).width(),
|
width: self.primitive_weight(bend.index().into()).width(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,25 +417,27 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dot_weight(&self, dot: DI) -> DW {
|
pub fn dot_weight(&self, dot: DI) -> DW {
|
||||||
self.primitive_weight(dot.index())
|
self.primitive_weight(dot.index().into())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seg_weight(&self, seg: SI) -> SW {
|
pub fn seg_weight(&self, seg: SI) -> SW {
|
||||||
self.primitive_weight(seg.index())
|
self.primitive_weight(seg.index().into())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bend_weight(&self, bend: BI) -> BW {
|
pub fn bend_weight(&self, bend: BI) -> BW {
|
||||||
self.primitive_weight(bend.index())
|
self.primitive_weight(bend.index().into())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compound_weight(&self, compound: GenericIndex<CW>) -> &CW {
|
pub fn compound_weight(&self, compound: GenericIndex<CW>) -> &CW {
|
||||||
if let GenericNode::Compound(weight) = self.graph.node_weight(compound.index()).unwrap() {
|
if let GenericNode::Compound(weight) =
|
||||||
|
self.graph.node_weight(compound.index().into()).unwrap()
|
||||||
|
{
|
||||||
weight
|
weight
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
@ -409,10 +446,10 @@ impl<
|
||||||
|
|
||||||
fn core_weight(&self, bend: BI) -> DW {
|
fn core_weight(&self, bend: BI) -> DW {
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(bend.index(), Outgoing)
|
.edges_directed(bend.index().into(), Outgoing)
|
||||||
.find(|edge| matches!(edge.weight(), GeometryLabel::Core))
|
.find(|edge| matches!(edge.weight(), GeometryLabel::Core))
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
self.primitive_weight(edge.target())
|
self.primitive_weight(edge.target().index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
|
|
@ -421,13 +458,13 @@ impl<
|
||||||
|
|
||||||
pub fn joineds(&self, node: PI) -> impl Iterator<Item = PI> + '_ {
|
pub fn joineds(&self, node: PI) -> impl Iterator<Item = PI> + '_ {
|
||||||
self.graph
|
self.graph
|
||||||
.neighbors_undirected(node.index())
|
.neighbors_undirected(node.index().into())
|
||||||
.filter(move |ni| {
|
.filter(move |ni| {
|
||||||
matches!(
|
matches!(
|
||||||
self.graph
|
self.graph
|
||||||
.edge_weight(
|
.edge_weight(
|
||||||
self.graph
|
self.graph
|
||||||
.find_edge_undirected(node.index(), *ni)
|
.find_edge_undirected(node.index().into(), *ni)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0,
|
.0,
|
||||||
)
|
)
|
||||||
|
|
@ -435,7 +472,7 @@ impl<
|
||||||
GeometryLabel::Joined
|
GeometryLabel::Joined
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(|ni| self.primitive_index(ni))
|
.map(|ni| self.primitive_index(ni.index()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn joined_segs(&self, dot: DI) -> impl Iterator<Item = SI> + '_ {
|
pub fn joined_segs(&self, dot: DI) -> impl Iterator<Item = SI> + '_ {
|
||||||
|
|
@ -449,24 +486,24 @@ impl<
|
||||||
fn joints(&self, node: PI) -> (DI, DI) {
|
fn joints(&self, node: PI) -> (DI, DI) {
|
||||||
let lhs = self
|
let lhs = self
|
||||||
.graph
|
.graph
|
||||||
.edges_directed(node.index(), Incoming)
|
.edges_directed(node.index().into(), Incoming)
|
||||||
.find(|edge| matches!(edge.weight(), GeometryLabel::Joined))
|
.find(|edge| matches!(edge.weight(), GeometryLabel::Joined))
|
||||||
.map(|edge| edge.source());
|
.map(|edge| edge.source());
|
||||||
let rhs = self
|
let rhs = self
|
||||||
.graph
|
.graph
|
||||||
.edges_directed(node.index(), Outgoing)
|
.edges_directed(node.index().into(), Outgoing)
|
||||||
.find(|edge| matches!(edge.weight(), GeometryLabel::Joined))
|
.find(|edge| matches!(edge.weight(), GeometryLabel::Joined))
|
||||||
.map(|edge| edge.target());
|
.map(|edge| edge.target());
|
||||||
|
|
||||||
(
|
(
|
||||||
lhs.map(|ni| {
|
lhs.map(|ni| {
|
||||||
self.primitive_index(ni)
|
self.primitive_index(ni.index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
rhs.map(|ni| {
|
rhs.map(|ni| {
|
||||||
self.primitive_index(ni)
|
self.primitive_index(ni.index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
|
|
@ -486,7 +523,7 @@ impl<
|
||||||
impl<PW: Copy + Retag<Index = PI>, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
impl<PW: Copy + Retag<Index = PI>, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
Geometry<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
Geometry<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
{
|
{
|
||||||
fn primitive_index(&self, index: NodeIndex<usize>) -> PI {
|
fn primitive_index(&self, index: usize) -> PI {
|
||||||
self.primitive_weight(index).retag(index)
|
self.primitive_weight(index).retag(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -543,12 +580,12 @@ impl<
|
||||||
BI: GetIndex,
|
BI: GetIndex,
|
||||||
> Geometry<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
> Geometry<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
{
|
{
|
||||||
pub fn all_rails(&self, node: NodeIndex<usize>) -> impl Iterator<Item = BI> + '_ {
|
pub fn all_rails(&self, index: usize) -> impl Iterator<Item = BI> + '_ {
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(node, Incoming)
|
.edges_directed(index.into(), Incoming)
|
||||||
.filter(|edge| matches!(edge.weight(), GeometryLabel::Core))
|
.filter(|edge| matches!(edge.weight(), GeometryLabel::Core))
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
self.primitive_index(edge.source())
|
self.primitive_index(edge.source().index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
|
|
@ -556,10 +593,10 @@ impl<
|
||||||
|
|
||||||
pub fn core(&self, bend: BI) -> DI {
|
pub fn core(&self, bend: BI) -> DI {
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(bend.index(), Outgoing)
|
.edges_directed(bend.index().into(), Outgoing)
|
||||||
.find(|edge| matches!(edge.weight(), GeometryLabel::Core))
|
.find(|edge| matches!(edge.weight(), GeometryLabel::Core))
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
self.primitive_index(edge.target())
|
self.primitive_index(edge.target().index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
|
|
@ -568,10 +605,10 @@ impl<
|
||||||
|
|
||||||
pub fn inner(&self, bend: BI) -> Option<BI> {
|
pub fn inner(&self, bend: BI) -> Option<BI> {
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(bend.index(), Incoming)
|
.edges_directed(bend.index().into(), Incoming)
|
||||||
.find(|edge| matches!(edge.weight(), GeometryLabel::Outer))
|
.find(|edge| matches!(edge.weight(), GeometryLabel::Outer))
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
self.primitive_index(edge.source())
|
self.primitive_index(edge.source().index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
|
|
@ -579,10 +616,10 @@ impl<
|
||||||
|
|
||||||
pub fn outers(&self, bend: BI) -> impl Iterator<Item = BI> + '_ {
|
pub fn outers(&self, bend: BI) -> impl Iterator<Item = BI> + '_ {
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(bend.index(), Outgoing)
|
.edges_directed(bend.index().into(), Outgoing)
|
||||||
.filter(|edge| matches!(edge.weight(), GeometryLabel::Outer))
|
.filter(|edge| matches!(edge.weight(), GeometryLabel::Outer))
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
self.primitive_index(edge.target())
|
self.primitive_index(edge.target().index())
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| unreachable!())
|
.unwrap_or_else(|_| unreachable!())
|
||||||
})
|
})
|
||||||
|
|
@ -600,11 +637,11 @@ impl<PW: Copy + Retag<Index = PI>, DW, SW, BW, CW: Clone, Cel: Copy, PI: Copy, D
|
||||||
type EntryLabel = Cel;
|
type EntryLabel = Cel;
|
||||||
|
|
||||||
fn add_compound(&mut self, weight: CW) -> GenericIndex<CW> {
|
fn add_compound(&mut self, weight: CW) -> GenericIndex<CW> {
|
||||||
GenericIndex::<CW>::new(self.graph.add_node(GenericNode::Compound(weight)))
|
GenericIndex::<CW>::new(self.graph.add_node(GenericNode::Compound(weight)).index())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_compound(&mut self, compound: GenericIndex<CW>) {
|
fn remove_compound(&mut self, compound: GenericIndex<CW>) {
|
||||||
debug_assert!(self.graph.remove_node(compound.index()).is_some());
|
debug_assert!(self.graph.remove_node(compound.index().into()).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_to_compound<I>(&mut self, primitive: I, entry_label: Cel, compound: GenericIndex<CW>)
|
fn add_to_compound<I>(&mut self, primitive: I, entry_label: Cel, compound: GenericIndex<CW>)
|
||||||
|
|
@ -612,14 +649,16 @@ impl<PW: Copy + Retag<Index = PI>, DW, SW, BW, CW: Clone, Cel: Copy, PI: Copy, D
|
||||||
I: Copy + GetIndex,
|
I: Copy + GetIndex,
|
||||||
{
|
{
|
||||||
self.graph.update_edge(
|
self.graph.update_edge(
|
||||||
primitive.index(),
|
primitive.index().into(),
|
||||||
compound.index(),
|
compound.index().into(),
|
||||||
GeometryLabel::Compound(entry_label),
|
GeometryLabel::Compound(entry_label),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compound_weight(&self, compound: GenericIndex<CW>) -> &CW {
|
fn compound_weight(&self, compound: GenericIndex<CW>) -> &CW {
|
||||||
if let GenericNode::Compound(weight) = self.graph.node_weight(compound.index()).unwrap() {
|
if let GenericNode::Compound(weight) =
|
||||||
|
self.graph.node_weight(compound.index().into()).unwrap()
|
||||||
|
{
|
||||||
weight
|
weight
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
@ -631,10 +670,10 @@ impl<PW: Copy + Retag<Index = PI>, DW, SW, BW, CW: Clone, Cel: Copy, PI: Copy, D
|
||||||
compound: GenericIndex<CW>,
|
compound: GenericIndex<CW>,
|
||||||
) -> impl Iterator<Item = (Cel, Self::GeneralIndex)> + '_ {
|
) -> impl Iterator<Item = (Cel, Self::GeneralIndex)> + '_ {
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(compound.index(), Incoming)
|
.edges_directed(compound.index().into(), Incoming)
|
||||||
.filter_map(|edge| {
|
.filter_map(|edge| {
|
||||||
if let GeometryLabel::Compound(entry_label) = *edge.weight() {
|
if let GeometryLabel::Compound(entry_label) = *edge.weight() {
|
||||||
Some((entry_label, self.primitive_index(edge.source())))
|
Some((entry_label, self.primitive_index(edge.source().index())))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -646,10 +685,10 @@ impl<PW: Copy + Retag<Index = PI>, DW, SW, BW, CW: Clone, Cel: Copy, PI: Copy, D
|
||||||
I: Copy + GetIndex,
|
I: Copy + GetIndex,
|
||||||
{
|
{
|
||||||
self.graph
|
self.graph
|
||||||
.edges_directed(node.index(), Outgoing)
|
.edges_directed(node.index().into(), Outgoing)
|
||||||
.filter_map(|edge| {
|
.filter_map(|edge| {
|
||||||
if let GeometryLabel::Compound(entry_label) = *edge.weight() {
|
if let GeometryLabel::Compound(entry_label) = *edge.weight() {
|
||||||
Some((entry_label, GenericIndex::new(edge.target())))
|
Some((entry_label, GenericIndex::new(edge.target().index())))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
src/graph.rs
18
src/graph.rs
|
|
@ -15,13 +15,13 @@ pub trait MakeRef<'a, C> {
|
||||||
|
|
||||||
#[enum_dispatch]
|
#[enum_dispatch]
|
||||||
pub trait GetIndex {
|
pub trait GetIndex {
|
||||||
fn index(&self) -> NodeIndex<usize>;
|
fn index(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetIndex for NodeIndex<usize> {
|
impl GetIndex for NodeIndex<usize> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn index(&self) -> NodeIndex<usize> {
|
fn index(&self) -> usize {
|
||||||
*self
|
NodeIndex::index(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,14 +31,14 @@ impl GetIndex for NodeIndex<usize> {
|
||||||
#[serde(bound = "")]
|
#[serde(bound = "")]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct GenericIndex<W> {
|
pub struct GenericIndex<W> {
|
||||||
node_index: NodeIndex<usize>,
|
node_index: usize,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
marker: PhantomData<W>,
|
marker: PhantomData<W>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> GenericIndex<W> {
|
impl<W> GenericIndex<W> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(index: NodeIndex<usize>) -> Self {
|
pub fn new(index: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
node_index: index,
|
node_index: index,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
|
|
@ -58,7 +58,7 @@ impl<W> core::marker::Copy for GenericIndex<W> {}
|
||||||
impl<W> core::fmt::Debug for GenericIndex<W> {
|
impl<W> core::fmt::Debug for GenericIndex<W> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
core::fmt::Display::fmt(&self.node_index.index(), f)
|
core::fmt::Display::fmt(&self.node_index, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ impl<W> core::hash::Hash for GenericIndex<W> {
|
||||||
|
|
||||||
impl<W> GetIndex for GenericIndex<W> {
|
impl<W> GetIndex for GenericIndex<W> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self) -> NodeIndex<usize> {
|
fn index(&self) -> usize {
|
||||||
self.node_index
|
self.node_index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -106,12 +106,12 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn serializable_index() {
|
fn serializable_index() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_string(&GenericIndex::<()>::new(NodeIndex::new(0))).unwrap(),
|
serde_json::to_string(&GenericIndex::<()>::new(0)).unwrap(),
|
||||||
"0"
|
"0"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::from_str::<GenericIndex<()>>("0").unwrap(),
|
serde_json::from_str::<GenericIndex<()>>("0").unwrap(),
|
||||||
GenericIndex::new(NodeIndex::new(0))
|
GenericIndex::new(0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ use crate::{
|
||||||
shape::AccessShape,
|
shape::AccessShape,
|
||||||
GenericNode,
|
GenericNode,
|
||||||
},
|
},
|
||||||
graph::GetIndex,
|
|
||||||
layout::{Layout, NodeIndex},
|
layout::{Layout, NodeIndex},
|
||||||
math::{intersect_linestring_and_ray, LineInGeneralForm, LineIntersection},
|
math::{intersect_linestring_and_ray, LineInGeneralForm, LineIntersection},
|
||||||
};
|
};
|
||||||
|
|
@ -121,11 +120,10 @@ impl<R: AccessRules> Layout<R> {
|
||||||
.filter(|(_, band_uid, _)| {
|
.filter(|(_, band_uid, _)| {
|
||||||
// filter entries which are connected to either lhs or rhs (and possibly both)
|
// filter entries which are connected to either lhs or rhs (and possibly both)
|
||||||
let (bts1, bts2) = band_uid.into();
|
let (bts1, bts2) = band_uid.into();
|
||||||
let (bts1, bts2) = (bts1.index(), bts2.index());
|
|
||||||
let geometry = self.drawing.geometry();
|
let geometry = self.drawing.geometry();
|
||||||
[(bts1, left), (bts1, right), (bts2, left), (bts2, right)]
|
[(bts1, left), (bts1, right), (bts2, left), (bts2, right)]
|
||||||
.iter()
|
.iter()
|
||||||
.all(|&(x, y)| !geometry.is_joined_with(x, y))
|
.all(|&(x, y)| !geometry.is_joined_with(*x, y))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
bands.sort_by(|a, b| f64::total_cmp(&a.0, &b.0));
|
bands.sort_by(|a, b| f64::total_cmp(&a.0, &b.0));
|
||||||
|
|
@ -162,11 +160,10 @@ impl<R: AccessRules> Layout<R> {
|
||||||
.filter(|(_, band_uid, _)| {
|
.filter(|(_, band_uid, _)| {
|
||||||
// filter entries which are connected to rhs
|
// filter entries which are connected to rhs
|
||||||
let (bts1, bts2) = band_uid.into();
|
let (bts1, bts2) = band_uid.into();
|
||||||
let (bts1, bts2) = (bts1.index(), bts2.index());
|
|
||||||
let geometry = self.drawing.geometry();
|
let geometry = self.drawing.geometry();
|
||||||
[(bts1, right), (bts2, right)]
|
[(bts1, right), (bts2, right)]
|
||||||
.iter()
|
.iter()
|
||||||
.all(|&(x, y)| !geometry.is_joined_with(x, y))
|
.all(|&(x, y)| !geometry.is_joined_with(*x, y))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
bands.sort_by(|a, b| f64::total_cmp(&a.0, &b.0));
|
bands.sort_by(|a, b| f64::total_cmp(&a.0, &b.0));
|
||||||
|
|
|
||||||
|
|
@ -360,8 +360,11 @@ impl<R: AccessRules> Layout<R> {
|
||||||
let PrimitiveIndex::FixedDot(dot) = index else {
|
let PrimitiveIndex::FixedDot(dot) = index else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
if let GenericNode::Primitive(PrimitiveWeight::FixedDot(weight)) =
|
if let GenericNode::Primitive(PrimitiveWeight::FixedDot(weight)) = drawing
|
||||||
drawing.geometry().graph().node_weight(dot.index()).unwrap()
|
.geometry()
|
||||||
|
.graph()
|
||||||
|
.node_weight(dot.index().into())
|
||||||
|
.unwrap()
|
||||||
{
|
{
|
||||||
Some((dot, weight))
|
Some((dot, weight))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -284,98 +284,98 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn petp00() {
|
fn petp00() {
|
||||||
let poly_ext = &[
|
let poly_ext = &[
|
||||||
(point! { x: 0., y: 0. }, FixedDotIndex::new(0.into())),
|
(point! { x: 0., y: 0. }, FixedDotIndex::new(0)),
|
||||||
(point! { x: 1., y: 0. }, FixedDotIndex::new(1.into())),
|
(point! { x: 1., y: 0. }, FixedDotIndex::new(1)),
|
||||||
(point! { x: 1., y: 1. }, FixedDotIndex::new(2.into())),
|
(point! { x: 1., y: 1. }, FixedDotIndex::new(2)),
|
||||||
(point! { x: 0., y: 1. }, FixedDotIndex::new(3.into())),
|
(point! { x: 0., y: 1. }, FixedDotIndex::new(3)),
|
||||||
];
|
];
|
||||||
let origin = point! { x: 0.5, y: -1.0 };
|
let origin = point! { x: 0.5, y: -1.0 };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
petp(poly_ext, false, origin),
|
petp(poly_ext, false, origin),
|
||||||
Ok((FixedDotIndex::new(1.into()), FixedDotIndex::new(0.into())))
|
Ok((FixedDotIndex::new(1), FixedDotIndex::new(0)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn petp00cw() {
|
fn petp00cw() {
|
||||||
let poly_ext = &[
|
let poly_ext = &[
|
||||||
(point! { x: 0., y: 0. }, FixedDotIndex::new(0.into())),
|
(point! { x: 0., y: 0. }, FixedDotIndex::new(0)),
|
||||||
(point! { x: 0., y: 1. }, FixedDotIndex::new(3.into())),
|
(point! { x: 0., y: 1. }, FixedDotIndex::new(3)),
|
||||||
(point! { x: 1., y: 1. }, FixedDotIndex::new(2.into())),
|
(point! { x: 1., y: 1. }, FixedDotIndex::new(2)),
|
||||||
(point! { x: 1., y: 0. }, FixedDotIndex::new(1.into())),
|
(point! { x: 1., y: 0. }, FixedDotIndex::new(1)),
|
||||||
];
|
];
|
||||||
let origin = point! { x: 0.5, y: -1.0 };
|
let origin = point! { x: 0.5, y: -1.0 };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
petp(poly_ext, true, origin),
|
petp(poly_ext, true, origin),
|
||||||
Ok((FixedDotIndex::new(1.into()), FixedDotIndex::new(0.into())))
|
Ok((FixedDotIndex::new(1), FixedDotIndex::new(0)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle() {
|
fn triangle() {
|
||||||
let poly_ext = &[
|
let poly_ext = &[
|
||||||
(point! { x: 0., y: 0. }, FixedDotIndex::new(0.into())),
|
(point! { x: 0., y: 0. }, FixedDotIndex::new(0)),
|
||||||
(point! { x: 1., y: 1. }, FixedDotIndex::new(1.into())),
|
(point! { x: 1., y: 1. }, FixedDotIndex::new(1)),
|
||||||
(point! { x: 0., y: 2. }, FixedDotIndex::new(2.into())),
|
(point! { x: 0., y: 2. }, FixedDotIndex::new(2)),
|
||||||
];
|
];
|
||||||
let origin = point! { x: 2., y: 1. };
|
let origin = point! { x: 2., y: 1. };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
petp(poly_ext, false, origin),
|
petp(poly_ext, false, origin),
|
||||||
Ok((FixedDotIndex::new(2.into()), FixedDotIndex::new(0.into())))
|
Ok((FixedDotIndex::new(2), FixedDotIndex::new(0)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle_cw() {
|
fn triangle_cw() {
|
||||||
let poly_ext = &[
|
let poly_ext = &[
|
||||||
(point! { x: 0., y: 0. }, FixedDotIndex::new(0.into())),
|
(point! { x: 0., y: 0. }, FixedDotIndex::new(0)),
|
||||||
(point! { x: 0., y: 2. }, FixedDotIndex::new(2.into())),
|
(point! { x: 0., y: 2. }, FixedDotIndex::new(2)),
|
||||||
(point! { x: 1., y: 1. }, FixedDotIndex::new(1.into())),
|
(point! { x: 1., y: 1. }, FixedDotIndex::new(1)),
|
||||||
];
|
];
|
||||||
let origin = point! { x: 2., y: 1. };
|
let origin = point! { x: 2., y: 1. };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
petp(poly_ext, true, origin),
|
petp(poly_ext, true, origin),
|
||||||
Ok((FixedDotIndex::new(2.into()), FixedDotIndex::new(0.into())))
|
Ok((FixedDotIndex::new(2), FixedDotIndex::new(0)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn handover00() {
|
fn handover00() {
|
||||||
let poly_ext_src = &[
|
let poly_ext_src = &[
|
||||||
(point! { x: 4., y: 0. }, FixedDotIndex::new(0.into())),
|
(point! { x: 4., y: 0. }, FixedDotIndex::new(0)),
|
||||||
(point! { x: 3., y: 3. }, FixedDotIndex::new(1.into())),
|
(point! { x: 3., y: 3. }, FixedDotIndex::new(1)),
|
||||||
(point! { x: 1., y: 2. }, FixedDotIndex::new(2.into())),
|
(point! { x: 1., y: 2. }, FixedDotIndex::new(2)),
|
||||||
(point! { x: 1., y: -2. }, FixedDotIndex::new(3.into())),
|
(point! { x: 1., y: -2. }, FixedDotIndex::new(3)),
|
||||||
(point! { x: 3., y: -3. }, FixedDotIndex::new(4.into())),
|
(point! { x: 3., y: -3. }, FixedDotIndex::new(4)),
|
||||||
];
|
];
|
||||||
let source = CachedPolyExt::new(poly_ext_src, false);
|
let source = CachedPolyExt::new(poly_ext_src, false);
|
||||||
let source = &source;
|
let source = &source;
|
||||||
|
|
||||||
let poly_ext_trg = &[
|
let poly_ext_trg = &[
|
||||||
(point! { x: -4., y: 0. }, FixedDotIndex::new(10.into())),
|
(point! { x: -4., y: 0. }, FixedDotIndex::new(10)),
|
||||||
(point! { x: -3., y: 3. }, FixedDotIndex::new(11.into())),
|
(point! { x: -3., y: 3. }, FixedDotIndex::new(11)),
|
||||||
(point! { x: -1., y: 2. }, FixedDotIndex::new(12.into())),
|
(point! { x: -1., y: 2. }, FixedDotIndex::new(12)),
|
||||||
(point! { x: -1., y: -2. }, FixedDotIndex::new(13.into())),
|
(point! { x: -1., y: -2. }, FixedDotIndex::new(13)),
|
||||||
(point! { x: -3., y: -3. }, FixedDotIndex::new(14.into())),
|
(point! { x: -3., y: -3. }, FixedDotIndex::new(14)),
|
||||||
];
|
];
|
||||||
let target = CachedPolyExt::new(poly_ext_trg, true);
|
let target = CachedPolyExt::new(poly_ext_trg, true);
|
||||||
let target = ⌖
|
let target = ⌖
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pehov(source, CoCw, target, CoCw),
|
pehov(source, CoCw, target, CoCw),
|
||||||
Some((FixedDotIndex::new(1.into()), FixedDotIndex::new(11.into())))
|
Some((FixedDotIndex::new(1), FixedDotIndex::new(11)))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pehov(source, CoCw, target, Cw),
|
pehov(source, CoCw, target, Cw),
|
||||||
Some((FixedDotIndex::new(2.into()), FixedDotIndex::new(13.into())))
|
Some((FixedDotIndex::new(2), FixedDotIndex::new(13)))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pehov(source, Cw, target, CoCw),
|
pehov(source, Cw, target, CoCw),
|
||||||
Some((FixedDotIndex::new(3.into()), FixedDotIndex::new(12.into())))
|
Some((FixedDotIndex::new(3), FixedDotIndex::new(12)))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pehov(source, Cw, target, Cw),
|
pehov(source, Cw, target, Cw),
|
||||||
Some((FixedDotIndex::new(4.into()), FixedDotIndex::new(14.into())))
|
Some((FixedDotIndex::new(4), FixedDotIndex::new(14)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ impl core::fmt::Debug for NavnodeIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetIndex for NavnodeIndex {
|
impl GetIndex for NavnodeIndex {
|
||||||
fn index(&self) -> NodeIndex<usize> {
|
fn index(&self) -> usize {
|
||||||
self.0
|
self.0.index()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -319,7 +319,7 @@ impl Navmesh {
|
||||||
|
|
||||||
fn unionize_with_overlapees(
|
fn unionize_with_overlapees(
|
||||||
layout: &Layout<impl AccessRules>,
|
layout: &Layout<impl AccessRules>,
|
||||||
overlapping_prenavnodes_unions: &mut UnionFind<NodeIndex<usize>>,
|
overlapping_prenavnodes_unions: &mut UnionFind<usize>,
|
||||||
prenavnode: PrenavmeshNodeIndex,
|
prenavnode: PrenavmeshNodeIndex,
|
||||||
) {
|
) {
|
||||||
// Ignore overlaps of a fillet.
|
// Ignore overlaps of a fillet.
|
||||||
|
|
@ -382,17 +382,17 @@ impl Navmesh {
|
||||||
PrenavmeshNodeIndex,
|
PrenavmeshNodeIndex,
|
||||||
Vec<(NodeIndex<usize>, NodeIndex<usize>)>,
|
Vec<(NodeIndex<usize>, NodeIndex<usize>)>,
|
||||||
>,
|
>,
|
||||||
overlapping_prenavnodes_unions: &UnionFind<NodeIndex<usize>>,
|
overlapping_prenavnodes_unions: &UnionFind<usize>,
|
||||||
from_prenavnode: PrenavmeshNodeIndex,
|
from_prenavnode: PrenavmeshNodeIndex,
|
||||||
to_prenavnode: PrenavmeshNodeIndex,
|
to_prenavnode: PrenavmeshNodeIndex,
|
||||||
) {
|
) {
|
||||||
// We assume prenavmesh nodes are fixed dots. This is an ugly shortcut,
|
// We assume prenavmesh nodes are fixed dots. This is an ugly shortcut,
|
||||||
// since fixed bends also can be prenavnodes, but it works for now.
|
// since fixed bends also can be prenavnodes, but it works for now.
|
||||||
let from_prenavnode_repr = PrenavmeshNodeIndex::FixedDot(GenericIndex::new(
|
let from_prenavnode_repr = PrenavmeshNodeIndex::FixedDot(GenericIndex::new(
|
||||||
overlapping_prenavnodes_unions.find(from_prenavnode.index()),
|
overlapping_prenavnodes_unions.find(from_prenavnode.index().into()),
|
||||||
));
|
));
|
||||||
let to_prenavnode_repr = PrenavmeshNodeIndex::FixedDot(GenericIndex::new(
|
let to_prenavnode_repr = PrenavmeshNodeIndex::FixedDot(GenericIndex::new(
|
||||||
overlapping_prenavnodes_unions.find(to_prenavnode.index()),
|
overlapping_prenavnodes_unions.find(to_prenavnode.index().into()),
|
||||||
));
|
));
|
||||||
|
|
||||||
Self::add_prenavedge_as_quadrinavedges(
|
Self::add_prenavedge_as_quadrinavedges(
|
||||||
|
|
@ -455,7 +455,7 @@ impl Data for Navmesh {
|
||||||
|
|
||||||
impl DataMap for Navmesh {
|
impl DataMap for Navmesh {
|
||||||
fn node_weight(&self, vertex: Self::NodeId) -> Option<&Self::NodeWeight> {
|
fn node_weight(&self, vertex: Self::NodeId) -> Option<&Self::NodeWeight> {
|
||||||
self.graph.node_weight(vertex.index())
|
self.graph.node_weight(vertex.index().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edge_weight(&self, _edge: Self::EdgeId) -> Option<&Self::EdgeWeight> {
|
fn edge_weight(&self, _edge: Self::EdgeId) -> Option<&Self::EdgeWeight> {
|
||||||
|
|
@ -495,7 +495,11 @@ impl<'a> IntoNeighbors for &'a Navmesh {
|
||||||
type Neighbors = Box<dyn Iterator<Item = NavnodeIndex> + 'a>;
|
type Neighbors = Box<dyn Iterator<Item = NavnodeIndex> + 'a>;
|
||||||
|
|
||||||
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
||||||
Box::new(self.graph.neighbors(vertex.index()).map(NavnodeIndex))
|
Box::new(
|
||||||
|
self.graph
|
||||||
|
.neighbors(vertex.index().into())
|
||||||
|
.map(NavnodeIndex),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -521,7 +525,7 @@ impl<'a> IntoEdges for &'a Navmesh {
|
||||||
fn edges(self, vertex: Self::NodeId) -> Self::Edges {
|
fn edges(self, vertex: Self::NodeId) -> Self::Edges {
|
||||||
Box::new(
|
Box::new(
|
||||||
self.graph
|
self.graph
|
||||||
.edges(vertex.index())
|
.edges(vertex.index().into())
|
||||||
.map(|edge| NavmeshEdgeReference {
|
.map(|edge| NavmeshEdgeReference {
|
||||||
from: NavnodeIndex(edge.source()),
|
from: NavnodeIndex(edge.source()),
|
||||||
to: NavnodeIndex(edge.target()),
|
to: NavnodeIndex(edge.target()),
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
use derive_getters::Getters;
|
use derive_getters::Getters;
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
use petgraph::{stable_graph::NodeIndex, visit::NodeIndexable};
|
use petgraph::visit::NodeIndexable;
|
||||||
use spade::{HasPosition, InsertionError, Point2};
|
use spade::{HasPosition, InsertionError, Point2};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
||||||
|
|
@ -39,15 +39,15 @@ impl<I: GetIndex, VW: GetTrianvertexNodeIndex<I> + HasPosition, EW: Default>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_vertex(&mut self, weight: VW) -> Result<(), InsertionError> {
|
pub fn add_vertex(&mut self, weight: VW) -> Result<(), InsertionError> {
|
||||||
let index = weight.node_index().index().index();
|
let index = weight.node_index().index();
|
||||||
self.trianvertex_to_handle[index] =
|
self.trianvertex_to_handle[index] =
|
||||||
Some(spade::Triangulation::insert(&mut self.cdt, weight)?);
|
Some(spade::Triangulation::insert(&mut self.cdt, weight)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_constraint_edge(&mut self, from: VW, to: VW) -> Result<bool, InsertionError> {
|
pub fn add_constraint_edge(&mut self, from: VW, to: VW) -> Result<bool, InsertionError> {
|
||||||
let from_index = from.node_index().index().index();
|
let from_index = from.node_index().index();
|
||||||
let to_index = to.node_index().index().index();
|
let to_index = to.node_index().index();
|
||||||
|
|
||||||
// It is possible for one or both constraint edge endpoint vertices to
|
// It is possible for one or both constraint edge endpoint vertices to
|
||||||
// not exist in the triangulation even after everything has been added.
|
// not exist in the triangulation even after everything has been added.
|
||||||
|
|
@ -75,13 +75,13 @@ impl<I: GetIndex, VW: GetTrianvertexNodeIndex<I> + HasPosition, EW: Default>
|
||||||
|
|
||||||
pub fn weight(&self, vertex: I) -> &VW {
|
pub fn weight(&self, vertex: I) -> &VW {
|
||||||
spade::Triangulation::s(&self.cdt)
|
spade::Triangulation::s(&self.cdt)
|
||||||
.vertex_data(self.trianvertex_to_handle[vertex.index().index()].unwrap())
|
.vertex_data(self.trianvertex_to_handle[vertex.index()].unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn weight_mut(&mut self, vertex: I) -> &mut VW {
|
pub fn weight_mut(&mut self, vertex: I) -> &mut VW {
|
||||||
spade::Triangulation::vertex_data_mut(
|
spade::Triangulation::vertex_data_mut(
|
||||||
&mut self.cdt,
|
&mut self.cdt,
|
||||||
self.trianvertex_to_handle[vertex.index().index()].unwrap(),
|
self.trianvertex_to_handle[vertex.index()].unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ impl<I: GetIndex, VW: GetTrianvertexNodeIndex<I> + HasPosition, EW: Default>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(&self, vertex: I) -> FixedVertexHandle {
|
fn handle(&self, vertex: I) -> FixedVertexHandle {
|
||||||
self.trianvertex_to_handle[vertex.index().index()].unwrap()
|
self.trianvertex_to_handle[vertex.index()].unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn position(&self, vertex: I) -> Point<<VW as HasPosition>::Scalar>
|
pub fn position(&self, vertex: I) -> Point<<VW as HasPosition>::Scalar>
|
||||||
|
|
@ -328,7 +328,7 @@ impl<
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_index(&self, node: I) -> usize {
|
fn to_index(&self, node: I) -> usize {
|
||||||
node.index().index()
|
node.index()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_index(&self, index: usize) -> I {
|
fn from_index(&self, index: usize) -> I {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::{fs::File, io::BufReader};
|
use std::{fs::File, io::BufReader};
|
||||||
|
|
||||||
use petgraph::{stable_graph::NodeIndex, unionfind::UnionFind, visit::NodeIndexable};
|
use petgraph::{unionfind::UnionFind, visit::NodeIndexable};
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
history::{History, HistoryError},
|
history::{History, HistoryError},
|
||||||
|
|
@ -257,7 +257,7 @@ pub fn assert_band_length(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unionfind(autorouter: &mut Autorouter<impl AccessMesadata>) -> UnionFind<NodeIndex<usize>> {
|
fn unionfind(autorouter: &mut Autorouter<impl AccessMesadata>) -> UnionFind<usize> {
|
||||||
for ratline in autorouter.ratsnest().graph().edge_indices() {
|
for ratline in autorouter.ratsnest().graph().edge_indices() {
|
||||||
// Accessing endpoints may create new dots because apex construction is lazy, so we access
|
// Accessing endpoints may create new dots because apex construction is lazy, so we access
|
||||||
// tem all before starting unionfind, as it requires a constant index bound.
|
// tem all before starting unionfind, as it requires a constant index bound.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue