diff --git a/src/layout.rs b/src/layout.rs index 9d780bf..6366a8e 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -128,7 +128,7 @@ impl Layout { if let Some(inner) = self.mesh.primitive(bend).inner() { self.bend_guidecircle(inner, width, conditions) } else { - self.dot_guidecircle(self.mesh.primitive(bend).core(), width + 5.0, conditions) + self.dot_guidecircle(self.mesh.primitive(bend).core().unwrap(), width + 5.0, conditions) } }, None => Circle { @@ -158,11 +158,11 @@ impl Layout { let mut layer = bend; while let Some(inner) = self.mesh.primitive(layer).inner() { - r += 5.0 + self.mesh.primitive(inner).shape().width(); + r += 5.0 + self.mesh.primitive(inner).shape().width; layer = inner; } - let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core()).weight().circle; + let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).weight().circle; Circle { pos: core_circle.pos, r: core_circle.r + r + 15.0 diff --git a/src/main.rs b/src/main.rs index 124be40..ff3d746 100644 --- a/src/main.rs +++ b/src/main.rs @@ -107,51 +107,38 @@ fn main() { } 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)); - }, - 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, - dot_neighbor_weights[1].circle.pos.y() as i16, - seg.width as u8, - Color::RGB(200, 52, 52)); - }, - TaggedWeight::Bend(bend) => { - let circle = shape.circle().unwrap(); - let dot_neighbor_weights = shape.dot_neighbor_weights; - //let around_circle = shape.around_weight.unwrap().circle; + if let Some(center) = shape.center { + let circle = shape.circle().unwrap(); + let delta1 = shape.from - circle.pos; + let delta2 = shape.to - circle.pos; - let delta1 = dot_neighbor_weights[0].circle.pos - circle.pos; - let delta2 = dot_neighbor_weights[1].circle.pos - circle.pos; + let mut angle1 = delta1.y().atan2(delta1.x()); + let mut angle2 = delta2.y().atan2(delta2.x()); - let mut angle1 = delta1.y().atan2(delta1.x()); - let mut angle2 = delta2.y().atan2(delta2.x()); - - if shape.weight.as_bend().unwrap().cw { - swap(&mut angle1, &mut angle2); - } - - for d in -3..3 { - let _ = canvas.arc( - //around_circle.pos.x() as i16, - //around_circle.pos.y() as i16, - circle.pos.x() as i16, - circle.pos.y() 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, - Color::RGB(200, 52, 52)); - } - - }, + for d in -3..3 { + let _ = canvas.arc( + //around_circle.pos.x() as i16, + //around_circle.pos.y() as i16, + circle.pos.x() as i16, + circle.pos.y() 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, + Color::RGB(200, 52, 52)); + } + } else if shape.from != shape.to { + let _ = canvas.thick_line(shape.from.x() as i16, + shape.from.y() as i16, + shape.to.x() as i16, + shape.to.y() as i16, + shape.width as u8, + Color::RGB(200, 52, 52)); + } else { + let _ = canvas.filled_circle(shape.from.x() as i16, + shape.from.y() as i16, + (shape.width / 2.0) as i16, + Color::RGB(200, 52, 52)); } } diff --git a/src/mesh.rs b/src/mesh.rs index 3d559b2..9e5dea2 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,5 +1,6 @@ use std::marker::PhantomData; use enum_as_inner::EnumAsInner; +use geo::Point; use petgraph::Direction::{Outgoing, Incoming}; use petgraph::stable_graph::{StableDiGraph, NodeIndex, EdgeIndex}; use petgraph::visit::EdgeRef; @@ -80,7 +81,7 @@ pub struct Mesh { impl Mesh { pub fn new() -> Self { - return Mesh { + Mesh { rtree: RTree::new(), graph: StableDiGraph::default(), } @@ -148,6 +149,14 @@ impl Mesh { self.graph.remove_node(bend.index); } + /*pub fn extend_bend(&mut self, bend: BendIndex, to: Point) -> DotIndex { + + } + + pub fn shift_bend(&mut self, bend: BendIndex, offset: f64) { + + }*/ + pub fn nodes(&self) -> impl Iterator + '_ { self.rtree.iter().map(|wrapper| wrapper.data) } @@ -155,4 +164,8 @@ impl Mesh { pub fn primitive(&self, index: Index) -> Primitive { Primitive::new(index, &self.graph) } + + /*fn insert_into_rtree(&mut self, index: Index) { + self.rtree.insert(RTreeWrapper::new(self.primitive(index).shape(), index.tag())); + }*/ } diff --git a/src/primitive.rs b/src/primitive.rs index 1267585..cbe1e86 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -1,3 +1,5 @@ +use std::mem::swap; + use petgraph::Direction::{Outgoing, Incoming}; use petgraph::stable_graph::StableDiGraph; @@ -14,6 +16,54 @@ impl<'a, Weight> Primitive<'a, Weight> { Primitive:: {index, graph} } + pub fn shape(&self) -> Shape { + let ends = self.ends(); + match self.tagged_weight() { + TaggedWeight::Dot(dot) => Shape { + width: dot.circle.r * 2.0, + from: dot.circle.pos, + to: dot.circle.pos, + center: None, + }, + TaggedWeight::Seg(seg) => { + Shape { + width: seg.width, + from: self.primitive(ends[0]).weight().circle.pos, + to: self.primitive(ends[1]).weight().circle.pos, + center: None, + } + } + TaggedWeight::Bend(bend) => { + let mut shape = Shape { + width: self.primitive(ends[0]).weight().circle.r * 2.0, + from: self.primitive(ends[0]).weight().circle.pos, + to: self.primitive(ends[1]).weight().circle.pos, + center: Some(self.primitive(self.core().unwrap()).weight().circle.pos), + }; + + if bend.cw { + swap(&mut shape.from, &mut shape.to); + } + shape + } + } + } + + 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 core(&self) -> Option { + 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() + } + pub fn tagged_weight(&self) -> TaggedWeight { *self.graph.node_weight(self.index.index).unwrap() } @@ -28,82 +78,26 @@ type Seg<'a> = Primitive<'a, SegWeight>; type Bend<'a> = Primitive<'a, BendWeight>; impl<'a> Dot<'a> { - pub fn shape(&self) -> Shape { - Shape { - weight: self.tagged_weight(), - dot_neighbor_weights: vec![], - core_pos: None, - } - } - pub fn weight(&self) -> DotWeight { *self.tagged_weight().as_dot().unwrap() } } impl<'a> Seg<'a> { - pub fn shape(&self) -> Shape { - Shape { - weight: self.tagged_weight(), - dot_neighbor_weights: - self.ends() - .into_iter() - .map(|index| self.primitive(index).weight()) - .collect(), - core_pos: None, - } - } - - 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 weight(&self) -> SegWeight { *self.tagged_weight().as_seg().unwrap() } } impl<'a> Bend<'a> { - pub fn shape(&self) -> Shape { - Shape { - weight: self.tagged_weight(), - dot_neighbor_weights: - self.ends() - .into_iter() - .map(|index| self.primitive(index).weight()) - .collect(), - core_pos: Some(self.primitive(self.core()).weight().circle.pos), - } - } - - 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 around(&self) -> TaggedIndex { if let Some(inner) = self.inner() { TaggedIndex::Bend(inner) } else { - TaggedIndex::Dot(self.core()) + TaggedIndex::Dot(self.core().unwrap()) } } - 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()) diff --git a/src/shape.rs b/src/shape.rs index 791645a..5ab0ce5 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -5,56 +5,41 @@ use crate::{weight::{TaggedWeight, DotWeight}, math::Circle}; #[derive(PartialEq)] pub struct Shape { - pub weight: TaggedWeight, - pub dot_neighbor_weights: Vec, - pub core_pos: Option, + pub width: f64, + pub from: Point, + pub to: Point, + pub center: 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. + pub fn new(width: f64, from: Point, to: Point, center: Option) -> Self { + Shape {width, from, to, center} + } - 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 envelope(&self) -> AABB<[f64; 2]> { + if self.from == self.to { + AABB::from_corners( + [self.from.x() - self.width, self.from.y() - self.width], + [self.from.x() + self.width, self.from.y() + self.width] + ) + } else { + // TODO: Take widths into account. + AABB::<[f64; 2]>::from_points(&[[self.from.x(), self.from.y()], + [self.to.x(), self.to.y()]]) } } 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, - }) - } + if let Some(center) = self.center { + let r = self.from.euclidean_distance(¢er); + Some(Circle { + pos: center, + r, + }) + } else { + None } } - - 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 {