triangulation: Parameterize to make independent from `Mesh`

This commit is contained in:
Mikolaj Wielgus 2023-11-05 20:19:18 +00:00
parent 961fc02678
commit d6163d3d44
2 changed files with 130 additions and 67 deletions

View File

@ -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<VertexIndex> for TriangulationWeight {
fn vertex(&self) -> VertexIndex {
self.vertex
}
}
impl HasPosition for TriangulationWeight {
type Scalar = f64;
fn position(&self) -> Point2<Self::Scalar> {
Point2::new(self.pos.x(), self.pos.y())
}
}
#[derive(Debug, Clone)]
pub struct Mesh {
triangulation: Triangulation,
triangulation: Triangulation<VertexIndex, TriangulationWeight>,
}
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<dyn Iterator<Item = MeshEdgeReference> + '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<dyn Iterator<Item = MeshEdgeReference> + '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(),
}),
)
}
}

View File

@ -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<Self::Scalar> {
Point2::new(self.x, self.y)
}
pub trait GetVertexIndex<I> {
fn vertex(&self) -> I;
}
#[derive(Debug, Clone)]
pub struct Triangulation {
triangulation: DelaunayTriangulation<VertexWeight>,
pub struct Triangulation<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition> {
triangulation: DelaunayTriangulation<W>,
vertex_to_handle: Vec<Option<FixedVertexHandle>>,
index_marker: PhantomData<I>,
}
impl Triangulation {
impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
Triangulation<I, W>
{
pub fn new(layout: &Layout) -> Self {
let mut this = Self {
triangulation: <DelaunayTriangulation<VertexWeight> as spade::Triangulation>::new(),
triangulation: <DelaunayTriangulation<W> 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<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
visit::GraphBase for Triangulation<I, W>
{
type NodeId = I;
type EdgeId = (I, I);
}
impl visit::Data for Triangulation {
impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
visit::Data for Triangulation<I, W>
{
type NodeWeight = ();
type EdgeWeight = ();
}
impl<'a> visit::IntoEdgeReferences for &'a Triangulation {
type EdgeRef = MeshEdgeReference;
type EdgeReferences = Box<dyn Iterator<Item = MeshEdgeReference> + 'a>;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TriangulationEdgeReference<I> {
from: I,
to: I,
}
impl<I: Copy> visit::EdgeRef for TriangulationEdgeReference<I> {
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<I> + HasPosition<Scalar = f64>>
visit::IntoEdgeReferences for &'a Triangulation<I, W>
{
type EdgeRef = TriangulationEdgeReference<I>;
type EdgeReferences = Box<dyn Iterator<Item = TriangulationEdgeReference<I>> + '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<dyn Iterator<Item = VertexIndex> + 'a>;
impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
visit::IntoNeighbors for &'a Triangulation<I, W>
{
type Neighbors = Box<dyn Iterator<Item = I> + '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<dyn Iterator<Item = MeshEdgeReference> + 'a>;
impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
visit::IntoEdges for &'a Triangulation<I, W>
{
type Edges = Box<dyn Iterator<Item = TriangulationEdgeReference<I>> + '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()),
}),