mirror of https://codeberg.org/topola/topola.git
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.
This commit is contained in:
parent
66d5b3e605
commit
8379470bb1
|
|
@ -23,6 +23,7 @@ mod segbend;
|
||||||
mod shape;
|
mod shape;
|
||||||
mod tracer;
|
mod tracer;
|
||||||
mod traverser;
|
mod traverser;
|
||||||
|
mod triangulation;
|
||||||
|
|
||||||
use geo::point;
|
use geo::point;
|
||||||
use graph::{FixedDotIndex, FixedSegWeight, LooseDotIndex};
|
use graph::{FixedDotIndex, FixedSegWeight, LooseDotIndex};
|
||||||
|
|
|
||||||
95
src/mesh.rs
95
src/mesh.rs
|
|
@ -1,25 +1,16 @@
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use fixedbitset::FixedBitSet;
|
use geo::Point;
|
||||||
use geo::{point, Point};
|
|
||||||
use petgraph::stable_graph::NodeIndex;
|
use petgraph::stable_graph::NodeIndex;
|
||||||
use petgraph::visit::{self, NodeIndexable};
|
use petgraph::visit;
|
||||||
use spade::{
|
use spade::InsertionError;
|
||||||
handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError, Point2,
|
|
||||||
Triangulation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graph::{FixedBendIndex, FixedDotIndex, GetNodeIndex, Index, LooseBendIndex},
|
graph::{FixedBendIndex, FixedDotIndex, GetNodeIndex, Index, LooseBendIndex},
|
||||||
layout::Layout,
|
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)]
|
#[enum_dispatch(GetNodeIndex)]
|
||||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|
@ -29,60 +20,32 @@ pub enum VertexIndex {
|
||||||
LooseBend(LooseBendIndex),
|
LooseBend(LooseBendIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasPosition for Vertex {
|
|
||||||
type Scalar = f64;
|
|
||||||
fn position(&self) -> Point2<Self::Scalar> {
|
|
||||||
Point2::new(self.x, self.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
triangulation: DelaunayTriangulation<Vertex>,
|
triangulation: Triangulation,
|
||||||
vertex_to_handle: Vec<Option<FixedVertexHandle>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
pub fn new() -> Self {
|
pub fn new(layout: &Layout) -> Self {
|
||||||
Self {
|
Self {
|
||||||
triangulation: DelaunayTriangulation::new(),
|
triangulation: Triangulation::new(layout),
|
||||||
vertex_to_handle: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn triangulate(&mut self, layout: &Layout) -> Result<(), InsertionError> {
|
pub fn generate(&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);
|
|
||||||
|
|
||||||
for node in layout.nodes() {
|
for node in layout.nodes() {
|
||||||
if let Index::FixedDot(dot) = node {
|
if let Index::FixedDot(dot) = node {
|
||||||
let center = layout.primitive(dot).shape().center();
|
let center = layout.primitive(dot).shape().center();
|
||||||
|
|
||||||
self.vertex_to_handle[dot.node_index().index()] =
|
self.triangulation
|
||||||
Some(self.triangulation.insert(Vertex {
|
.add_vertex(dot.into(), center.x(), center.y());
|
||||||
graph_index: dot.into(),
|
|
||||||
x: center.x(),
|
|
||||||
y: center.y(),
|
|
||||||
})?);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
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 {
|
pub fn position(&self, vertex: VertexIndex) -> Point {
|
||||||
let position = self.triangulation.vertex(self.handle(vertex)).position();
|
self.triangulation.position(vertex)
|
||||||
point! {x: position.x, y: position.y}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,8 +61,8 @@ impl visit::Data for Mesh {
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MeshEdgeReference {
|
pub struct MeshEdgeReference {
|
||||||
from: VertexIndex,
|
pub from: VertexIndex,
|
||||||
to: VertexIndex,
|
pub to: VertexIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> visit::EdgeRef for MeshEdgeReference {
|
impl<'a> visit::EdgeRef for MeshEdgeReference {
|
||||||
|
|
@ -129,14 +92,7 @@ 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(
|
Box::new(self.triangulation.edge_references())
|
||||||
self.triangulation
|
|
||||||
.directed_edges()
|
|
||||||
.map(|edge| MeshEdgeReference {
|
|
||||||
from: self.vertex(edge.from().fix()),
|
|
||||||
to: self.vertex(edge.to().fix()),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,27 +100,14 @@ impl<'a> visit::IntoNeighbors for &'a Mesh {
|
||||||
type Neighbors = Box<dyn Iterator<Item = VertexIndex> + 'a>;
|
type Neighbors = Box<dyn Iterator<Item = VertexIndex> + 'a>;
|
||||||
|
|
||||||
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors {
|
||||||
Box::new(
|
self.triangulation.neighbors(vertex)
|
||||||
self.triangulation
|
|
||||||
.vertex(self.handle(vertex))
|
|
||||||
.out_edges()
|
|
||||||
.map(|handle| self.vertex(handle.to().fix())),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> visit::IntoEdges for &'a Mesh {
|
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, a: Self::NodeId) -> Self::Edges {
|
fn edges(self, node: Self::NodeId) -> Self::Edges {
|
||||||
Box::new(
|
Box::new(self.triangulation.edges(node))
|
||||||
self.triangulation
|
|
||||||
.vertex(self.handle(a))
|
|
||||||
.out_edges()
|
|
||||||
.map(|edge| MeshEdgeReference {
|
|
||||||
from: self.vertex(edge.from().fix()),
|
|
||||||
to: self.vertex(edge.to().fix()),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ impl Router {
|
||||||
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
|
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
|
||||||
// right.
|
// right.
|
||||||
//self.mesh.triangulate(&self.layout)?;
|
//self.mesh.triangulate(&self.layout)?;
|
||||||
let mut mesh = Mesh::new();
|
let mut mesh = Mesh::new(&self.layout);
|
||||||
mesh.triangulate(&self.layout)?;
|
mesh.generate(&self.layout)?;
|
||||||
|
|
||||||
let mut tracer = self.tracer(&mesh);
|
let mut tracer = self.tracer(&mesh);
|
||||||
let trace = tracer.start(from);
|
let trace = tracer.start(from);
|
||||||
|
|
@ -129,7 +129,7 @@ impl Router {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.enroute(from, to_dot, observer)*/
|
self.enroute(from, to_dot, observer)*/
|
||||||
Ok(Mesh::new())
|
Ok(Mesh::new(&self.layout))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*pub fn squeeze_around_dot(
|
/*pub fn squeeze_around_dot(
|
||||||
|
|
|
||||||
|
|
@ -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<Self::Scalar> {
|
||||||
|
Point2::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Triangulation {
|
||||||
|
triangulation: DelaunayTriangulation<VertexWeight>,
|
||||||
|
vertex_to_handle: Vec<Option<FixedVertexHandle>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Triangulation {
|
||||||
|
pub fn new(layout: &Layout) -> Self {
|
||||||
|
let mut this = Self {
|
||||||
|
triangulation: <DelaunayTriangulation<VertexWeight> 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<dyn Iterator<Item = MeshEdgeReference> + '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<dyn Iterator<Item = VertexIndex> + '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<dyn Iterator<Item = MeshEdgeReference> + '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()),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue