From 8379470bb138ec762d320e8304d392e6f2049bd4 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sat, 4 Nov 2023 18:36:41 +0000 Subject: [PATCH] mesh: Split out `Mesh` into a new `Triangulation` struct It will be possible for the mesh to contain additional vertices that aren't part of the Delaunay triangulation. `Mesh` is now a wrapper over `Triangulation` that implements the same traits, and will be later adding its own vertices in addition to the ones from triangulation. --- src/main.rs | 1 + src/mesh.rs | 95 +++++++------------------------ src/router.rs | 6 +- src/triangulation.rs | 130 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 79 deletions(-) create mode 100644 src/triangulation.rs diff --git a/src/main.rs b/src/main.rs index bec9084..9dd93ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,6 +23,7 @@ mod segbend; mod shape; mod tracer; mod traverser; +mod triangulation; use geo::point; use graph::{FixedDotIndex, FixedSegWeight, LooseDotIndex}; diff --git a/src/mesh.rs b/src/mesh.rs index 9806dee..30c3559 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,25 +1,16 @@ use enum_dispatch::enum_dispatch; -use fixedbitset::FixedBitSet; -use geo::{point, Point}; +use geo::Point; use petgraph::stable_graph::NodeIndex; -use petgraph::visit::{self, NodeIndexable}; -use spade::{ - handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError, Point2, - Triangulation, -}; +use petgraph::visit; +use spade::InsertionError; use crate::{ graph::{FixedBendIndex, FixedDotIndex, GetNodeIndex, Index, LooseBendIndex}, layout::Layout, + primitive::MakeShape, + shape::ShapeTrait, + triangulation::Triangulation, }; -use crate::{primitive::MakeShape, shape::ShapeTrait}; - -#[derive(Debug, Clone)] -struct Vertex { - graph_index: VertexIndex, - x: f64, - y: f64, -} #[enum_dispatch(GetNodeIndex)] #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] @@ -29,60 +20,32 @@ pub enum VertexIndex { LooseBend(LooseBendIndex), } -impl HasPosition for Vertex { - type Scalar = f64; - fn position(&self) -> Point2 { - Point2::new(self.x, self.y) - } -} - #[derive(Debug, Clone)] pub struct Mesh { - triangulation: DelaunayTriangulation, - vertex_to_handle: Vec>, + triangulation: Triangulation, } impl Mesh { - pub fn new() -> Self { + pub fn new(layout: &Layout) -> Self { Self { - triangulation: DelaunayTriangulation::new(), - vertex_to_handle: Vec::new(), + triangulation: Triangulation::new(layout), } } - pub fn triangulate(&mut self, layout: &Layout) -> Result<(), InsertionError> { - self.triangulation.clear(); - self.vertex_to_handle = Vec::new(); - self.vertex_to_handle - .resize(layout.graph.node_bound(), None); - + pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> { for node in layout.nodes() { if let Index::FixedDot(dot) = node { let center = layout.primitive(dot).shape().center(); - self.vertex_to_handle[dot.node_index().index()] = - Some(self.triangulation.insert(Vertex { - graph_index: dot.into(), - x: center.x(), - y: center.y(), - })?); + self.triangulation + .add_vertex(dot.into(), center.x(), center.y()); } } - Ok(()) } - pub fn vertex(&self, handle: FixedVertexHandle) -> VertexIndex { - self.triangulation.vertex(handle).as_ref().graph_index - } - - pub fn handle(&self, graph_index: VertexIndex) -> FixedVertexHandle { - self.vertex_to_handle[graph_index.node_index().index()].unwrap() - } - pub fn position(&self, vertex: VertexIndex) -> Point { - let position = self.triangulation.vertex(self.handle(vertex)).position(); - point! {x: position.x, y: position.y} + self.triangulation.position(vertex) } } @@ -98,8 +61,8 @@ impl visit::Data for Mesh { #[derive(Clone, Copy)] pub struct MeshEdgeReference { - from: VertexIndex, - to: VertexIndex, + pub from: VertexIndex, + pub to: VertexIndex, } impl<'a> visit::EdgeRef for MeshEdgeReference { @@ -129,14 +92,7 @@ impl<'a> visit::IntoEdgeReferences for &'a Mesh { type EdgeReferences = Box + 'a>; fn edge_references(self) -> Self::EdgeReferences { - Box::new( - self.triangulation - .directed_edges() - .map(|edge| MeshEdgeReference { - from: self.vertex(edge.from().fix()), - to: self.vertex(edge.to().fix()), - }), - ) + Box::new(self.triangulation.edge_references()) } } @@ -144,27 +100,14 @@ impl<'a> visit::IntoNeighbors for &'a Mesh { type Neighbors = Box + 'a>; fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors { - Box::new( - self.triangulation - .vertex(self.handle(vertex)) - .out_edges() - .map(|handle| self.vertex(handle.to().fix())), - ) + self.triangulation.neighbors(vertex) } } impl<'a> visit::IntoEdges for &'a Mesh { type Edges = Box + 'a>; - fn edges(self, a: Self::NodeId) -> Self::Edges { - Box::new( - self.triangulation - .vertex(self.handle(a)) - .out_edges() - .map(|edge| MeshEdgeReference { - from: self.vertex(edge.from().fix()), - to: self.vertex(edge.to().fix()), - }), - ) + fn edges(self, node: Self::NodeId) -> Self::Edges { + Box::new(self.triangulation.edges(node)) } } diff --git a/src/router.rs b/src/router.rs index 93e9aa8..0ba1292 100644 --- a/src/router.rs +++ b/src/router.rs @@ -90,8 +90,8 @@ impl Router { // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look // right. //self.mesh.triangulate(&self.layout)?; - let mut mesh = Mesh::new(); - mesh.triangulate(&self.layout)?; + let mut mesh = Mesh::new(&self.layout); + mesh.generate(&self.layout)?; let mut tracer = self.tracer(&mesh); let trace = tracer.start(from); @@ -129,7 +129,7 @@ impl Router { }; self.enroute(from, to_dot, observer)*/ - Ok(Mesh::new()) + Ok(Mesh::new(&self.layout)) } /*pub fn squeeze_around_dot( diff --git a/src/triangulation.rs b/src/triangulation.rs new file mode 100644 index 0000000..e8a034b --- /dev/null +++ b/src/triangulation.rs @@ -0,0 +1,130 @@ +use geo::{point, Point}; +use petgraph::visit::{self, NodeIndexable}; +use spade::{ + handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError, Point2, +}; + +use crate::{ + graph::GetNodeIndex, + layout::Layout, + mesh::{MeshEdgeReference, VertexIndex}, +}; + +#[derive(Debug, Clone)] +struct VertexWeight { + vertex: VertexIndex, + x: f64, + y: f64, +} + +impl HasPosition for VertexWeight { + type Scalar = f64; + fn position(&self) -> Point2 { + Point2::new(self.x, self.y) + } +} + +#[derive(Debug, Clone)] +pub struct Triangulation { + triangulation: DelaunayTriangulation, + vertex_to_handle: Vec>, +} + +impl Triangulation { + pub fn new(layout: &Layout) -> Self { + let mut this = Self { + triangulation: as spade::Triangulation>::new(), + vertex_to_handle: Vec::new(), + }; + this.vertex_to_handle + .resize(layout.graph.node_bound(), None); + this + } + + pub fn add_vertex( + &mut self, + vertex: VertexIndex, + x: f64, + y: f64, + ) -> Result<(), InsertionError> { + self.vertex_to_handle[vertex.node_index().index()] = Some(spade::Triangulation::insert( + &mut self.triangulation, + VertexWeight { vertex, x, y }, + )?); + Ok(()) + } + + pub fn project_vertex(&mut self, from: VertexIndex, to: VertexIndex) { + self.vertex_to_handle[from.node_index().index()] = + self.vertex_to_handle[to.node_index().index()] + } + + pub fn position(&self, vertex: VertexIndex) -> Point { + let position = + spade::Triangulation::vertex(&self.triangulation, self.handle(vertex)).position(); + point! {x: position.x, y: position.y} + } + + fn vertex(&self, handle: FixedVertexHandle) -> VertexIndex { + spade::Triangulation::vertex(&self.triangulation, handle) + .as_ref() + .vertex + } + + fn handle(&self, vertex: VertexIndex) -> FixedVertexHandle { + self.vertex_to_handle[vertex.node_index().index()].unwrap() + } +} + +impl visit::GraphBase for Triangulation { + type NodeId = VertexIndex; + type EdgeId = (VertexIndex, VertexIndex); +} + +impl visit::Data for Triangulation { + type NodeWeight = (); + type EdgeWeight = (); +} + +impl<'a> visit::IntoEdgeReferences for &'a Triangulation { + type EdgeRef = MeshEdgeReference; + type EdgeReferences = Box + 'a>; + + fn edge_references(self) -> Self::EdgeReferences { + Box::new( + spade::Triangulation::directed_edges(&self.triangulation).map(|edge| { + MeshEdgeReference { + from: self.vertex(edge.from().fix()), + to: self.vertex(edge.to().fix()), + } + }), + ) + } +} + +impl<'a> visit::IntoNeighbors for &'a Triangulation { + type Neighbors = Box + 'a>; + + fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors { + Box::new( + spade::Triangulation::vertex(&self.triangulation, self.handle(vertex)) + .out_edges() + .map(|handle| self.vertex(handle.to().fix())), + ) + } +} + +impl<'a> visit::IntoEdges for &'a Triangulation { + type Edges = Box + 'a>; + + fn edges(self, node: Self::NodeId) -> Self::Edges { + Box::new( + spade::Triangulation::vertex(&self.triangulation, self.handle(node)) + .out_edges() + .map(|edge| MeshEdgeReference { + from: self.vertex(edge.from().fix()), + to: self.vertex(edge.to().fix()), + }), + ) + } +}