Store width and points instead of weights in `Shape`

This commit is contained in:
Mikolaj Wielgus 2023-07-22 03:48:56 +02:00
parent dea65a3b43
commit f1772ca0be
5 changed files with 123 additions and 144 deletions

View File

@ -128,7 +128,7 @@ impl Layout {
if let Some(inner) = self.mesh.primitive(bend).inner() { if let Some(inner) = self.mesh.primitive(bend).inner() {
self.bend_guidecircle(inner, width, conditions) self.bend_guidecircle(inner, width, conditions)
} else { } 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 { None => Circle {
@ -158,11 +158,11 @@ impl Layout {
let mut layer = bend; let mut layer = bend;
while let Some(inner) = self.mesh.primitive(layer).inner() { 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; 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 { Circle {
pos: core_circle.pos, pos: core_circle.pos,
r: core_circle.r + r + 15.0 r: core_circle.r + r + 15.0

View File

@ -107,51 +107,38 @@ fn main() {
} }
for shape in layout.shapes() { for shape in layout.shapes() {
match shape.weight { if let Some(center) = shape.center {
TaggedWeight::Dot(dot) => { let circle = shape.circle().unwrap();
let _ = canvas.filled_circle(dot.circle.pos.x() as i16, let delta1 = shape.from - circle.pos;
dot.circle.pos.y() as i16, let delta2 = shape.to - circle.pos;
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;
let delta1 = dot_neighbor_weights[0].circle.pos - circle.pos; let mut angle1 = delta1.y().atan2(delta1.x());
let delta2 = dot_neighbor_weights[1].circle.pos - circle.pos; let mut angle2 = delta2.y().atan2(delta2.x());
let mut angle1 = delta1.y().atan2(delta1.x()); for d in -3..3 {
let mut angle2 = delta2.y().atan2(delta2.x()); let _ = canvas.arc(
//around_circle.pos.x() as i16,
if shape.weight.as_bend().unwrap().cw { //around_circle.pos.y() as i16,
swap(&mut angle1, &mut angle2); circle.pos.x() as i16,
} circle.pos.y() as i16,
//(shape.around_weight.unwrap().circle.r + 10.0 + (d as f64)) as i16,
for d in -3..3 { (circle.r + (d as f64)) as i16,
let _ = canvas.arc( angle1.to_degrees() as i16,
//around_circle.pos.x() as i16, angle2.to_degrees() as i16,
//around_circle.pos.y() as i16, Color::RGB(200, 52, 52));
circle.pos.x() as i16, }
circle.pos.y() as i16, } else if shape.from != shape.to {
//(shape.around_weight.unwrap().circle.r + 10.0 + (d as f64)) as i16, let _ = canvas.thick_line(shape.from.x() as i16,
(circle.r + (d as f64)) as i16, shape.from.y() as i16,
angle1.to_degrees() as i16, shape.to.x() as i16,
angle2.to_degrees() as i16, shape.to.y() as i16,
Color::RGB(200, 52, 52)); 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));
} }
} }

View File

@ -1,5 +1,6 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use enum_as_inner::EnumAsInner; use enum_as_inner::EnumAsInner;
use geo::Point;
use petgraph::Direction::{Outgoing, Incoming}; use petgraph::Direction::{Outgoing, Incoming};
use petgraph::stable_graph::{StableDiGraph, NodeIndex, EdgeIndex}; use petgraph::stable_graph::{StableDiGraph, NodeIndex, EdgeIndex};
use petgraph::visit::EdgeRef; use petgraph::visit::EdgeRef;
@ -80,7 +81,7 @@ pub struct Mesh {
impl Mesh { impl Mesh {
pub fn new() -> Self { pub fn new() -> Self {
return Mesh { Mesh {
rtree: RTree::new(), rtree: RTree::new(),
graph: StableDiGraph::default(), graph: StableDiGraph::default(),
} }
@ -148,6 +149,14 @@ impl Mesh {
self.graph.remove_node(bend.index); 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<Item=TaggedIndex> + '_ { pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ {
self.rtree.iter().map(|wrapper| wrapper.data) self.rtree.iter().map(|wrapper| wrapper.data)
} }
@ -155,4 +164,8 @@ impl Mesh {
pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> { pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> {
Primitive::new(index, &self.graph) Primitive::new(index, &self.graph)
} }
/*fn insert_into_rtree<Weight>(&mut self, index: Index<Weight>) {
self.rtree.insert(RTreeWrapper::new(self.primitive(index).shape(), index.tag()));
}*/
} }

View File

@ -1,3 +1,5 @@
use std::mem::swap;
use petgraph::Direction::{Outgoing, Incoming}; use petgraph::Direction::{Outgoing, Incoming};
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
@ -14,6 +16,54 @@ impl<'a, Weight> Primitive<'a, Weight> {
Primitive::<Weight> {index, graph} Primitive::<Weight> {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<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 core(&self) -> Option<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()
}
pub fn tagged_weight(&self) -> TaggedWeight { pub fn tagged_weight(&self) -> TaggedWeight {
*self.graph.node_weight(self.index.index).unwrap() *self.graph.node_weight(self.index.index).unwrap()
} }
@ -28,82 +78,26 @@ type Seg<'a> = Primitive<'a, SegWeight>;
type Bend<'a> = Primitive<'a, BendWeight>; type Bend<'a> = Primitive<'a, BendWeight>;
impl<'a> Dot<'a> { 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 { pub fn weight(&self) -> DotWeight {
*self.tagged_weight().as_dot().unwrap() *self.tagged_weight().as_dot().unwrap()
} }
} }
impl<'a> Seg<'a> { 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<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 weight(&self) -> SegWeight { pub fn weight(&self) -> SegWeight {
*self.tagged_weight().as_seg().unwrap() *self.tagged_weight().as_seg().unwrap()
} }
} }
impl<'a> Bend<'a> { 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<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 around(&self) -> TaggedIndex { pub fn around(&self) -> TaggedIndex {
if let Some(inner) = self.inner() { if let Some(inner) = self.inner() {
TaggedIndex::Bend(inner) TaggedIndex::Bend(inner)
} else { } 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<BendIndex> { pub fn inner(&self) -> Option<BendIndex> {
self.graph.neighbors_directed(self.index.index, Incoming) 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()) .filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_outer())

View File

@ -5,56 +5,41 @@ use crate::{weight::{TaggedWeight, DotWeight}, math::Circle};
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct Shape { pub struct Shape {
pub weight: TaggedWeight, pub width: f64,
pub dot_neighbor_weights: Vec<DotWeight>, pub from: Point,
pub core_pos: Option<Point>, pub to: Point,
pub center: Option<Point>,
} }
impl Shape { impl Shape {
pub fn envelope(&self) -> AABB<[f64; 2]> { pub fn new(width: f64, from: Point, to: Point, center: Option<Point>) -> Self {
match self.weight { Shape {width, from, to, center}
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() pub fn envelope(&self) -> AABB<[f64; 2]> {
.map(|neighbor| [neighbor.circle.pos.x(), neighbor.circle.pos.y()]) if self.from == self.to {
.collect(); AABB::from_corners(
return AABB::<[f64; 2]>::from_points(&points); [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<Circle> { pub fn circle(&self) -> Option<Circle> {
match self.weight { if let Some(center) = self.center {
TaggedWeight::Dot(dot) => Some(dot.circle), let r = self.from.euclidean_distance(&center);
TaggedWeight::Seg(seg) => None, Some(Circle {
TaggedWeight::Bend(bend) => { pos: center,
let r = self.dot_neighbor_weights[0].circle.pos.euclidean_distance(&self.core_pos.unwrap()); r,
Some(Circle { })
pos: self.core_pos.unwrap(), } else {
r, 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 { impl RTreeObject for Shape {