Implement Petgraph's graph traits on a Spade's triangulation

This commit is contained in:
Mikolaj Wielgus 2023-08-25 23:39:44 +02:00
parent 658bb112c2
commit a1afd19fcb
4 changed files with 186 additions and 79 deletions

View File

@ -17,6 +17,9 @@ version = "0.6.3"
[dependencies.spade] [dependencies.spade]
version = "2.2.0" version = "2.2.0"
[dependencies.fixedbitset]
version = "0.4.0"
[dependencies.sdl2] [dependencies.sdl2]
version = "0.35.2" version = "0.35.2"
default-features = false default-features = false

View File

@ -17,7 +17,7 @@ use crate::shape::Shape;
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>; pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
pub struct Layout { pub struct Layout {
pub rtree: RTree<RTreeWrapper>, rtree: RTree<RTreeWrapper>,
pub graph: StableDiGraph<TaggedWeight, Label, usize>, pub graph: StableDiGraph<TaggedWeight, Label, usize>,
} }
@ -218,57 +218,6 @@ impl Layout {
Bow::new(bend, &self.graph) Bow::new(bend, &self.graph)
} }
/*fn triangulate(&mut self) {
let peer_edge_indices: Vec<EdgeIndex<usize>> = self
.graph
.edge_indices()
.filter(|index| *self.graph.edge_weight(*index).unwrap() == Label::Peer)
.collect();
for edge_index in peer_edge_indices {
self.graph.remove_edge(edge_index);
}
struct TriangulationVertex {
pub index: NodeIndex<usize>,
x: f64,
y: f64,
}
impl HasPosition for TriangulationVertex {
type Scalar = f64;
fn position(&self) -> Point2<Self::Scalar> {
Point2::new(self.x, self.y)
}
}
let mut triangulation: DelaunayTriangulation<_> = DelaunayTriangulation::new();
for node_index in self
.graph
.node_indices()
.filter(|index| self.graph.node_weight(*index).unwrap().is_dot())
{
let center = self
.primitive(Index::<Label>::new(node_index))
.shape()
.center();
triangulation
.insert(TriangulationVertex {
index: node_index,
x: center.x(),
y: center.y(),
})
.unwrap();
}
for edge in triangulation.directed_edges() {
let from = edge.from().as_ref().index;
let to = edge.to().as_ref().index;
self.graph.add_edge(from, to, Label::Peer);
}
}*/
fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>( fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>(
&mut self, &mut self,
index: Index<Weight>, index: Index<Weight>,
@ -311,18 +260,6 @@ impl Layout {
self.rtree.remove(&RTreeWrapper::new(shape, index)); self.rtree.remove(&RTreeWrapper::new(shape, index));
} }
/*pub fn edges(&self) -> impl Iterator<Item = (TaggedIndex, TaggedIndex)> + '_ {
self.graph.edge_indices().map(|edge| {
let endpoints = self.graph.edge_endpoints(edge).unwrap();
(
Index::<Label>::new(endpoints.0)
.retag(self.graph.node_weight(endpoints.0).unwrap()),
Index::<Label>::new(endpoints.1)
.retag(self.graph.node_weight(endpoints.1).unwrap()),
)
})
}*/
pub fn dots(&self) -> impl Iterator<Item = DotIndex> + '_ { pub fn dots(&self) -> impl Iterator<Item = DotIndex> + '_ {
self.nodes() self.nodes()
.filter_map(|ni| ni.as_dot().and_then(|di| Some(*di))) .filter_map(|ni| ni.as_dot().and_then(|di| Some(*di)))

View File

@ -1,15 +1,24 @@
use petgraph::stable_graph::NodeIndex; use fixedbitset::FixedBitSet;
use spade::{DelaunayTriangulation, HasPosition, Point2, Triangulation}; use geo::{point, Point};
use petgraph::{
stable_graph::NodeIndex,
visit::{self, NodeIndexable},
};
use spade::{
handles::{DirectedEdgeHandle, FixedDirectedEdgeHandle, FixedVertexHandle},
iterators::DirectedEdgeIterator,
DelaunayTriangulation, HasPosition, Point2, Triangulation,
};
use crate::{graph::DotIndex, layout::Layout, router::Router}; use crate::{graph::DotIndex, layout::Layout, router::Router};
struct TriangulationVertex { struct MeshVertex {
pub index: DotIndex, pub index: DotIndex,
x: f64, x: f64,
y: f64, y: f64,
} }
impl HasPosition for TriangulationVertex { impl HasPosition for MeshVertex {
type Scalar = f64; type Scalar = f64;
fn position(&self) -> Point2<Self::Scalar> { fn position(&self) -> Point2<Self::Scalar> {
Point2::new(self.x, self.y) Point2::new(self.x, self.y)
@ -17,7 +26,7 @@ impl HasPosition for TriangulationVertex {
} }
pub struct Mesh { pub struct Mesh {
triangulation: DelaunayTriangulation<TriangulationVertex>, triangulation: DelaunayTriangulation<MeshVertex>,
} }
impl Mesh { impl Mesh {
@ -33,7 +42,7 @@ impl Mesh {
for dot in layout.dots() { for dot in layout.dots() {
let center = layout.primitive(dot).shape().center(); let center = layout.primitive(dot).shape().center();
self.triangulation self.triangulation
.insert(TriangulationVertex { .insert(MeshVertex {
index: dot, index: dot,
x: center.x(), x: center.x(),
y: center.y(), y: center.y(),
@ -42,9 +51,168 @@ impl Mesh {
} }
} }
pub fn edges(&self) -> impl Iterator<Item = (DotIndex, DotIndex)> + '_ { pub fn position(&self, handle: FixedVertexHandle) -> Point {
self.triangulation let position = self.triangulation.vertex(handle).position();
.directed_edges() point! {x: position.x, y: position.y}
.map(|edge| (edge.from().as_ref().index, edge.to().as_ref().index)) }
}
impl visit::GraphBase for Mesh {
type NodeId = FixedVertexHandle;
type EdgeId = FixedDirectedEdgeHandle;
}
pub struct MeshVisitMap {
fixedbitset: FixedBitSet,
}
impl MeshVisitMap {
pub fn with_capacity(bits: usize) -> Self {
Self {
fixedbitset: FixedBitSet::with_capacity(bits),
}
}
pub fn clear(&mut self) {
self.fixedbitset.clear();
}
pub fn grow(&mut self, bits: usize) {
self.fixedbitset.grow(bits);
}
}
pub trait IndexHolder {
fn index(&self) -> usize;
}
impl IndexHolder for FixedVertexHandle {
fn index(&self) -> usize {
self.index()
}
}
impl<T: IndexHolder> visit::VisitMap<T> for MeshVisitMap {
fn visit(&mut self, a: T) -> bool {
!self.fixedbitset.put(a.index())
}
fn is_visited(&self, a: &T) -> bool {
self.fixedbitset.contains(a.index())
}
}
impl visit::Visitable for Mesh {
type Map = MeshVisitMap;
fn visit_map(&self) -> Self::Map {
MeshVisitMap::with_capacity(self.triangulation.num_vertices())
}
fn reset_map(&self, map: &mut Self::Map) {
map.clear();
map.grow(self.triangulation.num_vertices());
}
}
impl visit::Data for Mesh {
type NodeWeight = ();
type EdgeWeight = ();
}
#[derive(Clone, Copy)]
pub struct MeshEdgeReference<'a> {
handle: DirectedEdgeHandle<'a, MeshVertex, (), (), ()>,
}
impl<'a> visit::EdgeRef for MeshEdgeReference<'a> {
type NodeId = FixedVertexHandle;
type EdgeId = FixedDirectedEdgeHandle;
type Weight = ();
fn source(&self) -> Self::NodeId {
self.handle.from().fix()
}
fn target(&self) -> Self::NodeId {
self.handle.to().fix()
}
fn weight(&self) -> &Self::Weight {
&()
}
fn id(&self) -> Self::EdgeId {
self.handle.fix()
}
}
pub struct MeshEdgeReferences<'a> {
iter: DirectedEdgeIterator<'a, MeshVertex, (), (), ()>,
}
impl<'a> Iterator for MeshEdgeReferences<'a> {
type Item = MeshEdgeReference<'a>;
fn next(&mut self) -> Option<Self::Item> {
let handle = self.iter.next()?;
Some(MeshEdgeReference { handle })
}
}
impl<'a> visit::IntoEdgeReferences for &'a Mesh {
type EdgeRef = MeshEdgeReference<'a>;
type EdgeReferences = MeshEdgeReferences<'a>;
fn edge_references(self) -> Self::EdgeReferences {
MeshEdgeReferences {
iter: self.triangulation.directed_edges(),
}
}
}
pub struct MeshNeighbors<'a> {
iter: Box<dyn Iterator<Item = DirectedEdgeHandle<'a, MeshVertex, (), (), ()>> + 'a>,
}
impl<'a> Iterator for MeshNeighbors<'a> {
type Item = FixedVertexHandle;
fn next(&mut self) -> Option<Self::Item> {
let handle = self.iter.next()?;
Some(handle.to().fix())
}
}
impl<'a> visit::IntoNeighbors for &'a Mesh {
type Neighbors = MeshNeighbors<'a>;
fn neighbors(self, a: Self::NodeId) -> Self::Neighbors {
MeshNeighbors {
iter: Box::new(self.triangulation.vertex(a).out_edges()),
}
}
}
pub struct MeshEdges<'a> {
iter: Box<dyn Iterator<Item = DirectedEdgeHandle<'a, MeshVertex, (), (), ()>> + 'a>,
}
impl<'a> Iterator for MeshEdges<'a> {
type Item = MeshEdgeReference<'a>;
fn next(&mut self) -> Option<Self::Item> {
let handle = self.iter.next()?;
Some(MeshEdgeReference { handle })
}
}
impl<'a> visit::IntoEdges for &'a Mesh {
type Edges = MeshEdges<'a>;
fn edges(self, a: Self::NodeId) -> Self::Edges {
MeshEdges {
iter: Box::new(self.triangulation.vertex(a).out_edges()),
}
} }
} }

View File

@ -1,4 +1,5 @@
use geo::geometry::Point; use geo::geometry::Point;
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use std::cell::{Ref, RefCell}; use std::cell::{Ref, RefCell};
use std::rc::Rc; use std::rc::Rc;
@ -308,12 +309,10 @@ impl Router {
} }
pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ { pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ {
self.mesh.edges().map(|endpoints| { self.mesh.edge_references().map(|edge| {
let index0 = endpoints.0;
let index1 = endpoints.1;
( (
self.layout.primitive(index0).shape().center(), self.mesh.position(edge.source()),
self.layout.primitive(index1).shape().center(), self.mesh.position(edge.target()),
) )
}) })
} }