mirror of https://codeberg.org/topola/topola.git
mesh: fix finding neighbors and edges from non-triangulation vertices
This fixes a panic caused by lack of implementation of handling of these.
This commit is contained in:
parent
84d5f9c49e
commit
9a755059c0
137
src/mesh.rs
137
src/mesh.rs
|
|
@ -3,7 +3,7 @@ use std::iter;
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use petgraph::visit;
|
use petgraph::visit::{self, NodeIndexable};
|
||||||
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
|
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
|
||||||
use spade::{HasPosition, InsertionError, Point2};
|
use spade::{HasPosition, InsertionError, Point2};
|
||||||
|
|
||||||
|
|
@ -25,15 +25,31 @@ pub enum VertexIndex {
|
||||||
LooseBend(LooseBendIndex),
|
LooseBend(LooseBendIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[enum_dispatch(GetNodeIndex, MakePrimitive)]
|
||||||
|
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum TriangulationVertexIndex {
|
||||||
|
FixedDot(FixedDotIndex),
|
||||||
|
FixedBend(FixedBendIndex),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TriangulationVertexIndex> for VertexIndex {
|
||||||
|
fn from(vertex: TriangulationVertexIndex) -> Self {
|
||||||
|
match vertex {
|
||||||
|
TriangulationVertexIndex::FixedDot(dot) => VertexIndex::FixedDot(dot),
|
||||||
|
TriangulationVertexIndex::FixedBend(bend) => VertexIndex::FixedBend(bend),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct TriangulationWeight {
|
struct TriangulationWeight {
|
||||||
vertex: VertexIndex,
|
vertex: TriangulationVertexIndex,
|
||||||
rails: Vec<LooseBendIndex>,
|
rails: Vec<LooseBendIndex>,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetVertexIndex<VertexIndex> for TriangulationWeight {
|
impl GetVertexIndex<TriangulationVertexIndex> for TriangulationWeight {
|
||||||
fn vertex(&self) -> VertexIndex {
|
fn vertex(&self) -> TriangulationVertexIndex {
|
||||||
self.vertex
|
self.vertex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -47,14 +63,19 @@ impl HasPosition for TriangulationWeight {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
triangulation: Triangulation<VertexIndex, TriangulationWeight>,
|
triangulation: Triangulation<TriangulationVertexIndex, TriangulationWeight>,
|
||||||
|
vertex_to_triangulation_vertex: Vec<Option<TriangulationVertexIndex>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
pub fn new(layout: &Layout) -> Self {
|
pub fn new(layout: &Layout) -> Self {
|
||||||
Self {
|
let mut this = Self {
|
||||||
triangulation: Triangulation::new(layout),
|
triangulation: Triangulation::new(layout),
|
||||||
}
|
vertex_to_triangulation_vertex: Vec::new(),
|
||||||
|
};
|
||||||
|
this.vertex_to_triangulation_vertex
|
||||||
|
.resize(layout.graph.node_bound(), None);
|
||||||
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> {
|
pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> {
|
||||||
|
|
@ -62,16 +83,16 @@ impl Mesh {
|
||||||
let center = node.primitive(layout).shape().center();
|
let center = node.primitive(layout).shape().center();
|
||||||
|
|
||||||
match node {
|
match node {
|
||||||
Index::FixedDot(fixed_dot) => {
|
Index::FixedDot(dot) => {
|
||||||
self.triangulation.add_vertex(TriangulationWeight {
|
self.triangulation.add_vertex(TriangulationWeight {
|
||||||
vertex: fixed_dot.into(),
|
vertex: dot.into(),
|
||||||
rails: vec![],
|
rails: vec![],
|
||||||
pos: center,
|
pos: center,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Index::FixedBend(fixed_bend) => {
|
Index::FixedBend(bend) => {
|
||||||
self.triangulation.add_vertex(TriangulationWeight {
|
self.triangulation.add_vertex(TriangulationWeight {
|
||||||
vertex: fixed_bend.into(),
|
vertex: bend.into(),
|
||||||
rails: vec![],
|
rails: vec![],
|
||||||
pos: center,
|
pos: center,
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -81,12 +102,15 @@ impl Mesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
for node in layout.nodes() {
|
for node in layout.nodes() {
|
||||||
|
// Add rails as vertices. This is how the mesh differs from the triangulation.
|
||||||
match node {
|
match node {
|
||||||
Index::LooseBend(loose_bend) => {
|
Index::LooseBend(bend) => {
|
||||||
self.triangulation
|
self.triangulation
|
||||||
.weight_mut(layout.primitive(loose_bend).core().into())
|
.weight_mut(layout.primitive(bend).core().into())
|
||||||
.rails
|
.rails
|
||||||
.push(loose_bend.into());
|
.push(bend.into());
|
||||||
|
self.vertex_to_triangulation_vertex[bend.node_index().index()] =
|
||||||
|
Some(layout.primitive(bend).core().into());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +118,16 @@ impl Mesh {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn triangulation_vertex(&self, vertex: VertexIndex) -> TriangulationVertexIndex {
|
||||||
|
match vertex {
|
||||||
|
VertexIndex::FixedDot(dot) => TriangulationVertexIndex::FixedDot(dot),
|
||||||
|
VertexIndex::FixedBend(bend) => TriangulationVertexIndex::FixedBend(bend),
|
||||||
|
VertexIndex::LooseBend(bend) => {
|
||||||
|
self.vertex_to_triangulation_vertex[bend.node_index().index()].unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl visit::GraphBase for Mesh {
|
impl visit::GraphBase for Mesh {
|
||||||
|
|
@ -138,23 +172,29 @@ 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).flat_map(|neighbor| {
|
Box::new(
|
||||||
iter::once(neighbor).chain(
|
self.triangulation
|
||||||
self.triangulation
|
.neighbors(self.triangulation_vertex(vertex))
|
||||||
.weight(neighbor)
|
.flat_map(|neighbor| {
|
||||||
.rails
|
iter::once(neighbor.into()).chain(
|
||||||
.iter()
|
self.triangulation
|
||||||
.map(|index| VertexIndex::from(*index)),
|
.weight(neighbor)
|
||||||
)
|
.rails
|
||||||
}))
|
.iter()
|
||||||
|
.map(|index| VertexIndex::from(*index)),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edges(
|
fn edge_with_near_edges(
|
||||||
triangulation: &Triangulation<VertexIndex, TriangulationWeight>,
|
triangulation: &Triangulation<TriangulationVertexIndex, TriangulationWeight>,
|
||||||
edge: TriangulationEdgeReference<VertexIndex>,
|
edge: TriangulationEdgeReference<TriangulationVertexIndex>,
|
||||||
) -> impl Iterator<Item = MeshEdgeReference> {
|
) -> impl Iterator<Item = MeshEdgeReference> {
|
||||||
let mut from_vertices = vec![edge.source()];
|
let mut from_vertices = vec![edge.source().into()];
|
||||||
|
|
||||||
|
// Append rails to the source.
|
||||||
from_vertices.extend(
|
from_vertices.extend(
|
||||||
triangulation
|
triangulation
|
||||||
.weight(edge.source())
|
.weight(edge.source())
|
||||||
|
|
@ -163,7 +203,9 @@ fn edges(
|
||||||
.map(|bend| VertexIndex::from(*bend)),
|
.map(|bend| VertexIndex::from(*bend)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut to_vertices = vec![edge.target()];
|
let mut to_vertices = vec![edge.target().into()];
|
||||||
|
|
||||||
|
// Append rails to the target.
|
||||||
to_vertices.extend(
|
to_vertices.extend(
|
||||||
triangulation
|
triangulation
|
||||||
.weight(edge.target())
|
.weight(edge.target())
|
||||||
|
|
@ -172,12 +214,13 @@ fn edges(
|
||||||
.map(|bend| VertexIndex::from(*bend)),
|
.map(|bend| VertexIndex::from(*bend)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Return cartesian product.
|
||||||
from_vertices
|
from_vertices
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cartesian_product(to_vertices.into_iter())
|
.cartesian_product(to_vertices.into_iter())
|
||||||
.map(|pair| MeshEdgeReference {
|
.map(|pair| MeshEdgeReference {
|
||||||
from: pair.0,
|
from: pair.0,
|
||||||
to: pair.1,
|
to: pair.1.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,20 +232,46 @@ impl<'a> visit::IntoEdgeReferences for &'a Mesh {
|
||||||
Box::new(
|
Box::new(
|
||||||
self.triangulation
|
self.triangulation
|
||||||
.edge_references()
|
.edge_references()
|
||||||
.flat_map(move |edge| edges(&self.triangulation, edge)),
|
.flat_map(move |edge| edge_with_near_edges(&self.triangulation, edge)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vertex_edges(
|
||||||
|
triangulation: &Triangulation<TriangulationVertexIndex, TriangulationWeight>,
|
||||||
|
from: VertexIndex,
|
||||||
|
to: TriangulationVertexIndex,
|
||||||
|
) -> impl Iterator<Item = MeshEdgeReference> {
|
||||||
|
let from_vertices = vec![from];
|
||||||
|
let mut to_vertices = vec![to.into()];
|
||||||
|
|
||||||
|
// Append rails to the target.
|
||||||
|
to_vertices.extend(
|
||||||
|
triangulation
|
||||||
|
.weight(to)
|
||||||
|
.rails
|
||||||
|
.iter()
|
||||||
|
.map(|bend| VertexIndex::from(*bend)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return cartesian product.
|
||||||
|
from_vertices
|
||||||
|
.into_iter()
|
||||||
|
.cartesian_product(to_vertices.into_iter())
|
||||||
|
.map(|pair| MeshEdgeReference {
|
||||||
|
from: pair.0,
|
||||||
|
to: pair.1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
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, node: Self::NodeId) -> Self::Edges {
|
fn edges(self, vertex: Self::NodeId) -> Self::Edges {
|
||||||
Box::new(
|
Box::new(
|
||||||
self.triangulation
|
self.triangulation
|
||||||
// FIXME: node has to be converted to triangulation vertex (?)
|
.edges(self.triangulation_vertex(vertex))
|
||||||
.edges(node)
|
.flat_map(move |edge| vertex_edges(&self.triangulation, vertex, edge.target())),
|
||||||
.flat_map(move |edge| edges(&self.triangulation, edge)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue