diff --git a/src/layout.rs b/src/layout.rs index 0106604..1becf9c 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -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 { 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::>()[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 + '_> { - self.mesh.primitives() - } - - pub fn primitive(&self, index: TaggedIndex) -> Primitive { - self.mesh.primitive(index) + pub fn shapes(&self) -> Box + '_> { + self.mesh.shapes() } } diff --git a/src/main.rs b/src/main.rs index f6f0f69..a1b6991 100644 --- a/src/main.rs +++ b/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, diff --git a/src/mesh.rs b/src/mesh.rs index fddf9c3..c172d16 100644 --- a/src/mesh.rs +++ b/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 { - index: Ix, +pub struct Index { + pub index: NodeIndex, marker: PhantomData, } -impl Index { - pub fn new(index: Ix) -> Self { +impl Index { + pub fn new(index: NodeIndex) -> Self { Self { index, marker: PhantomData, @@ -29,7 +30,7 @@ pub trait Tag { fn tag(&self) -> TaggedIndex; } -pub type DotIndex = Index, DotWeight>; +pub type DotIndex = Index; impl Tag for DotIndex { fn tag(&self) -> TaggedIndex { @@ -37,7 +38,7 @@ impl Tag for DotIndex { } } -pub type SegIndex = Index, SegWeight>; +pub type SegIndex = Index; impl Tag for SegIndex { fn tag(&self) -> TaggedIndex { @@ -45,7 +46,7 @@ impl Tag for SegIndex { } } -pub type BendIndex = Index, BendWeight>; +pub type BendIndex = Index; impl Tag for BendIndex { fn tag(&self) -> TaggedIndex { @@ -60,11 +61,11 @@ pub enum TaggedIndex { Bend(BendIndex), } -pub type RTreeWrapper = GeomWithData; +pub type RTreeWrapper = GeomWithData; pub struct Mesh { pub rtree: RTree, - pub graph: StableDiGraph, + pub graph: StableDiGraph, } 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 + '_> { - Box::new(self.rtree.iter().map(|wrapper| self.primitive(wrapper.data))) + pub fn shapes(&self) -> Box + '_> { + 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(&self, index: Index) -> Primitive { + 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 { - 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 { - 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 { - 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(), } - } + }*/ } diff --git a/src/primitive.rs b/src/primitive.rs index 8ca7486..a699179 100644 --- a/src/primitive.rs +++ b/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, - pub core_pos: Option, +pub struct Primitive<'a, Weight> { + index: Index, + graph: &'a StableDiGraph, } -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, graph: &'a StableDiGraph) -> Primitive { + Primitive:: {index, graph} } - pub fn circle(&self) -> Option { - 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 { + 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 { + 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 { + 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() } } diff --git a/src/shape.rs b/src/shape.rs new file mode 100644 index 0000000..791645a --- /dev/null +++ b/src/shape.rs @@ -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, + pub core_pos: Option, +} + +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 { + 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(); + } +} diff --git a/src/weight.rs b/src/weight.rs index 414470c..4f99816 100644 --- a/src/weight.rs +++ b/src/weight.rs @@ -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),