mirror of https://codeberg.org/topola/topola.git
Implement Petgraph's graph traits on a Spade's triangulation
This commit is contained in:
parent
658bb112c2
commit
a1afd19fcb
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)))
|
||||||
|
|
|
||||||
188
src/mesh.rs
188
src/mesh.rs
|
|
@ -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()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue