primitive: Move `.shape()` to a new trait `MakeShape`

This commit is contained in:
Mikolaj Wielgus 2023-10-19 06:38:57 +00:00
parent ae9dd23b7c
commit 4e21ff754d
5 changed files with 69 additions and 46 deletions

View File

@ -5,6 +5,7 @@ use crate::{
graph::{BendIndex, DotIndex}, graph::{BendIndex, DotIndex},
layout::Layout, layout::Layout,
math::{self, Circle}, math::{self, Circle},
primitive::MakeShape,
rules::{Conditions, Rules}, rules::{Conditions, Rules},
}; };

View File

@ -13,7 +13,7 @@ use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, Retag, SegIndex, SegWeight, BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, Retag, SegIndex, SegWeight,
Tag, TaggedIndex, Weight, Tag, TaggedIndex, Weight,
}; };
use crate::primitive::Primitive; use crate::primitive::{MakeShape, Primitive};
use crate::segbend::Segbend; use crate::segbend::Segbend;
use crate::shape::{Shape, ShapeTrait}; use crate::shape::{Shape, ShapeTrait};
@ -49,7 +49,7 @@ impl Layout {
} }
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))]
pub fn remove<Weight: std::marker::Copy>(&mut self, index: Index<Weight>) { pub fn remove<W: std::marker::Copy>(&mut self, index: Index<W>) {
// Unnecessary retag. It should be possible to elide it. // Unnecessary retag. It should be possible to elide it.
let weight = *self.graph.node_weight(index.index).unwrap(); let weight = *self.graph.node_weight(index.index).unwrap();
@ -236,11 +236,14 @@ impl Layout {
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count()))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count() - 1))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count() - 1))]
fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>( fn fail_and_remove_if_collides_except<W: std::marker::Copy>(
&mut self, &mut self,
index: Index<Weight>, index: Index<W>,
except: &[TaggedIndex], except: &[TaggedIndex],
) -> Result<(), ()> { ) -> Result<(), ()>
where
for<'a> Primitive<'a, W>: MakeShape,
{
if let Some(..) = self.detect_collision_except(index, except) { if let Some(..) = self.detect_collision_except(index, except) {
self.remove(index); self.remove(index);
return Err(()); return Err(());
@ -310,15 +313,18 @@ impl Layout {
Ok(()) Ok(())
} }
pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> { pub fn primitive<W>(&self, index: Index<W>) -> Primitive<W> {
Primitive::new(index, &self.graph) Primitive::new(index, &self.graph)
} }
fn detect_collision_except<Weight: std::marker::Copy>( fn detect_collision_except<W>(
&self, &self,
index: Index<Weight>, index: Index<W>,
except: &[TaggedIndex], except: &[TaggedIndex],
) -> Option<TaggedIndex> { ) -> Option<TaggedIndex>
where
for<'a> Primitive<'a, W>: MakeShape,
{
let primitive = self.primitive(index); let primitive = self.primitive(index);
let shape = primitive.shape(); let shape = primitive.shape();

View File

@ -7,8 +7,8 @@ use spade::{
DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation, DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation,
}; };
use crate::shape::ShapeTrait;
use crate::{graph::DotIndex, layout::Layout}; use crate::{graph::DotIndex, layout::Layout};
use crate::{primitive::MakeShape, shape::ShapeTrait};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Vertex { struct Vertex {

View File

@ -1,5 +1,6 @@
use std::mem::{self, swap}; use std::mem::{self, swap};
use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::{NodeIndex, StableDiGraph}; use petgraph::stable_graph::{NodeIndex, StableDiGraph};
use petgraph::Direction::{Incoming, Outgoing}; use petgraph::Direction::{Incoming, Outgoing};
@ -10,6 +11,10 @@ use crate::graph::{
use crate::math::{self, Circle}; use crate::math::{self, Circle};
use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait}; use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait};
pub trait MakeShape {
fn shape(&self) -> Shape;
}
#[derive(Debug)] #[derive(Debug)]
pub struct Primitive<'a, W> { pub struct Primitive<'a, W> {
pub index: Index<W>, pub index: Index<W>,
@ -21,38 +26,6 @@ impl<'a, W> Primitive<'a, W> {
Self { index, graph } Self { index, graph }
} }
pub fn shape(&self) -> Shape {
match self.tagged_weight() {
Weight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }),
Weight::Seg(seg) => {
let ends = self.ends();
Shape::Seg(SegShape {
from: self.primitive(ends.0).weight().circle.pos,
to: self.primitive(ends.1).weight().circle.pos,
width: seg.width,
})
}
Weight::Bend(bend) => {
let ends = self.ends();
let mut bend_shape = BendShape {
from: self.primitive(ends.0).weight().circle.pos,
to: self.primitive(ends.1).weight().circle.pos,
c: Circle {
pos: self.primitive(self.core().unwrap()).weight().circle.pos,
r: self.inner_radius(),
},
width: self.primitive(ends.0).weight().circle.r * 2.0,
};
if bend.cw {
swap(&mut bend_shape.from, &mut bend_shape.to);
}
Shape::Bend(bend_shape)
}
}
}
fn inner_radius(&self) -> f64 { fn inner_radius(&self) -> f64 {
let mut r = 0.0; let mut r = 0.0;
let mut layer = BendIndex::new(self.index.index); let mut layer = BendIndex::new(self.index.index);
@ -224,13 +197,13 @@ impl<'a, W> Primitive<'a, W> {
} }
} }
impl<'a, Weight> Interior<TaggedIndex> for Primitive<'a, Weight> { impl<'a, W> Interior<TaggedIndex> for Primitive<'a, W> {
fn interior(&self) -> Vec<TaggedIndex> { fn interior(&self) -> Vec<TaggedIndex> {
vec![self.tagged_index()] vec![self.tagged_index()]
} }
} }
impl<'a, Weight> Ends<DotIndex, DotIndex> for Primitive<'a, Weight> { impl<'a, W> Ends<DotIndex, DotIndex> for Primitive<'a, W> {
fn ends(&self) -> (DotIndex, DotIndex) { fn ends(&self) -> (DotIndex, DotIndex) {
let v = self let v = self
.graph .graph
@ -254,8 +227,6 @@ impl<'a, Weight> Ends<DotIndex, DotIndex> for Primitive<'a, Weight> {
} }
pub type Dot<'a> = Primitive<'a, DotWeight>; pub type Dot<'a> = Primitive<'a, DotWeight>;
pub type Seg<'a> = Primitive<'a, SegWeight>;
pub type Bend<'a> = Primitive<'a, BendWeight>;
impl<'a> Dot<'a> { impl<'a> Dot<'a> {
pub fn bend(&self) -> Option<BendIndex> { pub fn bend(&self) -> Option<BendIndex> {
@ -296,6 +267,16 @@ impl<'a> Dot<'a> {
} }
} }
impl<'a> MakeShape for Dot<'a> {
fn shape(&self) -> Shape {
Shape::Dot(DotShape {
c: self.weight().circle,
})
}
}
pub type Seg<'a> = Primitive<'a, SegWeight>;
impl<'a> Seg<'a> { impl<'a> Seg<'a> {
pub fn next(&self) -> Option<DotIndex> { pub fn next(&self) -> Option<DotIndex> {
self.next_node().map(|ni| DotIndex::new(ni)) self.next_node().map(|ni| DotIndex::new(ni))
@ -310,6 +291,19 @@ impl<'a> Seg<'a> {
} }
} }
impl<'a> MakeShape for Seg<'a> {
fn shape(&self) -> Shape {
let ends = self.ends();
Shape::Seg(SegShape {
from: self.primitive(ends.0).weight().circle.pos,
to: self.primitive(ends.1).weight().circle.pos,
width: self.weight().width,
})
}
}
pub type Bend<'a> = Primitive<'a, BendWeight>;
impl<'a> Bend<'a> { impl<'a> Bend<'a> {
pub fn around(&self) -> TaggedIndex { pub fn around(&self) -> TaggedIndex {
if let Some(inner) = self.inner() { if let Some(inner) = self.inner() {
@ -365,3 +359,24 @@ impl<'a> Bend<'a> {
math::cross_product(end1 - center, end2 - center) math::cross_product(end1 - center, end2 - center)
} }
} }
impl<'a> MakeShape for Bend<'a> {
fn shape(&self) -> Shape {
let ends = self.ends();
let mut bend_shape = BendShape {
from: self.primitive(ends.0).weight().circle.pos,
to: self.primitive(ends.1).weight().circle.pos,
c: Circle {
pos: self.primitive(self.core().unwrap()).weight().circle.pos,
r: self.inner_radius(),
},
width: self.primitive(ends.0).weight().circle.r * 2.0,
};
if self.weight().cw {
swap(&mut bend_shape.from, &mut bend_shape.to);
}
Shape::Bend(bend_shape)
}
}

View File

@ -6,6 +6,7 @@ use crate::{
graph::{BendIndex, DotIndex, Ends}, graph::{BendIndex, DotIndex, Ends},
layout::Layout, layout::Layout,
mesh::{Mesh, MeshEdgeReference, VertexIndex}, mesh::{Mesh, MeshEdgeReference, VertexIndex},
primitive::MakeShape,
rules::Rules, rules::Rules,
}; };