mirror of https://codeberg.org/topola/topola.git
Implement basic failure for moving dot to obstructed place
Intersection with bends isn't working yet.
This commit is contained in:
parent
c2a553c475
commit
1a599951cd
|
|
@ -1,7 +1,7 @@
|
||||||
use petgraph::stable_graph::StableDiGraph;
|
use petgraph::stable_graph::StableDiGraph;
|
||||||
|
|
||||||
use crate::primitive::{Dot, Seg, Bend};
|
use crate::graph::{BendIndex, DotIndex, Label, Path, SegIndex, TaggedIndex, TaggedWeight};
|
||||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, TaggedWeight, Label, Path};
|
use crate::primitive::{Bend, Dot, Seg};
|
||||||
|
|
||||||
pub struct Bow<'a> {
|
pub struct Bow<'a> {
|
||||||
seg1_dot1: DotIndex,
|
seg1_dot1: DotIndex,
|
||||||
|
|
@ -43,11 +43,9 @@ impl<'a> Path for Bow<'a> {
|
||||||
fn interior(&self) -> Vec<TaggedIndex> {
|
fn interior(&self) -> Vec<TaggedIndex> {
|
||||||
vec![
|
vec![
|
||||||
TaggedIndex::Seg(self.seg1),
|
TaggedIndex::Seg(self.seg1),
|
||||||
|
|
||||||
TaggedIndex::Dot(self.seg1_dot2),
|
TaggedIndex::Dot(self.seg1_dot2),
|
||||||
TaggedIndex::Bend(self.bend),
|
TaggedIndex::Bend(self.bend),
|
||||||
TaggedIndex::Dot(self.seg2_dot1),
|
TaggedIndex::Dot(self.seg2_dot1),
|
||||||
|
|
||||||
TaggedIndex::Seg(self.seg2),
|
TaggedIndex::Seg(self.seg2),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -56,11 +54,9 @@ impl<'a> Path for Bow<'a> {
|
||||||
vec![
|
vec![
|
||||||
TaggedIndex::Dot(self.seg1_dot1),
|
TaggedIndex::Dot(self.seg1_dot1),
|
||||||
TaggedIndex::Seg(self.seg1),
|
TaggedIndex::Seg(self.seg1),
|
||||||
|
|
||||||
TaggedIndex::Dot(self.seg1_dot2),
|
TaggedIndex::Dot(self.seg1_dot2),
|
||||||
TaggedIndex::Bend(self.bend),
|
TaggedIndex::Bend(self.bend),
|
||||||
TaggedIndex::Dot(self.seg2_dot1),
|
TaggedIndex::Dot(self.seg2_dot1),
|
||||||
|
|
||||||
TaggedIndex::Seg(self.seg2),
|
TaggedIndex::Seg(self.seg2),
|
||||||
TaggedIndex::Dot(self.seg2_dot2),
|
TaggedIndex::Dot(self.seg2_dot2),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
26
src/graph.rs
26
src/graph.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use std::marker::PhantomData;
|
|
||||||
use enum_as_inner::EnumAsInner;
|
use enum_as_inner::EnumAsInner;
|
||||||
use petgraph::stable_graph::NodeIndex;
|
use petgraph::stable_graph::NodeIndex;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::math::Circle;
|
use crate::math::Circle;
|
||||||
|
|
||||||
|
|
@ -42,14 +42,14 @@ pub enum Label {
|
||||||
Core,
|
Core,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, EnumAsInner, Copy, Clone, PartialEq)]
|
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
|
||||||
pub enum TaggedIndex {
|
pub enum TaggedIndex {
|
||||||
Dot(DotIndex),
|
Dot(DotIndex),
|
||||||
Seg(SegIndex),
|
Seg(SegIndex),
|
||||||
Bend(BendIndex),
|
Bend(BendIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Index<T> {
|
pub struct Index<T> {
|
||||||
pub index: NodeIndex<usize>,
|
pub index: NodeIndex<usize>,
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
|
|
@ -65,12 +65,18 @@ impl<T> Index<T> {
|
||||||
|
|
||||||
pub fn retag(&self, weight: TaggedWeight) -> TaggedIndex {
|
pub fn retag(&self, weight: TaggedWeight) -> TaggedIndex {
|
||||||
match weight {
|
match weight {
|
||||||
TaggedWeight::Dot(..) =>
|
TaggedWeight::Dot(..) => TaggedIndex::Dot(DotIndex {
|
||||||
TaggedIndex::Dot(DotIndex {index: self.index, marker: PhantomData}),
|
index: self.index,
|
||||||
TaggedWeight::Seg(..) =>
|
marker: PhantomData,
|
||||||
TaggedIndex::Seg(SegIndex {index: self.index, marker: PhantomData}),
|
}),
|
||||||
TaggedWeight::Bend(..) =>
|
TaggedWeight::Seg(..) => TaggedIndex::Seg(SegIndex {
|
||||||
TaggedIndex::Bend(BendIndex {index: self.index, marker: PhantomData}),
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
|
}),
|
||||||
|
TaggedWeight::Bend(..) => TaggedIndex::Bend(BendIndex {
|
||||||
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +92,7 @@ macro_rules! untag {
|
||||||
TaggedIndex::Seg($index) => $expr,
|
TaggedIndex::Seg($index) => $expr,
|
||||||
TaggedIndex::Bend($index) => $expr,
|
TaggedIndex::Bend($index) => $expr,
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DotIndex = Index<DotWeight>;
|
pub type DotIndex = Index<DotWeight>;
|
||||||
|
|
|
||||||
212
src/layout.rs
212
src/layout.rs
|
|
@ -1,14 +1,14 @@
|
||||||
use std::cell::{RefCell, Ref};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use geo::geometry::Point;
|
use geo::geometry::Point;
|
||||||
|
use std::cell::{Ref, RefCell};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::graph::{BendIndex, DotIndex, Path, SegIndex, TaggedIndex};
|
||||||
|
use crate::graph::{BendWeight, DotWeight, SegWeight, TaggedWeight};
|
||||||
|
use crate::math;
|
||||||
use crate::math::Circle;
|
use crate::math::Circle;
|
||||||
use crate::mesh::Mesh;
|
use crate::mesh::Mesh;
|
||||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, Path};
|
use crate::rules::{Conditions, Rules};
|
||||||
use crate::rules::{Rules, Conditions};
|
|
||||||
use crate::shape::Shape;
|
use crate::shape::Shape;
|
||||||
use crate::graph::{TaggedWeight, DotWeight, SegWeight, BendWeight};
|
|
||||||
use crate::math;
|
|
||||||
|
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
mesh: Mesh,
|
mesh: Mesh,
|
||||||
|
|
@ -29,20 +29,23 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route_start(&mut self, from: DotIndex) -> Head {
|
pub fn route_start(&mut self, from: DotIndex) -> Head {
|
||||||
Head {dot: from, bend: self.mesh.primitive(from).bend()}
|
Head {
|
||||||
}
|
dot: from,
|
||||||
|
bend: self.mesh.primitive(from).bend(),
|
||||||
pub fn route_finish(&mut self, head: Head, to: DotIndex, width: f64) {
|
|
||||||
if let Some(bend) = self.mesh.primitive(to).bend() {
|
|
||||||
self.route_finish_in_bend(head, bend, to, width);
|
|
||||||
} else {
|
|
||||||
self.route_finish_in_dot(head, to, width);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_finish_in_dot(&mut self, head: Head, to: DotIndex, width: f64) {
|
pub fn route_finish(&mut self, head: Head, to: DotIndex, width: f64) -> Result<(), ()> {
|
||||||
|
if let Some(bend) = self.mesh.primitive(to).bend() {
|
||||||
|
self.route_finish_in_bend(head, bend, to, width)
|
||||||
|
} else {
|
||||||
|
self.route_finish_in_dot(head, to, width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn route_finish_in_dot(&mut self, head: Head, to: DotIndex, width: f64) -> Result<(), ()> {
|
||||||
let from_circle = self.head_guidecircle(&head, width);
|
let from_circle = self.head_guidecircle(&head, width);
|
||||||
|
|
||||||
let conditions = Conditions {
|
let conditions = Conditions {
|
||||||
lower_net: None,
|
lower_net: None,
|
||||||
higher_net: None,
|
higher_net: None,
|
||||||
|
|
@ -58,11 +61,18 @@ impl Layout {
|
||||||
let from_cw = self.head_cw(&head);
|
let from_cw = self.head_cw(&head);
|
||||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None);
|
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None);
|
||||||
|
|
||||||
let head = self.extend_head(head, tangent_points.0);
|
let head = self.extend_head(head, tangent_points.0)?;
|
||||||
self.add_seg(head.dot, to, width);
|
self.add_seg(head.dot, to, width)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_finish_in_bend(&mut self, head: Head, to_bend: BendIndex, to: DotIndex, width: f64) {
|
fn route_finish_in_bend(
|
||||||
|
&mut self,
|
||||||
|
head: Head,
|
||||||
|
to_bend: BendIndex,
|
||||||
|
to: DotIndex,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<(), ()> {
|
||||||
let from_circle = self.head_guidecircle(&head, width);
|
let from_circle = self.head_guidecircle(&head, width);
|
||||||
|
|
||||||
let conditions = Conditions {
|
let conditions = Conditions {
|
||||||
|
|
@ -75,26 +85,42 @@ impl Layout {
|
||||||
let to_circle = self.bend_circle(to_bend, width);
|
let to_circle = self.bend_circle(to_bend, width);
|
||||||
let from_cw = self.head_cw(&head);
|
let from_cw = self.head_cw(&head);
|
||||||
|
|
||||||
let to_head = Head {bend: Some(to_bend), dot: to};
|
let to_head = Head {
|
||||||
|
bend: Some(to_bend),
|
||||||
|
dot: to,
|
||||||
|
};
|
||||||
let to_cw = self.head_cw(&to_head);
|
let to_cw = self.head_cw(&to_head);
|
||||||
|
|
||||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, to_cw);
|
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, to_cw);
|
||||||
let head = self.extend_head(head, tangent_points.0);
|
let head = self.extend_head(head, tangent_points.0)?;
|
||||||
|
|
||||||
let to_head = self.extend_head(to_head, tangent_points.1);
|
let to_head = self.extend_head(to_head, tangent_points.1)?;
|
||||||
self.add_seg(head.dot, to, width);
|
self.add_seg(head.dot, to, width)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shove_around_dot(&mut self, head: Head, around: DotIndex, cw: bool, width: f64) -> Head {
|
pub fn shove_around_dot(
|
||||||
|
&mut self,
|
||||||
|
head: Head,
|
||||||
|
around: DotIndex,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<Head, ()> {
|
||||||
let outer = self.mesh.primitive(around).outer().unwrap();
|
let outer = self.mesh.primitive(around).outer().unwrap();
|
||||||
let head = self.route_around_dot(head, around, cw, width);
|
let head = self.route_around_dot(head, around, cw, width)?;
|
||||||
self.mesh.reattach_bend(outer, head.bend.unwrap());
|
self.mesh.reattach_bend(outer, head.bend.unwrap());
|
||||||
|
|
||||||
self.reroute_outward(outer);
|
self.reroute_outward(outer)?;
|
||||||
head
|
Ok(head)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route_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,
|
||||||
|
) -> Result<Head, ()> {
|
||||||
let from_circle = self.head_guidecircle(&head, width);
|
let from_circle = self.head_guidecircle(&head, width);
|
||||||
|
|
||||||
let conditions = Conditions {
|
let conditions = Conditions {
|
||||||
|
|
@ -109,22 +135,34 @@ impl Layout {
|
||||||
let from_cw = self.head_cw(&head);
|
let from_cw = self.head_cw(&head);
|
||||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw));
|
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw));
|
||||||
|
|
||||||
let head = self.extend_head(head, tangent_points.0);
|
let head = self.extend_head(head, tangent_points.0)?;
|
||||||
self.route_seg_bend(head, TaggedIndex::Dot(around), tangent_points.1, cw, width)
|
self.route_seg_bend(head, TaggedIndex::Dot(around), tangent_points.1, cw, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shove_around_bend(&mut self, head: Head, around: BendIndex, cw: bool, width: f64) -> Head {
|
pub fn shove_around_bend(
|
||||||
|
&mut self,
|
||||||
|
head: Head,
|
||||||
|
around: BendIndex,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<Head, ()> {
|
||||||
let outer = self.mesh.primitive(around).outer().unwrap();
|
let outer = self.mesh.primitive(around).outer().unwrap();
|
||||||
let head = self.route_around_bend(head, around, cw, width);
|
let head = self.route_around_bend(head, around, cw, width)?;
|
||||||
self.mesh.reattach_bend(outer, head.bend.unwrap());
|
self.mesh.reattach_bend(outer, head.bend.unwrap());
|
||||||
|
|
||||||
self.reroute_outward(outer);
|
self.reroute_outward(outer)?;
|
||||||
head
|
Ok(head)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route_around_bend(&mut self, head: Head, around: BendIndex, cw: bool, width: f64) -> Head {
|
pub fn route_around_bend(
|
||||||
|
&mut self,
|
||||||
|
head: Head,
|
||||||
|
around: BendIndex,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<Head, ()> {
|
||||||
let from_circle = self.head_guidecircle(&head, width);
|
let from_circle = self.head_guidecircle(&head, width);
|
||||||
|
|
||||||
let conditions = Conditions {
|
let conditions = Conditions {
|
||||||
lower_net: None,
|
lower_net: None,
|
||||||
higher_net: None,
|
higher_net: None,
|
||||||
|
|
@ -137,20 +175,32 @@ impl Layout {
|
||||||
let from_cw = self.head_cw(&head);
|
let from_cw = self.head_cw(&head);
|
||||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw));
|
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw));
|
||||||
|
|
||||||
let head = self.extend_head(head, tangent_points.0);
|
let head = self.extend_head(head, tangent_points.0)?;
|
||||||
self.route_seg_bend(head, TaggedIndex::Bend(around), tangent_points.1, cw, width)
|
self.route_seg_bend(head, TaggedIndex::Bend(around), tangent_points.1, cw, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_seg_bend(&mut self, head: Head, around: TaggedIndex, to: Point, cw: bool, width: f64) -> Head {
|
fn route_seg_bend(
|
||||||
let head = self.route_seg(head, to, width);
|
&mut self,
|
||||||
let bend_to = self.add_dot(self.mesh.primitive(head.dot).weight());
|
head: Head,
|
||||||
|
around: TaggedIndex,
|
||||||
|
to: Point,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<Head, ()> {
|
||||||
|
let head = self.route_seg(head, to, width)?;
|
||||||
|
let bend_to = self.add_dot(self.mesh.primitive(head.dot).weight())?;
|
||||||
let net = self.mesh.primitive(head.dot).weight().net;
|
let net = self.mesh.primitive(head.dot).weight().net;
|
||||||
|
|
||||||
let bend = self.mesh.add_bend(head.dot, bend_to, around, BendWeight {net, cw});
|
let bend = self
|
||||||
Head {dot: bend_to, bend: Some(bend)}
|
.mesh
|
||||||
|
.add_bend(head.dot, bend_to, around, BendWeight { net, cw })?;
|
||||||
|
Ok(Head {
|
||||||
|
dot: bend_to,
|
||||||
|
bend: Some(bend),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reroute_outward(&mut self, bend: BendIndex) {
|
fn reroute_outward(&mut self, bend: BendIndex) -> Result<(), ()> {
|
||||||
let mut endss: Vec<[DotIndex; 2]> = vec![];
|
let mut endss: Vec<[DotIndex; 2]> = vec![];
|
||||||
let mut interiors: Vec<Vec<TaggedIndex>> = vec![];
|
let mut interiors: Vec<Vec<TaggedIndex>> = vec![];
|
||||||
let cw = self.mesh.primitive(bend).weight().cw;
|
let cw = self.mesh.primitive(bend).weight().cw;
|
||||||
|
|
@ -179,43 +229,51 @@ impl Layout {
|
||||||
let width = 5.0;
|
let width = 5.0;
|
||||||
|
|
||||||
if let Some(inner) = maybe_inner {
|
if let Some(inner) = maybe_inner {
|
||||||
head = self.route_around_bend(head, inner, cw, width);
|
head = self.route_around_bend(head, inner, cw, width)?;
|
||||||
} else {
|
} else {
|
||||||
head = self.route_around_dot(head, core, cw, width);
|
head = self.route_around_dot(head, core, cw, width)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_inner = head.bend;
|
maybe_inner = head.bend;
|
||||||
self.route_finish(head, ends[1], width);
|
self.route_finish(head, ends[1], width)?;
|
||||||
self.relax_band(maybe_inner.unwrap());
|
self.relax_band(maybe_inner.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_seg(&mut self, head: Head, to: Point, width: f64) -> Head {
|
fn route_seg(&mut self, head: Head, to: Point, width: f64) -> Result<Head, ()> {
|
||||||
let net = self.mesh.primitive(head.dot).weight().net;
|
let net = self.mesh.primitive(head.dot).weight().net;
|
||||||
|
|
||||||
assert!(width <= self.mesh.primitive(head.dot).weight().circle.r * 2.0);
|
assert!(width <= self.mesh.primitive(head.dot).weight().circle.r * 2.);
|
||||||
|
|
||||||
let to_index = self.mesh.add_dot(DotWeight {
|
let to_index = self.mesh.add_dot(DotWeight {
|
||||||
net,
|
net,
|
||||||
circle: Circle {pos: to, r: width / 2.0},
|
circle: Circle {
|
||||||
});
|
pos: to,
|
||||||
self.add_seg(head.dot, to_index, width);
|
r: width / 2.0,
|
||||||
Head {dot: to_index, bend: None}
|
},
|
||||||
|
})?;
|
||||||
|
self.add_seg(head.dot, to_index, width)?;
|
||||||
|
Ok(Head {
|
||||||
|
dot: to_index,
|
||||||
|
bend: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relax_band(&mut self, bend: BendIndex) {
|
fn relax_band(&mut self, bend: BendIndex) {
|
||||||
let mut prev_bend = bend;
|
let mut prev_bend = bend;
|
||||||
while let Some(cur_bend) = self.mesh.primitive(prev_bend).prev_akin() {
|
while let Some(cur_bend) = self.mesh.primitive(prev_bend).prev_akin() {
|
||||||
if self.mesh.primitive(cur_bend).cross_product() >= 0.0 {
|
if self.mesh.primitive(cur_bend).cross_product() >= 0. {
|
||||||
self.release_bow(cur_bend);
|
self.release_bow(cur_bend);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_bend = cur_bend;
|
prev_bend = cur_bend;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut prev_bend = bend;
|
let mut prev_bend = bend;
|
||||||
while let Some(cur_bend) = self.mesh.primitive(prev_bend).next_akin() {
|
while let Some(cur_bend) = self.mesh.primitive(prev_bend).next_akin() {
|
||||||
if self.mesh.primitive(cur_bend).cross_product() >= 0.0 {
|
if self.mesh.primitive(cur_bend).cross_product() >= 0. {
|
||||||
self.release_bow(cur_bend);
|
self.release_bow(cur_bend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,15 +288,17 @@ impl Layout {
|
||||||
self.mesh.remove_open_set(bow.interior());
|
self.mesh.remove_open_set(bow.interior());
|
||||||
|
|
||||||
let head = self.route_start(ends[0]);
|
let head = self.route_start(ends[0]);
|
||||||
self.route_finish(head, ends[1], 5.0);
|
let _ = self.route_finish(head, ends[1], 5.);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_dot(&mut self, dot: DotIndex, to: Point) {
|
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> {
|
||||||
self.mesh.move_dot(dot, to);
|
self.mesh.move_dot(dot, to)?;
|
||||||
|
|
||||||
if let Some(outer) = self.mesh.primitive(dot).outer() {
|
if let Some(outer) = self.mesh.primitive(dot).outer() {
|
||||||
self.reroute_outward(outer);
|
self.reroute_outward(outer)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_guidecircle(&self, head: &Head, width: f64) -> Circle {
|
fn head_guidecircle(&self, head: &Head, width: f64) -> Circle {
|
||||||
|
|
@ -256,9 +316,13 @@ 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().unwrap(), width + 5.0, conditions)
|
self.dot_guidecircle(
|
||||||
|
self.mesh.primitive(bend).core().unwrap(),
|
||||||
|
width + 5.0,
|
||||||
|
conditions,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => Circle {
|
None => Circle {
|
||||||
pos: self.mesh.primitive(head.dot).weight().circle.pos,
|
pos: self.mesh.primitive(head.dot).weight().circle.pos,
|
||||||
r: 0.0,
|
r: 0.0,
|
||||||
|
|
@ -290,7 +354,11 @@ impl Layout {
|
||||||
layer = inner;
|
layer = inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).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 + width + 5.0,
|
r: core_circle.r + r + width + 5.0,
|
||||||
|
|
@ -303,11 +371,11 @@ impl Layout {
|
||||||
circle
|
circle
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_head(&mut self, head: Head, to: Point) -> Head {
|
fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, ()> {
|
||||||
if let Some(..) = head.bend {
|
if let Some(..) = head.bend {
|
||||||
self.extend_head_bend(head, to)
|
self.extend_head_bend(head, to)
|
||||||
} else {
|
} else {
|
||||||
head
|
Ok(head)
|
||||||
// No assertion for now because we temporarily use floats.
|
// No assertion for now because we temporarily use floats.
|
||||||
|
|
||||||
//println!("{:?} {:?}", self.mesh.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos, to);
|
//println!("{:?} {:?}", self.mesh.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos, to);
|
||||||
|
|
@ -315,21 +383,23 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_head_bend(&mut self, head: Head, to: Point) -> Head {
|
fn extend_head_bend(&mut self, head: Head, to: Point) -> Result<Head, ()> {
|
||||||
self.mesh.extend_bend(head.bend.unwrap(), head.dot, to);
|
self.mesh.extend_bend(head.bend.unwrap(), head.dot, to)?;
|
||||||
head
|
Ok(head)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
|
pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> {
|
||||||
self.mesh.add_dot(weight)
|
self.mesh.add_dot(weight)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, width: f64) -> SegIndex {
|
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, width: f64) -> Result<SegIndex, ()> {
|
||||||
let net = self.mesh.primitive(from).weight().net;
|
let net = self.mesh.primitive(from).weight().net;
|
||||||
self.mesh.add_seg(from, to, SegWeight {net, width})
|
self.mesh.add_seg(from, to, SegWeight { net, width })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shapes(&self) -> impl Iterator<Item=Shape> + '_ {
|
pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
|
||||||
self.mesh.nodes().map(|ni| untag!(ni, self.mesh.primitive(ni).shape()))
|
self.mesh
|
||||||
|
.nodes()
|
||||||
|
.map(|ni| untag!(ni, self.mesh.primitive(ni).shape()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
286
src/main.rs
286
src/main.rs
|
|
@ -4,40 +4,42 @@ macro_rules! dbg_dot {
|
||||||
($graph:expr) => {
|
($graph:expr) => {
|
||||||
use petgraph::dot::Dot;
|
use petgraph::dot::Dot;
|
||||||
println!("{:?}", Dot::new(&$graph));
|
println!("{:?}", Dot::new(&$graph));
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_use] mod graph;
|
#[macro_use]
|
||||||
mod layout;
|
mod graph;
|
||||||
mod rules;
|
|
||||||
mod mesh;
|
|
||||||
mod bow;
|
mod bow;
|
||||||
mod primitive;
|
mod layout;
|
||||||
mod shape;
|
|
||||||
mod math;
|
mod math;
|
||||||
|
mod mesh;
|
||||||
|
mod primitive;
|
||||||
|
mod rules;
|
||||||
|
mod shape;
|
||||||
|
|
||||||
use std::panic;
|
|
||||||
use std::time::Duration;
|
|
||||||
use geo::EuclideanDistance;
|
use geo::EuclideanDistance;
|
||||||
use graph::{TaggedIndex, Tag};
|
use graph::{Tag, TaggedIndex};
|
||||||
use sdl2::EventPump;
|
|
||||||
use sdl2::pixels::Color;
|
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
use sdl2::keyboard::Keycode;
|
|
||||||
use sdl2::gfx::primitives::DrawRenderer;
|
use sdl2::gfx::primitives::DrawRenderer;
|
||||||
|
use sdl2::keyboard::Keycode;
|
||||||
|
use sdl2::pixels::Color;
|
||||||
use sdl2::render::Canvas;
|
use sdl2::render::Canvas;
|
||||||
use sdl2::video::Window;
|
use sdl2::video::Window;
|
||||||
|
use sdl2::EventPump;
|
||||||
use shape::Shape;
|
use shape::Shape;
|
||||||
|
use std::panic;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::layout::Layout;
|
|
||||||
use crate::graph::DotWeight;
|
use crate::graph::DotWeight;
|
||||||
|
use crate::layout::Layout;
|
||||||
use crate::math::Circle;
|
use crate::math::Circle;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
|
let window = video_subsystem
|
||||||
|
.window("rust-sdl2 demo", 800, 600)
|
||||||
.position_centered()
|
.position_centered()
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -52,7 +54,6 @@ fn main() {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut layout = Layout::new();
|
let mut layout = Layout::new();
|
||||||
|
|
||||||
|
|
||||||
/*let index = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.0}});
|
/*let index = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.0}});
|
||||||
//layout.route_seg(index, Point {x: 400.5, y: 350.5}, 6.0);
|
//layout.route_seg(index, Point {x: 400.5, y: 350.5}, 6.0);
|
||||||
|
|
||||||
|
|
@ -70,7 +71,6 @@ fn main() {
|
||||||
let index6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}});
|
let index6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}});
|
||||||
let index7 = layout.route_to(index5, index6, 5.0);*/
|
let index7 = layout.route_to(index5, index6, 5.0);*/
|
||||||
|
|
||||||
|
|
||||||
/*let dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.5, 150.5).into(), r: 8.0}});
|
/*let dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.5, 150.5).into(), r: 8.0}});
|
||||||
let dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 150.5).into(), r: 8.0}});
|
let dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 150.5).into(), r: 8.0}});
|
||||||
let dot3 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 150.5).into(), r: 8.0}});
|
let dot3 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 150.5).into(), r: 8.0}});
|
||||||
|
|
@ -103,86 +103,202 @@ fn main() {
|
||||||
let head = layout.route_around_bend(head, bend2_2, true, 5.0);
|
let head = layout.route_around_bend(head, bend2_2, true, 5.0);
|
||||||
layout.route_finish(head, dot6, 5.0);*/
|
layout.route_finish(head, dot6, 5.0);*/
|
||||||
|
|
||||||
|
let dot1_1 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (100.5, 400.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let dot2_1 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (130.5, 430.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let dot3_1 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (160.5, 460.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let dot4_1 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (190.5, 490.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let dot1_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.5, 400.5).into(), r: 8.0}});
|
let dot1_2 = layout
|
||||||
let dot2_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 430.5).into(), r: 8.0}});
|
.add_dot(DotWeight {
|
||||||
let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 460.5).into(), r: 8.0}});
|
net: 0,
|
||||||
let dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (190.5, 490.5).into(), r: 8.0}});
|
circle: Circle {
|
||||||
|
pos: (700.5, 400.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let dot2_2 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (670.5, 430.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let dot3_2 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (640.5, 460.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let dot4_2 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (610.5, 490.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let dot1_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (700.5, 400.5).into(), r: 8.0}});
|
let barrier1_dot1 = layout
|
||||||
let dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (670.5, 430.5).into(), r: 8.0}});
|
.add_dot(DotWeight {
|
||||||
let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (640.5, 460.5).into(), r: 8.0}});
|
net: 0,
|
||||||
let dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (610.5, 490.5).into(), r: 8.0}});
|
circle: Circle {
|
||||||
|
pos: (250.5, 150.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let barrier1_dot2 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (250.5, 700.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let _ = layout.add_seg(barrier1_dot1, barrier1_dot2, 16.0);
|
||||||
|
|
||||||
let barrier1_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (250.5, 150.5).into(), r: 8.0}});
|
let barrier2_dot1 = layout
|
||||||
let barrier1_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (250.5, 700.5).into(), r: 8.0}});
|
.add_dot(DotWeight {
|
||||||
layout.add_seg(barrier1_dot1, barrier1_dot2, 16.0);
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
let barrier2_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (450.5, 200.5).into(), r: 8.0}});
|
pos: (420.5, 200.5).into(),
|
||||||
let barrier2_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (450.5, 700.5).into(), r: 8.0}});
|
r: 8.0,
|
||||||
layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0);
|
},
|
||||||
|
})
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
.unwrap();
|
||||||
|
let barrier2_dot2 = layout
|
||||||
|
.add_dot(DotWeight {
|
||||||
|
net: 0,
|
||||||
|
circle: Circle {
|
||||||
|
pos: (480.5, 700.5).into(),
|
||||||
|
r: 8.0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let _ = layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0);
|
||||||
|
|
||||||
|
/*render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||||
|
|
||||||
let head = layout.route_start(dot1_1);
|
let head = layout.route_start(dot1_1);
|
||||||
let head = layout.route_around_dot(head, barrier1_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.route_around_dot(head, barrier1_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
let head = layout.route_around_dot(head, barrier2_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.route_around_dot(head, barrier2_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot1_2, 5.0);
|
layout.route_finish(head, dot1_2, 5.0).unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot2_1);
|
let head = layout.route_start(dot2_1);
|
||||||
let head = layout.shove_around_dot(head, barrier1_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.shove_around_dot(head, barrier1_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
let head = layout.shove_around_dot(head, barrier2_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.shove_around_dot(head, barrier2_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot2_2, 5.0);
|
let _ = layout.route_finish(head, dot2_2, 5.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot3_1);
|
let head = layout.route_start(dot3_1);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
let head = layout.shove_around_dot(head, barrier1_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.shove_around_dot(head, barrier1_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
let head = layout.shove_around_dot(head, barrier2_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.shove_around_dot(head, barrier2_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot3_2, 5.0);
|
let _ = layout.route_finish(head, dot3_2, 5.);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot4_1);
|
let head = layout.route_start(dot4_1);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
let head = layout.shove_around_dot(head, barrier1_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.shove_around_dot(head, barrier1_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
let head = layout.shove_around_dot(head, barrier2_dot1, true, 5.0);
|
let head = layout
|
||||||
|
.shove_around_dot(head, barrier2_dot1, true, 5.)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot4_2, 5.0);
|
let _ = layout.route_finish(head, dot4_2, 5.);*/
|
||||||
|
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, Some(barrier1_dot1.tag()), -1);
|
render_times(
|
||||||
|
&mut event_pump,
|
||||||
|
&mut canvas,
|
||||||
|
&mut layout,
|
||||||
|
Some(barrier1_dot1.tag()),
|
||||||
|
-1,
|
||||||
|
);
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout: &mut Layout,
|
fn render_times(
|
||||||
follower: Option<TaggedIndex>, times: i64)
|
event_pump: &mut EventPump,
|
||||||
{
|
canvas: &mut Canvas<Window>,
|
||||||
|
layout: &mut Layout,
|
||||||
|
follower: Option<TaggedIndex>,
|
||||||
|
times: i64,
|
||||||
|
) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
||||||
'running: loop {
|
'running: loop {
|
||||||
|
|
@ -191,10 +307,11 @@ fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout:
|
||||||
|
|
||||||
for event in event_pump.poll_iter() {
|
for event in event_pump.poll_iter() {
|
||||||
match event {
|
match event {
|
||||||
Event::Quit {..} |
|
Event::Quit { .. }
|
||||||
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
|
| Event::KeyDown {
|
||||||
break 'running
|
keycode: Some(Keycode::Escape),
|
||||||
}
|
..
|
||||||
|
} => break 'running,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,26 +319,33 @@ fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout:
|
||||||
if let Some(follower) = follower {
|
if let Some(follower) = follower {
|
||||||
let state = event_pump.mouse_state();
|
let state = event_pump.mouse_state();
|
||||||
|
|
||||||
layout.move_dot(*follower.as_dot().unwrap(), (state.x() as f64, state.y() as f64).into());
|
let _ = layout.move_dot(
|
||||||
|
*follower.as_dot().unwrap(),
|
||||||
|
(state.x() as f64, state.y() as f64).into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = panic::catch_unwind(|| {
|
let result = panic::catch_unwind(|| {
|
||||||
for shape in layout.shapes() {
|
for shape in layout.shapes() {
|
||||||
match shape {
|
match shape {
|
||||||
Shape::Dot(dot) => {
|
Shape::Dot(dot) => {
|
||||||
let _ = canvas.filled_circle(dot.c.pos.x() as i16,
|
let _ = canvas.filled_circle(
|
||||||
dot.c.pos.y() as i16,
|
dot.c.pos.x() as i16,
|
||||||
dot.c.r as i16,
|
dot.c.pos.y() as i16,
|
||||||
Color::RGB(200, 52, 52));
|
dot.c.r as i16,
|
||||||
},
|
Color::RGB(200, 52, 52),
|
||||||
|
);
|
||||||
|
}
|
||||||
Shape::Seg(seg) => {
|
Shape::Seg(seg) => {
|
||||||
let _ = canvas.thick_line(seg.from.x() as i16,
|
let _ = canvas.thick_line(
|
||||||
seg.from.y() as i16,
|
seg.from.x() as i16,
|
||||||
seg.to.x() as i16,
|
seg.from.y() as i16,
|
||||||
seg.to.y() as i16,
|
seg.to.x() as i16,
|
||||||
seg.width as u8,
|
seg.to.y() as i16,
|
||||||
Color::RGB(200, 52, 52));
|
seg.width as u8,
|
||||||
},
|
Color::RGB(200, 52, 52),
|
||||||
|
);
|
||||||
|
}
|
||||||
Shape::Bend(bend) => {
|
Shape::Bend(bend) => {
|
||||||
let delta1 = bend.from - bend.center;
|
let delta1 = bend.from - bend.center;
|
||||||
let delta2 = bend.to - bend.center;
|
let delta2 = bend.to - bend.center;
|
||||||
|
|
@ -240,17 +364,19 @@ fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout:
|
||||||
(r + (d as f64)) as i16,
|
(r + (d as f64)) as i16,
|
||||||
angle1.to_degrees() as i16,
|
angle1.to_degrees() as i16,
|
||||||
angle2.to_degrees() as i16,
|
angle2.to_degrees() as i16,
|
||||||
Color::RGB(200, 52, 52));
|
Color::RGB(200, 52, 52),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
/*let envelope = shape.envelope();
|
let envelope = shape.envelope();
|
||||||
let _ = canvas.rectangle(envelope.lower()[0] as i16,
|
let _ = canvas.rectangle(
|
||||||
envelope.lower()[1] as i16,
|
envelope.lower()[0] as i16,
|
||||||
envelope.upper()[0] as i16,
|
envelope.lower()[1] as i16,
|
||||||
envelope.upper()[1] as i16,
|
envelope.upper()[0] as i16,
|
||||||
|
envelope.upper()[1] as i16,
|
||||||
Color::RGB(100, 100, 100));*/
|
Color::RGB(100, 100, 100),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
58
src/math.rs
58
src/math.rs
|
|
@ -1,5 +1,5 @@
|
||||||
|
use geo::{geometry::Point, point, EuclideanDistance};
|
||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
use geo::{geometry::Point, EuclideanDistance, point};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Line {
|
pub struct Line {
|
||||||
|
|
@ -19,7 +19,10 @@ impl Sub for Circle {
|
||||||
|
|
||||||
fn sub(self, other: Self) -> Self {
|
fn sub(self, other: Self) -> Self {
|
||||||
//return Self{pos: Point{x: self.pos.x() - other.pos.x(), y: self.pos.y() - other.pos.y()}, r: self.r};
|
//return Self{pos: Point{x: self.pos.x() - other.pos.x(), y: self.pos.y() - other.pos.y()}, r: self.r};
|
||||||
return Self {pos: self.pos - other.pos, r: self.r};
|
return Self {
|
||||||
|
pos: self.pos - other.pos,
|
||||||
|
r: self.r,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,23 +62,43 @@ fn _tangents(circle1: Circle, circle2: Circle) -> [Line; 4] {
|
||||||
|
|
||||||
fn cast_point_to_line(pt: Point, line: Line) -> Point {
|
fn cast_point_to_line(pt: Point, line: Line) -> Point {
|
||||||
return (
|
return (
|
||||||
(line.b * (line.b * pt.x() - line.a * pt.y()) - line.a * line.c) / (line.a * line.a + line.b * line.b),
|
(line.b * (line.b * pt.x() - line.a * pt.y()) - line.a * line.c)
|
||||||
(line.a * (-line.b * pt.x() + line.a * pt.y()) - line.b * line.c) / (line.a * line.a + line.b * line.b),
|
/ (line.a * line.a + line.b * line.b),
|
||||||
).into();
|
(line.a * (-line.b * pt.x() + line.a * pt.y()) - line.b * line.c)
|
||||||
|
/ (line.a * line.a + line.b * line.b),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] {
|
pub fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] {
|
||||||
let tgs = _tangents(circle1, circle2);
|
let tgs = _tangents(circle1, circle2);
|
||||||
|
|
||||||
[
|
[
|
||||||
(cast_point_to_line(circle1.pos, tgs[0]), cast_point_to_line(circle2.pos, tgs[0])),
|
(
|
||||||
(cast_point_to_line(circle1.pos, tgs[1]), cast_point_to_line(circle2.pos, tgs[1])),
|
cast_point_to_line(circle1.pos, tgs[0]),
|
||||||
(cast_point_to_line(circle1.pos, tgs[2]), cast_point_to_line(circle2.pos, tgs[2])),
|
cast_point_to_line(circle2.pos, tgs[0]),
|
||||||
(cast_point_to_line(circle1.pos, tgs[3]), cast_point_to_line(circle2.pos, tgs[3])),
|
),
|
||||||
|
(
|
||||||
|
cast_point_to_line(circle1.pos, tgs[1]),
|
||||||
|
cast_point_to_line(circle2.pos, tgs[1]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cast_point_to_line(circle1.pos, tgs[2]),
|
||||||
|
cast_point_to_line(circle2.pos, tgs[2]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cast_point_to_line(circle1.pos, tgs[3]),
|
||||||
|
cast_point_to_line(circle2.pos, tgs[3]),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tangent_point_pair(circle1: Circle, cw1: Option<bool>, circle2: Circle, cw2: Option<bool>) -> (Point, Point) {
|
pub fn tangent_point_pair(
|
||||||
|
circle1: Circle,
|
||||||
|
cw1: Option<bool>,
|
||||||
|
circle2: Circle,
|
||||||
|
cw2: Option<bool>,
|
||||||
|
) -> (Point, Point) {
|
||||||
let tangent_point_pairs = tangent_point_pairs(circle1, circle2);
|
let tangent_point_pairs = tangent_point_pairs(circle1, circle2);
|
||||||
|
|
||||||
for tangent_point_pair in tangent_point_pairs {
|
for tangent_point_pair in tangent_point_pairs {
|
||||||
|
|
@ -116,22 +139,19 @@ pub fn circles_intersection(circle1: &Circle, circle2: &Circle) -> Vec<Point> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distance from `circle1.pos` to the intersection of the diagonals.
|
// Distance from `circle1.pos` to the intersection of the diagonals.
|
||||||
let a = (circle1.r*circle1.r - circle2.r*circle2.r + d*d) / (2.0*d);
|
let a = (circle1.r * circle1.r - circle2.r * circle2.r + d * d) / (2.0 * d);
|
||||||
|
|
||||||
// Intersection of the diagonals.
|
// Intersection of the diagonals.
|
||||||
let p = circle1.pos + delta*(a/d);
|
let p = circle1.pos + delta * (a / d);
|
||||||
let h = (circle1.r*circle1.r - a*a).sqrt();
|
let h = (circle1.r * circle1.r - a * a).sqrt();
|
||||||
|
|
||||||
if h == 0. {
|
if h == 0. {
|
||||||
return [p].into();
|
return [p].into();
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = point! {x: -delta.x(), y: delta.y()} * (h/d);
|
let r = point! {x: -delta.x(), y: delta.y()} * (h / d);
|
||||||
|
|
||||||
[
|
[p + r, p - r].into()
|
||||||
p + r,
|
|
||||||
p - r,
|
|
||||||
].into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn between_vectors(v: Point, from: Point, to: Point) -> bool {
|
pub fn between_vectors(v: Point, from: Point, to: Point) -> bool {
|
||||||
|
|
|
||||||
136
src/mesh.rs
136
src/mesh.rs
|
|
@ -1,14 +1,17 @@
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
use petgraph::Direction::Incoming;
|
|
||||||
use petgraph::stable_graph::StableDiGraph;
|
use petgraph::stable_graph::StableDiGraph;
|
||||||
use petgraph::visit::EdgeRef;
|
use petgraph::visit::EdgeRef;
|
||||||
use rstar::RTree;
|
use petgraph::Direction::Incoming;
|
||||||
use rstar::primitives::GeomWithData;
|
use rstar::primitives::GeomWithData;
|
||||||
|
use rstar::RTree;
|
||||||
|
|
||||||
|
use crate::bow::Bow;
|
||||||
|
use crate::graph::{
|
||||||
|
BendIndex, BendWeight, DotIndex, DotWeight, Index, Label, Path, SegIndex, SegWeight, Tag,
|
||||||
|
TaggedIndex, TaggedWeight,
|
||||||
|
};
|
||||||
use crate::primitive::Primitive;
|
use crate::primitive::Primitive;
|
||||||
use crate::shape::Shape;
|
use crate::shape::Shape;
|
||||||
use crate::graph::{Tag, TaggedIndex, DotIndex, SegIndex, BendIndex, Index, TaggedWeight, DotWeight, SegWeight, BendWeight, Label, Path};
|
|
||||||
use crate::bow::Bow;
|
|
||||||
|
|
||||||
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
||||||
|
|
||||||
|
|
@ -32,7 +35,7 @@ impl Mesh {
|
||||||
|
|
||||||
// We must remove the dots only after the segs and bends because we need dots to calculate
|
// We must remove the dots only after the segs and bends because we need dots to calculate
|
||||||
// the shapes, which we need to remove the segs and bends from the R-tree.
|
// the shapes, which we need to remove the segs and bends from the R-tree.
|
||||||
|
|
||||||
for index in open_set.iter().filter(|index| index.is_dot()) {
|
for index in open_set.iter().filter(|index| index.is_dot()) {
|
||||||
untag!(index, self.remove(*index));
|
untag!(index, self.remove(*index));
|
||||||
}
|
}
|
||||||
|
|
@ -47,55 +50,94 @@ impl Mesh {
|
||||||
self.graph.remove_node(index.index);
|
self.graph.remove_node(index.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
|
pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> {
|
||||||
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight)));
|
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight)));
|
||||||
self.rtree.insert(RTreeWrapper::new(self.primitive(dot).shape(), TaggedIndex::Dot(dot)));
|
self.fail_and_remove_if_collides(dot)?;
|
||||||
dot
|
|
||||||
|
self.rtree.insert(RTreeWrapper::new(
|
||||||
|
self.primitive(dot).shape(),
|
||||||
|
TaggedIndex::Dot(dot),
|
||||||
|
));
|
||||||
|
Ok(dot)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, weight: SegWeight) -> SegIndex {
|
pub fn add_seg(
|
||||||
|
&mut self,
|
||||||
|
from: DotIndex,
|
||||||
|
to: DotIndex,
|
||||||
|
weight: SegWeight,
|
||||||
|
) -> Result<SegIndex, ()> {
|
||||||
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight)));
|
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight)));
|
||||||
|
self.fail_and_remove_if_collides(seg)?;
|
||||||
|
|
||||||
self.graph.add_edge(from.index, seg.index, Label::End);
|
self.graph.add_edge(from.index, seg.index, Label::End);
|
||||||
self.graph.add_edge(seg.index, to.index, Label::End);
|
self.graph.add_edge(seg.index, to.index, Label::End);
|
||||||
|
|
||||||
self.rtree.insert(RTreeWrapper::new(self.primitive(seg).shape(), TaggedIndex::Seg(seg)));
|
self.insert_into_rtree(seg.tag());
|
||||||
seg
|
Ok(seg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_bend(&mut self, from: DotIndex, to: DotIndex, around: TaggedIndex, weight: BendWeight) -> BendIndex {
|
pub fn add_bend(
|
||||||
|
&mut self,
|
||||||
|
from: DotIndex,
|
||||||
|
to: DotIndex,
|
||||||
|
around: TaggedIndex,
|
||||||
|
weight: BendWeight,
|
||||||
|
) -> Result<BendIndex, ()> {
|
||||||
match around {
|
match around {
|
||||||
TaggedIndex::Dot(core) =>
|
TaggedIndex::Dot(core) => self.add_core_bend(from, to, core, weight),
|
||||||
self.add_core_bend(from, to, core, weight),
|
TaggedIndex::Bend(around) => self.add_outer_bend(from, to, around, weight),
|
||||||
TaggedIndex::Bend(around) =>
|
|
||||||
self.add_outer_bend(from, to, around, weight),
|
|
||||||
TaggedIndex::Seg(..) => unreachable!(),
|
TaggedIndex::Seg(..) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_core_bend(&mut self, from: DotIndex, to: DotIndex, core: DotIndex, weight: BendWeight) -> BendIndex {
|
pub fn add_core_bend(
|
||||||
|
&mut self,
|
||||||
|
from: DotIndex,
|
||||||
|
to: DotIndex,
|
||||||
|
core: DotIndex,
|
||||||
|
weight: BendWeight,
|
||||||
|
) -> Result<BendIndex, ()> {
|
||||||
let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight)));
|
let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight)));
|
||||||
|
self.fail_and_remove_if_collides(bend)?;
|
||||||
|
|
||||||
self.graph.add_edge(from.index, bend.index, Label::End);
|
self.graph.add_edge(from.index, bend.index, Label::End);
|
||||||
self.graph.add_edge(bend.index, to.index, Label::End);
|
self.graph.add_edge(bend.index, to.index, Label::End);
|
||||||
self.graph.add_edge(bend.index, core.index, Label::Core);
|
self.graph.add_edge(bend.index, core.index, Label::Core);
|
||||||
|
|
||||||
self.rtree.insert(RTreeWrapper::new(self.primitive(bend).shape(), TaggedIndex::Bend(bend)));
|
self.insert_into_rtree(bend.tag());
|
||||||
bend
|
Ok(bend)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_outer_bend(&mut self, from: DotIndex, to: DotIndex, inner: BendIndex, weight: BendWeight) -> BendIndex {
|
pub fn add_outer_bend(
|
||||||
let core = *self.graph.neighbors(inner.index)
|
&mut self,
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(inner.index, *ni).unwrap()).unwrap().is_core())
|
from: DotIndex,
|
||||||
|
to: DotIndex,
|
||||||
|
inner: BendIndex,
|
||||||
|
weight: BendWeight,
|
||||||
|
) -> Result<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))
|
.map(|ni| DotIndex::new(ni))
|
||||||
.collect::<Vec<DotIndex>>()
|
.collect::<Vec<DotIndex>>()
|
||||||
.first()
|
.first()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let bend = self.add_core_bend(from, to, core, weight);
|
let bend = self.add_core_bend(from, to, core, weight)?;
|
||||||
self.graph.add_edge(inner.index, bend.index, Label::Outer);
|
self.graph.add_edge(inner.index, bend.index, Label::Outer);
|
||||||
bend
|
Ok(bend)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reattach_bend(&mut self, bend: BendIndex, inner: BendIndex) {
|
pub fn reattach_bend(&mut self, bend: BendIndex, inner: BendIndex) {
|
||||||
if let Some(old_inner_edge) = self.graph.edges_directed(bend.index, Incoming)
|
if let Some(old_inner_edge) = self
|
||||||
|
.graph
|
||||||
|
.edges_directed(bend.index, Incoming)
|
||||||
.filter(|edge| *edge.weight() == Label::Outer)
|
.filter(|edge| *edge.weight() == Label::Outer)
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
|
|
@ -104,13 +146,14 @@ impl Mesh {
|
||||||
self.graph.add_edge(inner.index, bend.index, Label::Outer);
|
self.graph.add_edge(inner.index, bend.index, Label::Outer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend_bend(&mut self, bend: BendIndex, dot: DotIndex, to: Point) {
|
pub fn extend_bend(&mut self, bend: BendIndex, dot: DotIndex, to: Point) -> Result<(), ()> {
|
||||||
self.remove_from_rtree(bend.tag());
|
self.remove_from_rtree(bend.tag());
|
||||||
self.move_dot(dot, to);
|
self.move_dot(dot, to)?;
|
||||||
self.insert_into_rtree(bend.tag());
|
self.insert_into_rtree(bend.tag());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_dot(&mut self, dot: DotIndex, to: Point) {
|
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> {
|
||||||
let mut cur_bend = self.primitive(dot).outer();
|
let mut cur_bend = self.primitive(dot).outer();
|
||||||
loop {
|
loop {
|
||||||
match cur_bend {
|
match cur_bend {
|
||||||
|
|
@ -119,15 +162,25 @@ impl Mesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.remove_from_rtree(cur_bend.unwrap().tag());
|
self.remove_from_rtree(cur_bend.unwrap().tag());
|
||||||
cur_bend = self.primitive(cur_bend.unwrap()).outer()
|
cur_bend = self.primitive(cur_bend.unwrap()).outer();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.remove_from_rtree(dot.tag());
|
self.remove_from_rtree(dot.tag());
|
||||||
|
|
||||||
let mut dot_weight = self.primitive(dot).weight();
|
let mut dot_weight = self.primitive(dot).weight();
|
||||||
|
let old_weight = dot_weight;
|
||||||
|
|
||||||
dot_weight.circle.pos = to;
|
dot_weight.circle.pos = to;
|
||||||
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight);
|
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight);
|
||||||
|
|
||||||
|
if let Some(..) = self.detect_collision(&self.primitive(dot).shape()) {
|
||||||
|
// Restore original state.
|
||||||
|
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(old_weight);
|
||||||
|
self.insert_into_rtree(dot.tag());
|
||||||
|
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
self.insert_into_rtree(dot.tag());
|
self.insert_into_rtree(dot.tag());
|
||||||
|
|
||||||
let mut cur_bend = self.primitive(dot).outer();
|
let mut cur_bend = self.primitive(dot).outer();
|
||||||
|
|
@ -138,11 +191,13 @@ impl Mesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.insert_into_rtree(cur_bend.unwrap().tag());
|
self.insert_into_rtree(cur_bend.unwrap().tag());
|
||||||
cur_bend = self.primitive(cur_bend.unwrap()).outer()
|
cur_bend = self.primitive(cur_bend.unwrap()).outer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,6 +209,25 @@ impl Mesh {
|
||||||
Bow::new(bend, &self.graph)
|
Bow::new(bend, &self.graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fail_and_remove_if_collides<Weight: std::marker::Copy>(
|
||||||
|
&mut self,
|
||||||
|
index: Index<Weight>,
|
||||||
|
) -> Result<(), ()> {
|
||||||
|
/*if self.detect_collision(&self.primitive(index).shape()) {
|
||||||
|
self.remove(index);
|
||||||
|
return Err(());
|
||||||
|
}*/
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detect_collision(&self, shape: &Shape) -> Option<TaggedIndex> {
|
||||||
|
self.rtree
|
||||||
|
.locate_in_envelope_intersecting(&shape.envelope())
|
||||||
|
.filter(|wrapper| shape.intersects(wrapper.geom()))
|
||||||
|
.map(|wrapper| wrapper.data)
|
||||||
|
.next()
|
||||||
|
}
|
||||||
|
|
||||||
fn insert_into_rtree(&mut self, index: TaggedIndex) {
|
fn insert_into_rtree(&mut self, index: TaggedIndex) {
|
||||||
let shape = untag!(index, self.primitive(index).shape());
|
let shape = untag!(index, self.primitive(index).shape());
|
||||||
self.rtree.insert(RTreeWrapper::new(shape, index));
|
self.rtree.insert(RTreeWrapper::new(shape, index));
|
||||||
|
|
|
||||||
139
src/primitive.rs
139
src/primitive.rs
|
|
@ -1,11 +1,14 @@
|
||||||
use std::mem::{swap, self};
|
use std::mem::{self, swap};
|
||||||
|
|
||||||
use petgraph::Direction::{Outgoing, Incoming};
|
|
||||||
use petgraph::stable_graph::StableDiGraph;
|
use petgraph::stable_graph::StableDiGraph;
|
||||||
|
use petgraph::Direction::{Incoming, Outgoing};
|
||||||
|
|
||||||
use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
|
use crate::graph::{
|
||||||
|
BendIndex, BendWeight, DotIndex, DotWeight, Index, Label, Path, SegIndex, SegWeight, Tag,
|
||||||
|
TaggedIndex, TaggedWeight,
|
||||||
|
};
|
||||||
use crate::math;
|
use crate::math;
|
||||||
use crate::shape::{Shape, DotShape, SegShape, BendShape};
|
use crate::shape::{BendShape, DotShape, SegShape, Shape};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Primitive<'a, Weight> {
|
pub struct Primitive<'a, Weight> {
|
||||||
|
|
@ -15,14 +18,12 @@ pub struct Primitive<'a, Weight> {
|
||||||
|
|
||||||
impl<'a, Weight> Primitive<'a, Weight> {
|
impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
pub fn new(index: Index<Weight>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self {
|
pub fn new(index: Index<Weight>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self {
|
||||||
Self {index, graph}
|
Self { index, graph }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shape(&self) -> Shape {
|
pub fn shape(&self) -> Shape {
|
||||||
match self.tagged_weight() {
|
match self.tagged_weight() {
|
||||||
TaggedWeight::Dot(dot) => Shape::Dot(DotShape {
|
TaggedWeight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }),
|
||||||
c: dot.circle,
|
|
||||||
}),
|
|
||||||
TaggedWeight::Seg(seg) => {
|
TaggedWeight::Seg(seg) => {
|
||||||
let ends = self.ends();
|
let ends = self.ends();
|
||||||
Shape::Seg(SegShape {
|
Shape::Seg(SegShape {
|
||||||
|
|
@ -30,7 +31,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
to: self.primitive(ends[1]).weight().circle.pos,
|
to: self.primitive(ends[1]).weight().circle.pos,
|
||||||
width: seg.width,
|
width: seg.width,
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
TaggedWeight::Bend(bend) => {
|
TaggedWeight::Bend(bend) => {
|
||||||
let ends = self.ends();
|
let ends = self.ends();
|
||||||
let mut bend_shape = BendShape {
|
let mut bend_shape = BendShape {
|
||||||
|
|
@ -44,13 +45,19 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
swap(&mut bend_shape.from, &mut bend_shape.to);
|
swap(&mut bend_shape.from, &mut bend_shape.to);
|
||||||
}
|
}
|
||||||
Shape::Bend(bend_shape)
|
Shape::Bend(bend_shape)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&self) -> Option<TaggedIndex> {
|
pub fn next(&self) -> Option<TaggedIndex> {
|
||||||
self.graph.neighbors_directed(self.index.index, Outgoing)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_end())
|
.neighbors_directed(self.index.index, Outgoing)
|
||||||
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.is_end()
|
||||||
|
})
|
||||||
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
@ -58,9 +65,16 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
pub fn next_akin(&self) -> Option<Index<Weight>> {
|
pub fn next_akin(&self) -> Option<Index<Weight>> {
|
||||||
let mut prev_index = self.index.index;
|
let mut prev_index = self.index.index;
|
||||||
|
|
||||||
while let Some(index) = self.graph.neighbors_directed(prev_index, Outgoing)
|
while let Some(index) = self
|
||||||
|
.graph
|
||||||
|
.neighbors_directed(prev_index, Outgoing)
|
||||||
.filter(|ni| self.graph.find_edge(prev_index, *ni).is_some())
|
.filter(|ni| self.graph.find_edge(prev_index, *ni).is_some())
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(prev_index, *ni).unwrap()).unwrap().is_end())
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(self.graph.find_edge(prev_index, *ni).unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.is_end()
|
||||||
|
})
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
let weight = *self.graph.node_weight(index).unwrap();
|
let weight = *self.graph.node_weight(index).unwrap();
|
||||||
|
|
@ -76,8 +90,14 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prev(&self) -> Option<TaggedIndex> {
|
pub fn prev(&self) -> Option<TaggedIndex> {
|
||||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_end())
|
.neighbors_directed(self.index.index, Incoming)
|
||||||
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.is_end()
|
||||||
|
})
|
||||||
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
@ -85,9 +105,16 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
pub fn prev_akin(&self) -> Option<Index<Weight>> {
|
pub fn prev_akin(&self) -> Option<Index<Weight>> {
|
||||||
let mut prev_index = self.index.index;
|
let mut prev_index = self.index.index;
|
||||||
|
|
||||||
while let Some(index) = self.graph.neighbors_directed(prev_index, Incoming)
|
while let Some(index) = self
|
||||||
|
.graph
|
||||||
|
.neighbors_directed(prev_index, Incoming)
|
||||||
.filter(|ni| self.graph.find_edge(*ni, prev_index).is_some())
|
.filter(|ni| self.graph.find_edge(*ni, prev_index).is_some())
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, prev_index).unwrap()).unwrap().is_end())
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(self.graph.find_edge(*ni, prev_index).unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.is_end()
|
||||||
|
})
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
let weight = *self.graph.node_weight(index).unwrap();
|
let weight = *self.graph.node_weight(index).unwrap();
|
||||||
|
|
@ -103,14 +130,21 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn core(&self) -> Option<DotIndex> {
|
pub fn core(&self) -> Option<DotIndex> {
|
||||||
self.graph.neighbors(self.index.index)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core())
|
.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))
|
.map(|ni| DotIndex::new(ni))
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tagged_index(&self) -> TaggedIndex {
|
pub fn tagged_index(&self) -> TaggedIndex {
|
||||||
self.index.retag(*self.graph.node_weight(self.index.index).unwrap())
|
self.index
|
||||||
|
.retag(*self.graph.node_weight(self.index.index).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tagged_weight(&self) -> TaggedWeight {
|
pub fn tagged_weight(&self) -> TaggedWeight {
|
||||||
|
|
@ -128,7 +162,8 @@ impl<'a, Weight> Path for Primitive<'a, Weight> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn closure(&self) -> Vec<TaggedIndex> {
|
fn closure(&self) -> Vec<TaggedIndex> {
|
||||||
let ends: Vec<TaggedIndex> = self.ends()
|
let ends: Vec<TaggedIndex> = self
|
||||||
|
.ends()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|end| TaggedIndex::Dot(end))
|
.map(|end| TaggedIndex::Dot(end))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
@ -136,8 +171,19 @@ impl<'a, Weight> Path for Primitive<'a, Weight> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ends(&self) -> [DotIndex; 2] {
|
fn ends(&self) -> [DotIndex; 2] {
|
||||||
self.graph.neighbors_undirected(self.index.index)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge_undirected(self.index.index, *ni).unwrap().0).unwrap().is_end())
|
.neighbors_undirected(self.index.index)
|
||||||
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(
|
||||||
|
self.graph
|
||||||
|
.find_edge_undirected(self.index.index, *ni)
|
||||||
|
.unwrap()
|
||||||
|
.0,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.is_end()
|
||||||
|
})
|
||||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_dot())
|
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_dot())
|
||||||
.map(|ni| DotIndex::new(ni))
|
.map(|ni| DotIndex::new(ni))
|
||||||
.collect::<Vec<DotIndex>>()
|
.collect::<Vec<DotIndex>>()
|
||||||
|
|
@ -152,16 +198,33 @@ pub type Bend<'a> = Primitive<'a, BendWeight>;
|
||||||
|
|
||||||
impl<'a> Dot<'a> {
|
impl<'a> Dot<'a> {
|
||||||
pub fn bend(&self) -> Option<BendIndex> {
|
pub fn bend(&self) -> Option<BendIndex> {
|
||||||
self.graph.neighbors_undirected(self.index.index)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge_undirected(self.index.index, *ni).unwrap().0).unwrap().is_end())
|
.neighbors_undirected(self.index.index)
|
||||||
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(
|
||||||
|
self.graph
|
||||||
|
.find_edge_undirected(self.index.index, *ni)
|
||||||
|
.unwrap()
|
||||||
|
.0,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.is_end()
|
||||||
|
})
|
||||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_bend())
|
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_bend())
|
||||||
.map(|ni| BendIndex::new(ni))
|
.map(|ni| BendIndex::new(ni))
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outer(&self) -> Option<BendIndex> {
|
pub fn outer(&self) -> Option<BendIndex> {
|
||||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_core())
|
.neighbors_directed(self.index.index, Incoming)
|
||||||
|
.filter(|ni| {
|
||||||
|
self.graph
|
||||||
|
.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.is_core()
|
||||||
|
})
|
||||||
.map(|ni| BendIndex::new(ni))
|
.map(|ni| BendIndex::new(ni))
|
||||||
.filter(|bend| self.primitive(*bend).inner().is_none())
|
.filter(|bend| self.primitive(*bend).inner().is_none())
|
||||||
.next()
|
.next()
|
||||||
|
|
@ -188,15 +251,27 @@ impl<'a> Bend<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner(&self) -> Option<BendIndex> {
|
pub fn inner(&self) -> Option<BendIndex> {
|
||||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_outer())
|
.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))
|
.map(|ni| BendIndex::new(ni))
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outer(&self) -> Option<BendIndex> {
|
pub fn outer(&self) -> Option<BendIndex> {
|
||||||
self.graph.neighbors_directed(self.index.index, Outgoing)
|
self.graph
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_outer())
|
.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))
|
.map(|ni| BendIndex::new(ni))
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/rules.rs
17
src/rules.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub struct Conditions {
|
pub struct Conditions {
|
||||||
pub lower_net: Option<i32>,
|
pub lower_net: Option<i32>,
|
||||||
pub higher_net: Option<i32>,
|
pub higher_net: Option<i32>,
|
||||||
|
|
@ -28,12 +28,15 @@ impl Rules {
|
||||||
let mut me = Self {
|
let mut me = Self {
|
||||||
rulesets: Default::default(),
|
rulesets: Default::default(),
|
||||||
};
|
};
|
||||||
me.rulesets[0] = Some(HashMap::from([(Conditions {
|
me.rulesets[0] = Some(HashMap::from([(
|
||||||
lower_net: None,
|
Conditions {
|
||||||
higher_net: None,
|
lower_net: None,
|
||||||
layer: None,
|
higher_net: None,
|
||||||
zone: None,
|
layer: None,
|
||||||
}, Ruleset::new())]));
|
zone: None,
|
||||||
|
},
|
||||||
|
Ruleset::new(),
|
||||||
|
)]));
|
||||||
me
|
me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
108
src/shape.rs
108
src/shape.rs
|
|
@ -1,17 +1,17 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use geo::{Point, EuclideanDistance, point, Polygon, Rotate, polygon, Intersects};
|
use geo::{point, polygon, EuclideanDistance, Intersects, Point, Polygon, Rotate};
|
||||||
use rstar::{RTreeObject, AABB};
|
use rstar::{RTreeObject, AABB};
|
||||||
|
|
||||||
use crate::graph::{TaggedWeight, DotWeight};
|
use crate::graph::{DotWeight, TaggedWeight};
|
||||||
use crate::math::{Circle, self};
|
use crate::math::{self, Circle};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct DotShape {
|
pub struct DotShape {
|
||||||
pub c: Circle,
|
pub c: Circle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct SegShape {
|
pub struct SegShape {
|
||||||
pub from: Point,
|
pub from: Point,
|
||||||
pub to: Point,
|
pub to: Point,
|
||||||
|
|
@ -26,16 +26,16 @@ impl SegShape {
|
||||||
|
|
||||||
let normal = unit_tangent_vector.rotate_around_point(-90., point! {x: 0., y: 0.});
|
let normal = unit_tangent_vector.rotate_around_point(-90., point! {x: 0., y: 0.});
|
||||||
|
|
||||||
let p1 = self.from - normal * self.width;
|
let p1 = self.from - normal * (self.width / 2.);
|
||||||
let p2 = self.from + normal * self.width;
|
let p2 = self.from + normal * (self.width / 2.);
|
||||||
let p3 = self.to + normal * self.width;
|
let p3 = self.to + normal * (self.width / 2.);
|
||||||
let p4 = self.to - normal * self.width;
|
let p4 = self.to - normal * (self.width / 2.);
|
||||||
|
|
||||||
polygon![p1.0, p2.0, p3.0, p4.0]
|
polygon![p1.0, p2.0, p3.0, p4.0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct BendShape {
|
pub struct BendShape {
|
||||||
pub from: Point,
|
pub from: Point,
|
||||||
pub to: Point,
|
pub to: Point,
|
||||||
|
|
@ -90,72 +90,74 @@ impl Shape {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Shape::Dot(dot) => {
|
Shape::Dot(dot) => match other {
|
||||||
match other {
|
Shape::Dot(other) => {
|
||||||
Shape::Dot(other) => {
|
dot.c.pos.euclidean_distance(&other.c.pos) < dot.c.r + other.c.r
|
||||||
dot.c.pos.euclidean_distance(&other.c.pos) < dot.c.r + other.c.r
|
}
|
||||||
},
|
Shape::Seg(other) => dot.c.pos.euclidean_distance(&other.polygon()) < dot.c.r,
|
||||||
Shape::Seg(other) => {
|
Shape::Bend(other) => {
|
||||||
dot.c.pos.euclidean_distance(&other.polygon()) < dot.c.r
|
for point in math::circles_intersection(&dot.c, &other.inner_circle()) {
|
||||||
},
|
if !math::between_vectors(
|
||||||
Shape::Bend(other) => {
|
point - other.center,
|
||||||
for point in math::circles_intersection(&dot.c, &other.inner_circle()) {
|
other.from - other.center,
|
||||||
if !math::between_vectors(point - other.center,
|
other.to - other.center,
|
||||||
other.from - other.center,
|
) {
|
||||||
other.to - other.center) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for point in math::circles_intersection(&dot.c, &other.outer_circle()) {
|
for point in math::circles_intersection(&dot.c, &other.outer_circle()) {
|
||||||
if !math::between_vectors(point - other.center,
|
if !math::between_vectors(
|
||||||
other.from - other.center,
|
point - other.center,
|
||||||
other.to - other.center) {
|
other.from - other.center,
|
||||||
return false;
|
other.to - other.center,
|
||||||
}
|
) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Shape::Seg(seg) => {
|
Shape::Seg(seg) => {
|
||||||
match other {
|
match other {
|
||||||
Shape::Dot(..) => unreachable!(),
|
Shape::Dot(..) => unreachable!(),
|
||||||
Shape::Seg(other) => {
|
Shape::Seg(other) => seg.polygon().intersects(&other.polygon()),
|
||||||
seg.polygon().intersects(&other.polygon())
|
|
||||||
},
|
|
||||||
Shape::Bend(other) => {
|
Shape::Bend(other) => {
|
||||||
false // TODO.
|
false // TODO.
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Shape::Bend(bend) => {
|
Shape::Bend(bend) => {
|
||||||
match other {
|
match other {
|
||||||
Shape::Dot(..) | Shape::Seg(..) => unreachable!(),
|
Shape::Dot(..) | Shape::Seg(..) => unreachable!(),
|
||||||
Shape::Bend(other) => {
|
Shape::Bend(other) => {
|
||||||
false // TODO.
|
false // TODO.
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn envelope(&self) -> AABB<[f64; 2]> {
|
pub fn envelope(&self) -> AABB<[f64; 2]> {
|
||||||
match self {
|
match self {
|
||||||
Shape::Dot(dot) =>
|
Shape::Dot(dot) => AABB::from_corners(
|
||||||
AABB::from_corners(
|
[dot.c.pos.x() - dot.c.r, dot.c.pos.y() - dot.c.r],
|
||||||
[dot.c.pos.x() - dot.c.r, dot.c.pos.y() - dot.c.r],
|
[dot.c.pos.x() + dot.c.r, dot.c.pos.y() + dot.c.r],
|
||||||
[dot.c.pos.x() + dot.c.r, dot.c.pos.y() + dot.c.r],
|
),
|
||||||
),
|
Shape::Seg(seg) => {
|
||||||
Shape::Seg(seg) =>
|
let points: Vec<[f64; 2]> = seg
|
||||||
AABB::<[f64; 2]>::from_points(&[[seg.from.x(), seg.from.y()],
|
.polygon()
|
||||||
[seg.to.x(), seg.to.y()]]),
|
.exterior()
|
||||||
Shape::Bend(bend) =>
|
.points()
|
||||||
AABB::<[f64; 2]>::from_points(&[[bend.from.x() - bend.width,
|
.map(|p| [p.x(), p.y()])
|
||||||
bend.from.y() - bend.width],
|
.collect();
|
||||||
[bend.to.x() + bend.width,
|
AABB::<[f64; 2]>::from_points(points.iter())
|
||||||
bend.to.y() + bend.width]]),
|
}
|
||||||
|
Shape::Bend(bend) => AABB::<[f64; 2]>::from_points(&[
|
||||||
|
[bend.from.x() - bend.width, bend.from.y() - bend.width],
|
||||||
|
[bend.to.x() + bend.width, bend.to.y() + bend.width],
|
||||||
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue