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() {
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

View File

@ -107,37 +107,14 @@ 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) => {
if let Some(center) = shape.center {
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;
let delta1 = shape.from - circle.pos;
let delta2 = shape.to - circle.pos;
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,
@ -150,8 +127,18 @@ fn main() {
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));
}
}

View File

@ -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<Item=TaggedIndex> + '_ {
self.rtree.iter().map(|wrapper| wrapper.data)
}
@ -155,4 +164,8 @@ impl Mesh {
pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> {
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::stable_graph::StableDiGraph;
@ -14,6 +16,54 @@ impl<'a, Weight> Primitive<'a, Weight> {
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 {
*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<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 {
*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<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 {
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<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())

View File

@ -5,58 +5,43 @@ 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>,
pub width: f64,
pub from: Point,
pub to: Point,
pub center: 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.
pub fn new(width: f64, from: Point, to: Point, center: Option<Point>) -> 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<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());
if let Some(center) = self.center {
let r = self.from.euclidean_distance(&center);
Some(Circle {
pos: self.core_pos.unwrap(),
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 {
type Envelope = AABB<[f64; 2]>;
fn envelope(&self) -> Self::Envelope {