mirror of https://codeberg.org/topola/topola.git
Rename `Primitive` to `Shape`, introduce new `Primitive`
Move some `Mesh` methods into `Primitive`.
This commit is contained in:
parent
69317384dd
commit
8b5cfb3686
|
|
@ -5,8 +5,8 @@ use geo::geometry::Point;
|
|||
use crate::math::Circle;
|
||||
use crate::mesh::{Mesh, TaggedIndex, RTreeWrapper, DotIndex, SegIndex, BendIndex, Tag};
|
||||
use crate::rules::{Rules, Conditions};
|
||||
use crate::primitive::Primitive;
|
||||
use crate::weight::{Weight, DotWeight, SegWeight, BendWeight};
|
||||
use crate::shape::Shape;
|
||||
use crate::weight::{TaggedWeight, DotWeight, SegWeight, BendWeight};
|
||||
use crate::math;
|
||||
|
||||
|
||||
|
|
@ -32,6 +32,32 @@ impl Layout {
|
|||
Head {dot: from, bend: None}
|
||||
}
|
||||
|
||||
pub fn route_end(&mut self, head: Head, to: DotIndex, width: f64) {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
let conditions = Conditions {
|
||||
lower_net: None,
|
||||
higher_net: None,
|
||||
layer: None,
|
||||
zone: None,
|
||||
};
|
||||
|
||||
let to_circle = Circle {
|
||||
pos: self.mesh.primitive(to).weight().circle.pos,
|
||||
r: 0.0,
|
||||
};
|
||||
|
||||
let from_cw = self.head_cw(&head);
|
||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None);
|
||||
|
||||
let head = self.extend_head(head, tangent_points.0);
|
||||
self.add_seg(head.dot, to, width);
|
||||
}
|
||||
|
||||
/*pub fn shove_around_dot(&mut self, head: Head, around: DotIndex, cw: bool, width: f64) -> Head {
|
||||
|
||||
}*/
|
||||
|
||||
pub fn route_around_dot(&mut self, head: Head, around: DotIndex, cw: bool, width: f64) -> Head {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
|
|
@ -70,41 +96,19 @@ impl Layout {
|
|||
self.route_seg_bend(head, TaggedIndex::Bend(around), tangent_points.1, cw, width)
|
||||
}
|
||||
|
||||
pub fn route_end(&mut self, head: Head, to: DotIndex, width: f64) {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
let conditions = Conditions {
|
||||
lower_net: None,
|
||||
higher_net: None,
|
||||
layer: None,
|
||||
zone: None,
|
||||
};
|
||||
|
||||
let to_circle = Circle {
|
||||
pos: self.mesh.dot_weight(to).circle.pos,
|
||||
r: 0.0,
|
||||
};
|
||||
|
||||
let from_cw = self.head_cw(&head);
|
||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None);
|
||||
|
||||
let head = self.extend_head(head, tangent_points.0);
|
||||
self.add_seg(head.dot, to, width);
|
||||
}
|
||||
|
||||
fn route_seg_bend(&mut self, head: Head, around: TaggedIndex, to: Point, cw: bool, width: f64) -> Head {
|
||||
let head = self.route_seg(head, to, width);
|
||||
let bend_to = self.add_dot(self.mesh.dot_weight(head.dot));
|
||||
let net = self.mesh.dot_weight(head.dot).net;
|
||||
let bend_to = self.add_dot(self.mesh.primitive(head.dot).weight());
|
||||
let net = self.mesh.primitive(head.dot).weight().net;
|
||||
|
||||
let bend = self.mesh.add_bend(head.dot, bend_to, around, BendWeight {net, cw});
|
||||
Head {dot: bend_to, bend: Some(bend)}
|
||||
}
|
||||
|
||||
fn route_seg(&mut self, head: Head, to: Point, width: f64) -> Head {
|
||||
let net = self.mesh.dot_weight(head.dot).net;
|
||||
let net = self.mesh.primitive(head.dot).weight().net;
|
||||
|
||||
assert!(width <= self.mesh.dot_weight(head.dot).circle.r * 2.0);
|
||||
assert!(width <= self.mesh.primitive(head.dot).weight().circle.r * 2.0);
|
||||
|
||||
let to_index = self.mesh.add_dot(DotWeight {
|
||||
net,
|
||||
|
|
@ -126,14 +130,14 @@ impl Layout {
|
|||
|
||||
match maybe_bend {
|
||||
Some(bend) => {
|
||||
if let Some(inner) = self.mesh.inner(bend) {
|
||||
if let Some(inner) = self.mesh.primitive(bend).inner() {
|
||||
self.bend_guidecircle(inner, width, conditions)
|
||||
} else {
|
||||
self.dot_guidecircle(self.mesh.core(bend), width + 5.0, conditions)
|
||||
self.dot_guidecircle(self.mesh.primitive(bend).core(), width + 5.0, conditions)
|
||||
}
|
||||
},
|
||||
None => Circle {
|
||||
pos: self.mesh.dot_weight(head.dot).circle.pos,
|
||||
pos: self.mesh.primitive(head.dot).weight().circle.pos,
|
||||
r: 0.0,
|
||||
},
|
||||
}
|
||||
|
|
@ -141,13 +145,13 @@ impl Layout {
|
|||
|
||||
fn head_cw(&self, head: &Head) -> Option<bool> {
|
||||
match head.bend {
|
||||
Some(bend) => Some(self.mesh.bend_weight(bend).cw),
|
||||
Some(bend) => Some(self.mesh.primitive(bend).weight().cw),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn dot_guidecircle(&self, dot: DotIndex, width: f64, conditions: Conditions) -> Circle {
|
||||
let circle = self.mesh.dot_weight(dot).circle;
|
||||
let circle = self.mesh.primitive(dot).weight().circle;
|
||||
Circle {
|
||||
pos: circle.pos,
|
||||
r: circle.r + width + self.rules.ruleset(conditions).clearance.min,
|
||||
|
|
@ -158,12 +162,12 @@ impl Layout {
|
|||
let mut r = width + self.rules.ruleset(conditions).clearance.min;
|
||||
let mut layer = bend;
|
||||
|
||||
while let Some(inner) = self.mesh.inner(layer) {
|
||||
r += 5.0 + self.mesh.primitive(inner.tag()).width();
|
||||
while let Some(inner) = self.mesh.primitive(layer).inner() {
|
||||
r += 5.0 + self.mesh.shape(inner.tag()).width();
|
||||
layer = inner;
|
||||
}
|
||||
|
||||
let core_circle = self.mesh.dot_weight(self.mesh.core(bend)).circle;
|
||||
let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core()).weight().circle;
|
||||
Circle {
|
||||
pos: core_circle.pos,
|
||||
r: core_circle.r + r + 15.0
|
||||
|
|
@ -184,11 +188,11 @@ impl Layout {
|
|||
|
||||
fn extend_head_bend(&mut self, head: Head, to: Point) -> Head {
|
||||
let bend = head.bend.unwrap();
|
||||
let dot_weight = self.mesh.dot_weight(head.dot);
|
||||
let bend_weight = self.mesh.bend_weight(bend);
|
||||
let around = self.mesh.around(bend);
|
||||
let dot_weight = self.mesh.primitive(head.dot).weight();
|
||||
let bend_weight = self.mesh.primitive(bend).weight();
|
||||
let around = self.mesh.primitive(bend).around();
|
||||
|
||||
let fixed_dot: DotIndex = self.mesh.ends(TaggedIndex::Bend(bend))
|
||||
let fixed_dot: DotIndex = self.mesh.primitive(bend).ends()
|
||||
.into_iter()
|
||||
.filter(|neighbor| {*neighbor != head.dot})
|
||||
.collect::<Vec<DotIndex>>()[0];
|
||||
|
|
@ -217,15 +221,11 @@ impl Layout {
|
|||
}
|
||||
|
||||
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, width: f64) -> SegIndex {
|
||||
let net = self.mesh.dot_weight(from).net;
|
||||
let net = self.mesh.primitive(from).weight().net;
|
||||
self.mesh.add_seg(from, to, SegWeight {net, width})
|
||||
}
|
||||
|
||||
pub fn primitives(&self) -> Box<dyn Iterator<Item=Primitive> + '_> {
|
||||
self.mesh.primitives()
|
||||
}
|
||||
|
||||
pub fn primitive(&self, index: TaggedIndex) -> Primitive {
|
||||
self.mesh.primitive(index)
|
||||
pub fn shapes(&self) -> Box<dyn Iterator<Item=Shape> + '_> {
|
||||
self.mesh.shapes()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
src/main.rs
27
src/main.rs
|
|
@ -4,6 +4,7 @@ mod layout;
|
|||
mod rules;
|
||||
mod mesh;
|
||||
mod primitive;
|
||||
mod shape;
|
||||
mod weight;
|
||||
mod math;
|
||||
|
||||
|
|
@ -17,8 +18,8 @@ use sdl2::keyboard::Keycode;
|
|||
use sdl2::gfx::primitives::DrawRenderer;
|
||||
|
||||
use crate::layout::Layout;
|
||||
use crate::primitive::Primitive;
|
||||
use crate::weight::{Weight, DotWeight};
|
||||
use crate::shape::Shape;
|
||||
use crate::weight::{TaggedWeight, DotWeight};
|
||||
use crate::math::Circle;
|
||||
|
||||
fn main() {
|
||||
|
|
@ -105,16 +106,16 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
for primitive in layout.primitives() {
|
||||
match primitive.weight {
|
||||
Weight::Dot(dot) => {
|
||||
for shape in layout.shapes() {
|
||||
match shape.weight {
|
||||
TaggedWeight::Dot(dot) => {
|
||||
let _ = canvas.filled_circle(dot.circle.pos.x() as i16,
|
||||
dot.circle.pos.y() as i16,
|
||||
dot.circle.r as i16,
|
||||
Color::RGB(200, 52, 52));
|
||||
},
|
||||
Weight::Seg(seg) => {
|
||||
let dot_neighbor_weights = primitive.dot_neighbor_weights;
|
||||
TaggedWeight::Seg(seg) => {
|
||||
let dot_neighbor_weights = shape.dot_neighbor_weights;
|
||||
let _ = canvas.thick_line(dot_neighbor_weights[0].circle.pos.x() as i16,
|
||||
dot_neighbor_weights[0].circle.pos.y() as i16,
|
||||
dot_neighbor_weights[1].circle.pos.x() as i16,
|
||||
|
|
@ -122,10 +123,10 @@ fn main() {
|
|||
seg.width as u8,
|
||||
Color::RGB(200, 52, 52));
|
||||
},
|
||||
Weight::Bend(bend) => {
|
||||
let circle = primitive.circle().unwrap();
|
||||
let dot_neighbor_weights = primitive.dot_neighbor_weights;
|
||||
//let around_circle = primitive.around_weight.unwrap().circle;
|
||||
TaggedWeight::Bend(bend) => {
|
||||
let circle = shape.circle().unwrap();
|
||||
let dot_neighbor_weights = shape.dot_neighbor_weights;
|
||||
//let around_circle = shape.around_weight.unwrap().circle;
|
||||
|
||||
let delta1 = dot_neighbor_weights[0].circle.pos - circle.pos;
|
||||
let delta2 = dot_neighbor_weights[1].circle.pos - circle.pos;
|
||||
|
|
@ -133,7 +134,7 @@ fn main() {
|
|||
let mut angle1 = delta1.y().atan2(delta1.x());
|
||||
let mut angle2 = delta2.y().atan2(delta2.x());
|
||||
|
||||
if primitive.weight.as_bend().unwrap().cw {
|
||||
if shape.weight.as_bend().unwrap().cw {
|
||||
swap(&mut angle1, &mut angle2);
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +144,7 @@ fn main() {
|
|||
//around_circle.pos.y() as i16,
|
||||
circle.pos.x() as i16,
|
||||
circle.pos.y() as i16,
|
||||
//(primitive.around_weight.unwrap().circle.r + 10.0 + (d as f64)) as i16,
|
||||
//(shape.around_weight.unwrap().circle.r + 10.0 + (d as f64)) as i16,
|
||||
(circle.r + (d as f64)) as i16,
|
||||
angle1.to_degrees() as i16,
|
||||
angle2.to_degrees() as i16,
|
||||
|
|
|
|||
144
src/mesh.rs
144
src/mesh.rs
|
|
@ -7,17 +7,18 @@ use rstar::{RTree, RTreeObject, AABB};
|
|||
use rstar::primitives::GeomWithData;
|
||||
|
||||
use crate::primitive::Primitive;
|
||||
use crate::weight::{Weight, DotWeight, SegWeight, BendWeight, Label};
|
||||
use crate::shape::Shape;
|
||||
use crate::weight::{TaggedWeight, DotWeight, SegWeight, BendWeight, Label};
|
||||
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Index<Ix, T> {
|
||||
index: Ix,
|
||||
pub struct Index<T> {
|
||||
pub index: NodeIndex<usize>,
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<Ix, T> Index<Ix, T> {
|
||||
pub fn new(index: Ix) -> Self {
|
||||
impl<T> Index<T> {
|
||||
pub fn new(index: NodeIndex<usize>) -> Self {
|
||||
Self {
|
||||
index,
|
||||
marker: PhantomData,
|
||||
|
|
@ -29,7 +30,7 @@ pub trait Tag {
|
|||
fn tag(&self) -> TaggedIndex;
|
||||
}
|
||||
|
||||
pub type DotIndex = Index<NodeIndex<usize>, DotWeight>;
|
||||
pub type DotIndex = Index<DotWeight>;
|
||||
|
||||
impl Tag for DotIndex {
|
||||
fn tag(&self) -> TaggedIndex {
|
||||
|
|
@ -37,7 +38,7 @@ impl Tag for DotIndex {
|
|||
}
|
||||
}
|
||||
|
||||
pub type SegIndex = Index<NodeIndex<usize>, SegWeight>;
|
||||
pub type SegIndex = Index<SegWeight>;
|
||||
|
||||
impl Tag for SegIndex {
|
||||
fn tag(&self) -> TaggedIndex {
|
||||
|
|
@ -45,7 +46,7 @@ impl Tag for SegIndex {
|
|||
}
|
||||
}
|
||||
|
||||
pub type BendIndex = Index<NodeIndex<usize>, BendWeight>;
|
||||
pub type BendIndex = Index<BendWeight>;
|
||||
|
||||
impl Tag for BendIndex {
|
||||
fn tag(&self) -> TaggedIndex {
|
||||
|
|
@ -60,11 +61,11 @@ pub enum TaggedIndex {
|
|||
Bend(BendIndex),
|
||||
}
|
||||
|
||||
pub type RTreeWrapper = GeomWithData<Primitive, TaggedIndex>;
|
||||
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
||||
|
||||
pub struct Mesh {
|
||||
pub rtree: RTree<RTreeWrapper>,
|
||||
pub graph: StableDiGraph<Weight, Label, usize>,
|
||||
pub graph: StableDiGraph<TaggedWeight, Label, usize>,
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
|
|
@ -76,30 +77,30 @@ impl Mesh {
|
|||
}
|
||||
|
||||
pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
|
||||
let dot = DotIndex::new(self.graph.add_node(Weight::Dot(weight)));
|
||||
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight)));
|
||||
let index = TaggedIndex::Dot(dot);
|
||||
self.rtree.insert(RTreeWrapper::new(self.primitive(index), index));
|
||||
self.rtree.insert(RTreeWrapper::new(self.shape(index), index));
|
||||
dot
|
||||
}
|
||||
|
||||
pub fn remove_dot(&mut self, dot: DotIndex) {
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(TaggedIndex::Dot(dot)), TaggedIndex::Dot(dot)));
|
||||
self.rtree.remove(&RTreeWrapper::new(self.shape(TaggedIndex::Dot(dot)), TaggedIndex::Dot(dot)));
|
||||
self.graph.remove_node(dot.index);
|
||||
}
|
||||
|
||||
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, weight: SegWeight) -> SegIndex {
|
||||
let seg = SegIndex::new(self.graph.add_node(Weight::Seg(weight)));
|
||||
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight)));
|
||||
self.graph.add_edge(seg.index, from.index, Label::End);
|
||||
self.graph.add_edge(seg.index, to.index, Label::End);
|
||||
|
||||
let index = TaggedIndex::Seg(seg);
|
||||
self.rtree.insert(RTreeWrapper::new(self.primitive(index), index));
|
||||
self.rtree.insert(RTreeWrapper::new(self.shape(index), index));
|
||||
seg
|
||||
|
||||
}
|
||||
|
||||
pub fn remove_seg(&mut self, seg: SegIndex) {
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(TaggedIndex::Seg(seg)), TaggedIndex::Seg(seg)));
|
||||
self.rtree.remove(&RTreeWrapper::new(self.shape(TaggedIndex::Seg(seg)), TaggedIndex::Seg(seg)));
|
||||
self.graph.remove_node(seg.index);
|
||||
}
|
||||
|
||||
|
|
@ -108,23 +109,23 @@ impl Mesh {
|
|||
TaggedIndex::Dot(core) =>
|
||||
self.add_core_bend(from, to, core, weight),
|
||||
TaggedIndex::Bend(around) =>
|
||||
self.add_noncore_bend(from, to, around, weight),
|
||||
self.add_outer_bend(from, to, around, weight),
|
||||
TaggedIndex::Seg(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_core_bend(&mut self, from: DotIndex, to: DotIndex, core: DotIndex, weight: BendWeight) -> BendIndex {
|
||||
let bend = BendIndex::new(self.graph.add_node(Weight::Bend(weight)));
|
||||
let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight)));
|
||||
self.graph.add_edge(bend.index, from.index, Label::End);
|
||||
self.graph.add_edge(bend.index, to.index, Label::End);
|
||||
self.graph.add_edge(bend.index, core.index, Label::Core);
|
||||
|
||||
let index = TaggedIndex::Bend(bend);
|
||||
self.rtree.insert(RTreeWrapper::new(self.primitive(index), index));
|
||||
self.rtree.insert(RTreeWrapper::new(self.shape(index), index));
|
||||
bend
|
||||
}
|
||||
|
||||
pub fn add_noncore_bend(&mut self, from: DotIndex, to: DotIndex, inner: BendIndex, weight: BendWeight) -> BendIndex {
|
||||
pub fn add_outer_bend(&mut self, from: DotIndex, to: DotIndex, inner: BendIndex, weight: BendWeight) -> BendIndex {
|
||||
let core = *self.graph.neighbors(inner.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(inner.index, *ni).unwrap()).unwrap().is_core())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
|
|
@ -137,93 +138,60 @@ impl Mesh {
|
|||
}
|
||||
|
||||
pub fn remove_bend(&mut self, bend: BendIndex) {
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(TaggedIndex::Bend(bend)), TaggedIndex::Bend(bend)));
|
||||
self.rtree.remove(&RTreeWrapper::new(self.shape(TaggedIndex::Bend(bend)), TaggedIndex::Bend(bend)));
|
||||
self.graph.remove_node(bend.index);
|
||||
}
|
||||
|
||||
pub fn primitives(&self) -> Box<dyn Iterator<Item=Primitive> + '_> {
|
||||
Box::new(self.rtree.iter().map(|wrapper| self.primitive(wrapper.data)))
|
||||
pub fn shapes(&self) -> Box<dyn Iterator<Item=Shape> + '_> {
|
||||
Box::new(self.rtree.iter().map(|wrapper| self.shape(wrapper.data)))
|
||||
}
|
||||
|
||||
pub fn primitive(&self, index: TaggedIndex) -> Primitive {
|
||||
Primitive {
|
||||
weight: self.weight(index),
|
||||
dot_neighbor_weights:
|
||||
self.ends(index)
|
||||
.into_iter()
|
||||
.map(|index| self.dot_weight(index))
|
||||
.collect(),
|
||||
pub fn shape(&self, index: TaggedIndex) -> Shape {
|
||||
Shape {
|
||||
weight: match index {
|
||||
TaggedIndex::Dot(index) => self.primitive(index).tagged_weight(),
|
||||
TaggedIndex::Seg(index) => self.primitive(index).tagged_weight(),
|
||||
TaggedIndex::Bend(index) => self.primitive(index).tagged_weight(),
|
||||
},
|
||||
dot_neighbor_weights: match index {
|
||||
TaggedIndex::Dot(index) => {
|
||||
self.primitive(index).ends()
|
||||
.into_iter()
|
||||
.map(|index| self.primitive(index).weight())
|
||||
.collect()
|
||||
},
|
||||
TaggedIndex::Seg(index) => {
|
||||
self.primitive(index).ends()
|
||||
.into_iter()
|
||||
.map(|index| self.primitive(index).weight())
|
||||
.collect()
|
||||
},
|
||||
TaggedIndex::Bend(index) => {
|
||||
self.primitive(index).ends()
|
||||
.into_iter()
|
||||
.map(|index| self.primitive(index).weight())
|
||||
.collect()
|
||||
},
|
||||
},
|
||||
core_pos: match index {
|
||||
TaggedIndex::Bend(bend) => {
|
||||
Some(self.dot_weight(self.core(bend)).circle.pos)
|
||||
Some(self.primitive(self.primitive(bend).core()).weight().circle.pos)
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn around(&self, bend: BendIndex) -> TaggedIndex {
|
||||
if let Some(inner) = self.inner(bend) {
|
||||
TaggedIndex::Bend(inner)
|
||||
} else {
|
||||
TaggedIndex::Dot(self.core(bend))
|
||||
}
|
||||
pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> {
|
||||
Primitive::new(index, &self.graph)
|
||||
}
|
||||
|
||||
pub fn core(&self, bend: BendIndex) -> DotIndex {
|
||||
self.graph.neighbors(bend.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(bend.index, *ni).unwrap()).unwrap().is_core())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.next()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn inner(&self, bend: BendIndex) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(bend.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, bend.index).unwrap()).unwrap().is_outer())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn outer(&self, bend: BendIndex) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(bend.index, Outgoing)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(bend.index, *ni).unwrap()).unwrap().is_outer())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn ends(&self, index: TaggedIndex) -> Vec<DotIndex> {
|
||||
match index {
|
||||
TaggedIndex::Dot(DotIndex {index: node, ..})
|
||||
| TaggedIndex::Seg(SegIndex {index: node, ..})
|
||||
| TaggedIndex::Bend(BendIndex {index: node, ..}) => {
|
||||
self.graph.neighbors(node)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(node, *ni).unwrap()).unwrap().is_end())
|
||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_dot())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dot_weight(&self, dot: DotIndex) -> DotWeight {
|
||||
*self.weight(dot.tag()).as_dot().unwrap()
|
||||
}
|
||||
|
||||
pub fn seg_weight(&self, seg: SegIndex) -> SegWeight {
|
||||
*self.weight(seg.tag()).as_seg().unwrap()
|
||||
}
|
||||
|
||||
pub fn bend_weight(&self, bend: BendIndex) -> BendWeight {
|
||||
*self.weight(bend.tag()).as_bend().unwrap()
|
||||
}
|
||||
|
||||
pub fn weight(&self, index: TaggedIndex) -> Weight {
|
||||
/*pub fn tagged_weight(&self, index: TaggedIndex) -> Weight {
|
||||
match index {
|
||||
TaggedIndex::Dot(DotIndex {index: node, ..})
|
||||
| TaggedIndex::Seg(SegIndex {index: node, ..})
|
||||
| TaggedIndex::Bend(BendIndex {index: node, ..}) =>
|
||||
*self.graph.node_weight(node).unwrap(),
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
|||
118
src/primitive.rs
118
src/primitive.rs
|
|
@ -1,65 +1,79 @@
|
|||
use geo::{Point, EuclideanDistance};
|
||||
use rstar::{RTreeObject, AABB};
|
||||
use petgraph::Direction::{Outgoing, Incoming};
|
||||
use petgraph::stable_graph::StableDiGraph;
|
||||
|
||||
use crate::{weight::{Weight, DotWeight}, math::Circle};
|
||||
use crate::{mesh::{DotIndex, SegIndex, BendIndex, TaggedIndex, Mesh, Tag, Index}, weight::{DotWeight, SegWeight, BendWeight, TaggedWeight, Label}};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct Primitive {
|
||||
pub weight: Weight,
|
||||
pub dot_neighbor_weights: Vec<DotWeight>,
|
||||
pub core_pos: Option<Point>,
|
||||
pub struct Primitive<'a, Weight> {
|
||||
index: Index<Weight>,
|
||||
graph: &'a StableDiGraph<TaggedWeight, Label, usize>,
|
||||
}
|
||||
|
||||
impl Primitive {
|
||||
pub fn envelope(&self) -> AABB<[f64; 2]> {
|
||||
match self.weight {
|
||||
Weight::Dot(dot) => {
|
||||
return AABB::from_corners(
|
||||
[dot.circle.pos.x() - dot.circle.r, dot.circle.pos.y() - dot.circle.r],
|
||||
[dot.circle.pos.x() + dot.circle.r, dot.circle.pos.y() + dot.circle.r]
|
||||
);
|
||||
},
|
||||
Weight::Seg(..) | Weight::Bend(..) => {
|
||||
// TODO: Take widths into account.
|
||||
|
||||
let points: Vec<[f64; 2]> = self.dot_neighbor_weights.iter()
|
||||
.map(|neighbor| [neighbor.circle.pos.x(), neighbor.circle.pos.y()])
|
||||
.collect();
|
||||
return AABB::<[f64; 2]>::from_points(&points);
|
||||
},
|
||||
}
|
||||
impl<'a, Weight> Primitive<'a, Weight> {
|
||||
pub fn new(index: Index<Weight>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Primitive<Weight> {
|
||||
Primitive::<Weight> {index, graph}
|
||||
}
|
||||
|
||||
pub fn circle(&self) -> Option<Circle> {
|
||||
match self.weight {
|
||||
Weight::Dot(dot) => Some(dot.circle),
|
||||
Weight::Seg(seg) => None,
|
||||
Weight::Bend(bend) => {
|
||||
let r = self.dot_neighbor_weights[0].circle.pos.euclidean_distance(&self.core_pos.unwrap());
|
||||
Some(Circle {
|
||||
pos: self.core_pos.unwrap(),
|
||||
r,
|
||||
})
|
||||
}
|
||||
}
|
||||
pub fn ends(&self) -> Vec<DotIndex> {
|
||||
self.graph.neighbors(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_end())
|
||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_dot())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn width(&self) -> f64 {
|
||||
match self.weight {
|
||||
Weight::Dot(dot) => dot.circle.r * 2.0,
|
||||
Weight::Seg(seg) => seg.width,
|
||||
Weight::Bend(bend) => self.dot_neighbor_weights[0].circle.r * 2.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn weight(&self) -> Weight {
|
||||
return self.weight;
|
||||
pub fn tagged_weight(&self) -> TaggedWeight {
|
||||
*self.graph.node_weight(self.index.index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl RTreeObject for Primitive {
|
||||
type Envelope = AABB<[f64; 2]>;
|
||||
fn envelope(&self) -> Self::Envelope {
|
||||
return self.envelope();
|
||||
type Dot<'a> = Primitive<'a, DotWeight>;
|
||||
type Seg<'a> = Primitive<'a, SegWeight>;
|
||||
type Bend<'a> = Primitive<'a, BendWeight>;
|
||||
|
||||
impl<'a> Dot<'a> {
|
||||
pub fn weight(&self) -> DotWeight {
|
||||
*self.tagged_weight().as_dot().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Seg<'a> {
|
||||
pub fn weight(&self) -> SegWeight {
|
||||
*self.tagged_weight().as_seg().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Bend<'a> {
|
||||
pub fn around(&self) -> TaggedIndex {
|
||||
if let Some(inner) = self.inner() {
|
||||
TaggedIndex::Bend(inner)
|
||||
} else {
|
||||
TaggedIndex::Dot(self.core())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn core(&self) -> DotIndex {
|
||||
self.graph.neighbors(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.next()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_outer())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn outer(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Outgoing)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_outer())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn weight(&self) -> BendWeight {
|
||||
*self.tagged_weight().as_bend().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
use geo::{Point, EuclideanDistance};
|
||||
use rstar::{RTreeObject, AABB};
|
||||
|
||||
use crate::{weight::{TaggedWeight, DotWeight}, math::Circle};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct Shape {
|
||||
pub weight: TaggedWeight,
|
||||
pub dot_neighbor_weights: Vec<DotWeight>,
|
||||
pub core_pos: Option<Point>,
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
pub fn envelope(&self) -> AABB<[f64; 2]> {
|
||||
match self.weight {
|
||||
TaggedWeight::Dot(dot) => {
|
||||
return AABB::from_corners(
|
||||
[dot.circle.pos.x() - dot.circle.r, dot.circle.pos.y() - dot.circle.r],
|
||||
[dot.circle.pos.x() + dot.circle.r, dot.circle.pos.y() + dot.circle.r]
|
||||
);
|
||||
},
|
||||
TaggedWeight::Seg(..) | TaggedWeight::Bend(..) => {
|
||||
// TODO: Take widths into account.
|
||||
|
||||
let points: Vec<[f64; 2]> = self.dot_neighbor_weights.iter()
|
||||
.map(|neighbor| [neighbor.circle.pos.x(), neighbor.circle.pos.y()])
|
||||
.collect();
|
||||
return AABB::<[f64; 2]>::from_points(&points);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn circle(&self) -> Option<Circle> {
|
||||
match self.weight {
|
||||
TaggedWeight::Dot(dot) => Some(dot.circle),
|
||||
TaggedWeight::Seg(seg) => None,
|
||||
TaggedWeight::Bend(bend) => {
|
||||
let r = self.dot_neighbor_weights[0].circle.pos.euclidean_distance(&self.core_pos.unwrap());
|
||||
Some(Circle {
|
||||
pos: self.core_pos.unwrap(),
|
||||
r,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(&self) -> f64 {
|
||||
match self.weight {
|
||||
TaggedWeight::Dot(dot) => dot.circle.r * 2.0,
|
||||
TaggedWeight::Seg(seg) => seg.width,
|
||||
TaggedWeight::Bend(bend) => self.dot_neighbor_weights[0].circle.r * 2.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn weight(&self) -> TaggedWeight {
|
||||
return self.weight;
|
||||
}
|
||||
}
|
||||
|
||||
impl RTreeObject for Shape {
|
||||
type Envelope = AABB<[f64; 2]>;
|
||||
fn envelope(&self) -> Self::Envelope {
|
||||
return self.envelope();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ pub struct SegWeight {
|
|||
}
|
||||
|
||||
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
|
||||
pub enum Weight {
|
||||
pub enum TaggedWeight {
|
||||
Dot(DotWeight),
|
||||
Seg(SegWeight),
|
||||
Bend(BendWeight),
|
||||
|
|
|
|||
Loading…
Reference in New Issue