mirror of https://codeberg.org/topola/topola.git
triangulation: Parameterize to make independent from `Mesh`
This commit is contained in:
parent
961fc02678
commit
d6163d3d44
67
src/mesh.rs
67
src/mesh.rs
|
|
@ -1,15 +1,15 @@
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
use petgraph::stable_graph::NodeIndex;
|
|
||||||
use petgraph::visit;
|
use petgraph::visit;
|
||||||
use spade::InsertionError;
|
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
|
||||||
|
use spade::{HasPosition, InsertionError, Point2};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graph::{FixedBendIndex, FixedDotIndex, GetNodeIndex, Index, LooseBendIndex, MakePrimitive},
|
graph::{FixedBendIndex, FixedDotIndex, GetNodeIndex, Index, LooseBendIndex, MakePrimitive},
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
primitive::{GetCore, MakeShape},
|
primitive::MakeShape,
|
||||||
shape::ShapeTrait,
|
shape::ShapeTrait,
|
||||||
triangulation::Triangulation,
|
triangulation::{GetVertexIndex, Triangulation},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[enum_dispatch(GetNodeIndex)]
|
#[enum_dispatch(GetNodeIndex)]
|
||||||
|
|
@ -20,9 +20,28 @@ pub enum VertexIndex {
|
||||||
LooseBend(LooseBendIndex),
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
triangulation: Triangulation,
|
triangulation: Triangulation<VertexIndex, TriangulationWeight>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
|
|
@ -38,12 +57,16 @@ impl Mesh {
|
||||||
|
|
||||||
match node {
|
match node {
|
||||||
Index::FixedDot(fixed_dot) => {
|
Index::FixedDot(fixed_dot) => {
|
||||||
self.triangulation
|
self.triangulation.add_vertex(TriangulationWeight {
|
||||||
.add_vertex(fixed_dot.into(), center.x(), center.y())?;
|
vertex: fixed_dot.into(),
|
||||||
|
pos: center,
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
Index::FixedBend(fixed_bend) => {
|
Index::FixedBend(fixed_bend) => {
|
||||||
self.triangulation
|
self.triangulation.add_vertex(TriangulationWeight {
|
||||||
.add_vertex(fixed_bend.into(), center.x(), center.y())?;
|
vertex: fixed_bend.into(),
|
||||||
|
pos: center,
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
/*Index::LooseBend(loose_bend) => {
|
/*Index::LooseBend(loose_bend) => {
|
||||||
self.triangulation.add_bend(
|
self.triangulation.add_bend(
|
||||||
|
|
@ -72,13 +95,13 @@ impl visit::Data for Mesh {
|
||||||
type EdgeWeight = ();
|
type EdgeWeight = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct MeshEdgeReference {
|
pub struct MeshEdgeReference {
|
||||||
pub from: VertexIndex,
|
from: VertexIndex,
|
||||||
pub to: VertexIndex,
|
to: VertexIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> visit::EdgeRef for MeshEdgeReference {
|
impl visit::EdgeRef for MeshEdgeReference {
|
||||||
type NodeId = VertexIndex;
|
type NodeId = VertexIndex;
|
||||||
type EdgeId = (VertexIndex, VertexIndex);
|
type EdgeId = (VertexIndex, VertexIndex);
|
||||||
type Weight = ();
|
type Weight = ();
|
||||||
|
|
@ -105,7 +128,14 @@ impl<'a> visit::IntoEdgeReferences for &'a Mesh {
|
||||||
type EdgeReferences = Box<dyn Iterator<Item = MeshEdgeReference> + 'a>;
|
type EdgeReferences = Box<dyn Iterator<Item = MeshEdgeReference> + 'a>;
|
||||||
|
|
||||||
fn edge_references(self) -> Self::EdgeReferences {
|
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>;
|
type Edges = Box<dyn Iterator<Item = MeshEdgeReference> + 'a>;
|
||||||
|
|
||||||
fn edges(self, node: Self::NodeId) -> Self::Edges {
|
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(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,99 +1,121 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use geo::{point, Point};
|
use geo::{point, Point};
|
||||||
use petgraph::visit::{self, NodeIndexable};
|
use petgraph::visit::{self, NodeIndexable};
|
||||||
use spade::{
|
use spade::{handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError};
|
||||||
handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError, Point2,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{graph::GetNodeIndex, layout::Layout};
|
||||||
graph::GetNodeIndex,
|
|
||||||
layout::Layout,
|
|
||||||
mesh::{MeshEdgeReference, VertexIndex},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
pub trait GetVertexIndex<I> {
|
||||||
struct VertexWeight {
|
fn vertex(&self) -> I;
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Triangulation {
|
pub struct Triangulation<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition> {
|
||||||
triangulation: DelaunayTriangulation<VertexWeight>,
|
triangulation: DelaunayTriangulation<W>,
|
||||||
vertex_to_handle: Vec<Option<FixedVertexHandle>>,
|
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 {
|
pub fn new(layout: &Layout) -> Self {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
triangulation: <DelaunayTriangulation<VertexWeight> as spade::Triangulation>::new(),
|
triangulation: <DelaunayTriangulation<W> as spade::Triangulation>::new(),
|
||||||
vertex_to_handle: Vec::new(),
|
vertex_to_handle: Vec::new(),
|
||||||
|
index_marker: PhantomData,
|
||||||
};
|
};
|
||||||
this.vertex_to_handle
|
this.vertex_to_handle
|
||||||
.resize(layout.graph.node_bound(), None);
|
.resize(layout.graph.node_bound(), None);
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_vertex(
|
pub fn add_vertex(&mut self, weight: W) -> Result<(), InsertionError> {
|
||||||
&mut self,
|
let index = weight.vertex().node_index().index();
|
||||||
vertex: VertexIndex,
|
self.vertex_to_handle[index] = Some(spade::Triangulation::insert(
|
||||||
x: f64,
|
|
||||||
y: f64,
|
|
||||||
) -> Result<(), InsertionError> {
|
|
||||||
self.vertex_to_handle[vertex.node_index().index()] = Some(spade::Triangulation::insert(
|
|
||||||
&mut self.triangulation,
|
&mut self.triangulation,
|
||||||
VertexWeight { vertex, x, y },
|
weight,
|
||||||
)?);
|
)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn project_vertex(&mut self, from: VertexIndex, to: VertexIndex) {
|
pub fn weight_mut(&mut self, vertex: I) -> &mut W {
|
||||||
self.vertex_to_handle[from.node_index().index()] =
|
spade::Triangulation::vertex_data_mut(
|
||||||
self.vertex_to_handle[to.node_index().index()]
|
&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 =
|
let position =
|
||||||
spade::Triangulation::vertex(&self.triangulation, self.handle(vertex)).position();
|
spade::Triangulation::vertex(&self.triangulation, self.handle(vertex)).position();
|
||||||
point! {x: position.x, y: position.y}
|
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)
|
spade::Triangulation::vertex(&self.triangulation, handle)
|
||||||
.as_ref()
|
.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()
|
self.vertex_to_handle[vertex.node_index().index()].unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl visit::GraphBase for Triangulation {
|
impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
|
||||||
type NodeId = VertexIndex;
|
visit::GraphBase for Triangulation<I, W>
|
||||||
type EdgeId = (VertexIndex, VertexIndex);
|
{
|
||||||
|
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 NodeWeight = ();
|
||||||
type EdgeWeight = ();
|
type EdgeWeight = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> visit::IntoEdgeReferences for &'a Triangulation {
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
type EdgeRef = MeshEdgeReference;
|
pub struct TriangulationEdgeReference<I> {
|
||||||
type EdgeReferences = Box<dyn Iterator<Item = MeshEdgeReference> + 'a>;
|
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 {
|
fn edge_references(self) -> Self::EdgeReferences {
|
||||||
Box::new(
|
Box::new(
|
||||||
spade::Triangulation::directed_edges(&self.triangulation).map(|edge| {
|
spade::Triangulation::directed_edges(&self.triangulation).map(|edge| {
|
||||||
MeshEdgeReference {
|
TriangulationEdgeReference {
|
||||||
from: self.vertex(edge.from().fix()),
|
from: self.vertex(edge.from().fix()),
|
||||||
to: self.vertex(edge.to().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 {
|
impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
|
||||||
type Neighbors = Box<dyn Iterator<Item = VertexIndex> + 'a>;
|
visit::IntoNeighbors for &'a Triangulation<I, W>
|
||||||
|
{
|
||||||
|
type Neighbors = Box<dyn Iterator<Item = I> + 'a>;
|
||||||
|
|
||||||
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
||||||
Box::new(
|
Box::new(
|
||||||
|
|
@ -114,14 +138,16 @@ impl<'a> visit::IntoNeighbors for &'a Triangulation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> visit::IntoEdges for &'a Triangulation {
|
impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
|
||||||
type Edges = Box<dyn Iterator<Item = MeshEdgeReference> + 'a>;
|
visit::IntoEdges for &'a Triangulation<I, W>
|
||||||
|
{
|
||||||
|
type Edges = Box<dyn Iterator<Item = TriangulationEdgeReference<I>> + 'a>;
|
||||||
|
|
||||||
fn edges(self, node: Self::NodeId) -> Self::Edges {
|
fn edges(self, node: Self::NodeId) -> Self::Edges {
|
||||||
Box::new(
|
Box::new(
|
||||||
spade::Triangulation::vertex(&self.triangulation, self.handle(node))
|
spade::Triangulation::vertex(&self.triangulation, self.handle(node))
|
||||||
.out_edges()
|
.out_edges()
|
||||||
.map(|edge| MeshEdgeReference {
|
.map(|edge| TriangulationEdgeReference {
|
||||||
from: self.vertex(edge.from().fix()),
|
from: self.vertex(edge.from().fix()),
|
||||||
to: self.vertex(edge.to().fix()),
|
to: self.vertex(edge.to().fix()),
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue