diff --git a/src/mesh.rs b/src/mesh.rs index 12274a9..fa62c1a 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,15 +1,15 @@ use enum_dispatch::enum_dispatch; use geo::Point; -use petgraph::stable_graph::NodeIndex; use petgraph::visit; -use spade::InsertionError; +use petgraph::{stable_graph::NodeIndex, visit::EdgeRef}; +use spade::{HasPosition, InsertionError, Point2}; use crate::{ graph::{FixedBendIndex, FixedDotIndex, GetNodeIndex, Index, LooseBendIndex, MakePrimitive}, layout::Layout, - primitive::{GetCore, MakeShape}, + primitive::MakeShape, shape::ShapeTrait, - triangulation::Triangulation, + triangulation::{GetVertexIndex, Triangulation}, }; #[enum_dispatch(GetNodeIndex)] @@ -20,9 +20,28 @@ pub enum VertexIndex { LooseBend(LooseBendIndex), } +#[derive(Debug, Clone)] +struct TriangulationWeight { + vertex: VertexIndex, + pos: Point, +} + +impl GetVertexIndex for TriangulationWeight { + fn vertex(&self) -> VertexIndex { + self.vertex + } +} + +impl HasPosition for TriangulationWeight { + type Scalar = f64; + fn position(&self) -> Point2 { + Point2::new(self.pos.x(), self.pos.y()) + } +} + #[derive(Debug, Clone)] pub struct Mesh { - triangulation: Triangulation, + triangulation: Triangulation, } impl Mesh { @@ -38,12 +57,16 @@ impl Mesh { match node { Index::FixedDot(fixed_dot) => { - self.triangulation - .add_vertex(fixed_dot.into(), center.x(), center.y())?; + self.triangulation.add_vertex(TriangulationWeight { + vertex: fixed_dot.into(), + pos: center, + })?; } Index::FixedBend(fixed_bend) => { - self.triangulation - .add_vertex(fixed_bend.into(), center.x(), center.y())?; + self.triangulation.add_vertex(TriangulationWeight { + vertex: fixed_bend.into(), + pos: center, + })?; } /*Index::LooseBend(loose_bend) => { self.triangulation.add_bend( @@ -72,13 +95,13 @@ impl visit::Data for Mesh { type EdgeWeight = (); } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct MeshEdgeReference { - pub from: VertexIndex, - pub to: VertexIndex, + from: VertexIndex, + to: VertexIndex, } -impl<'a> visit::EdgeRef for MeshEdgeReference { +impl visit::EdgeRef for MeshEdgeReference { type NodeId = VertexIndex; type EdgeId = (VertexIndex, VertexIndex); type Weight = (); @@ -105,7 +128,14 @@ impl<'a> visit::IntoEdgeReferences for &'a Mesh { type EdgeReferences = Box + 'a>; fn edge_references(self) -> Self::EdgeReferences { - Box::new(self.triangulation.edge_references()) + Box::new( + self.triangulation + .edge_references() + .map(|edge| MeshEdgeReference { + from: edge.source(), + to: edge.target(), + }), + ) } } @@ -121,6 +151,13 @@ impl<'a> visit::IntoEdges for &'a Mesh { type Edges = Box + 'a>; fn edges(self, node: Self::NodeId) -> Self::Edges { - Box::new(self.triangulation.edges(node)) + Box::new( + self.triangulation + .edges(node) + .map(|edge| MeshEdgeReference { + from: edge.source(), + to: edge.target(), + }), + ) } } diff --git a/src/triangulation.rs b/src/triangulation.rs index e8a034b..36423d3 100644 --- a/src/triangulation.rs +++ b/src/triangulation.rs @@ -1,99 +1,121 @@ +use std::marker::PhantomData; + use geo::{point, Point}; use petgraph::visit::{self, NodeIndexable}; -use spade::{ - handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError, Point2, -}; +use spade::{handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError}; -use crate::{ - graph::GetNodeIndex, - layout::Layout, - mesh::{MeshEdgeReference, VertexIndex}, -}; +use crate::{graph::GetNodeIndex, layout::Layout}; -#[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) - } +pub trait GetVertexIndex { + fn vertex(&self) -> I; } #[derive(Debug, Clone)] -pub struct Triangulation { - triangulation: DelaunayTriangulation, +pub struct Triangulation + HasPosition> { + triangulation: DelaunayTriangulation, vertex_to_handle: Vec>, + index_marker: PhantomData, } -impl Triangulation { +impl + HasPosition> + Triangulation +{ pub fn new(layout: &Layout) -> Self { let mut this = Self { - triangulation: as spade::Triangulation>::new(), + triangulation: as spade::Triangulation>::new(), vertex_to_handle: Vec::new(), + index_marker: PhantomData, }; 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( + pub fn add_vertex(&mut self, weight: W) -> Result<(), InsertionError> { + let index = weight.vertex().node_index().index(); + self.vertex_to_handle[index] = Some(spade::Triangulation::insert( &mut self.triangulation, - VertexWeight { vertex, x, y }, + weight, )?); 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 weight_mut(&mut self, vertex: I) -> &mut W { + spade::Triangulation::vertex_data_mut( + &mut self.triangulation, + self.vertex_to_handle[vertex.node_index().index()].unwrap(), + ) } - pub fn position(&self, vertex: VertexIndex) -> Point { + pub fn position(&self, vertex: I) -> 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 { + fn vertex(&self, handle: FixedVertexHandle) -> I { spade::Triangulation::vertex(&self.triangulation, handle) .as_ref() - .vertex + .vertex() } - fn handle(&self, vertex: VertexIndex) -> FixedVertexHandle { + fn handle(&self, vertex: I) -> FixedVertexHandle { self.vertex_to_handle[vertex.node_index().index()].unwrap() } } -impl visit::GraphBase for Triangulation { - type NodeId = VertexIndex; - type EdgeId = (VertexIndex, VertexIndex); +impl + HasPosition> + visit::GraphBase for Triangulation +{ + type NodeId = I; + type EdgeId = (I, I); } -impl visit::Data for Triangulation { +impl + HasPosition> + visit::Data for Triangulation +{ type NodeWeight = (); type EdgeWeight = (); } -impl<'a> visit::IntoEdgeReferences for &'a Triangulation { - type EdgeRef = MeshEdgeReference; - type EdgeReferences = Box + 'a>; +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct TriangulationEdgeReference { + from: I, + to: I, +} + +impl visit::EdgeRef for TriangulationEdgeReference { + type NodeId = I; + type EdgeId = (I, I); + type Weight = (); + + fn source(&self) -> Self::NodeId { + self.from + } + + fn target(&self) -> Self::NodeId { + self.to + } + + fn weight(&self) -> &Self::Weight { + &() + } + + fn id(&self) -> Self::EdgeId { + (self.from, self.to) + } +} + +impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> + visit::IntoEdgeReferences for &'a Triangulation +{ + type EdgeRef = TriangulationEdgeReference; + type EdgeReferences = Box> + 'a>; fn edge_references(self) -> Self::EdgeReferences { Box::new( spade::Triangulation::directed_edges(&self.triangulation).map(|edge| { - MeshEdgeReference { + TriangulationEdgeReference { from: self.vertex(edge.from().fix()), to: self.vertex(edge.to().fix()), } @@ -102,8 +124,10 @@ impl<'a> visit::IntoEdgeReferences for &'a Triangulation { } } -impl<'a> visit::IntoNeighbors for &'a Triangulation { - type Neighbors = Box + 'a>; +impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> + visit::IntoNeighbors for &'a Triangulation +{ + type Neighbors = Box + 'a>; fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors { Box::new( @@ -114,14 +138,16 @@ impl<'a> visit::IntoNeighbors for &'a Triangulation { } } -impl<'a> visit::IntoEdges for &'a Triangulation { - type Edges = Box + 'a>; +impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> + 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 { + .map(|edge| TriangulationEdgeReference { from: self.vertex(edge.from().fix()), to: self.vertex(edge.to().fix()), }),