Implement basic failure for moving dot to obstructed place

Intersection with bends isn't working yet.
This commit is contained in:
Mikolaj Wielgus 2023-08-15 04:04:08 +02:00
parent c2a553c475
commit 1a599951cd
9 changed files with 681 additions and 309 deletions

View File

@ -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),
] ]

View File

@ -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>;

View File

@ -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,18 +29,21 @@ 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) { pub fn route_finish(&mut self, head: Head, to: DotIndex, width: f64) -> Result<(), ()> {
if let Some(bend) = self.mesh.primitive(to).bend() { if let Some(bend) = self.mesh.primitive(to).bend() {
self.route_finish_in_bend(head, bend, to, width); self.route_finish_in_bend(head, bend, to, width)
} else { } else {
self.route_finish_in_dot(head, to, width); self.route_finish_in_dot(head, to, width)
} }
} }
fn route_finish_in_dot(&mut self, head: Head, to: DotIndex, width: f64) { 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 {
@ -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,20 +135,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::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 {
@ -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,34 +229,42 @@ 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);
} }
@ -215,7 +273,7 @@ impl Layout {
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()))
} }
} }

View File

@ -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.x() as i16,
dot.c.pos.y() as i16, dot.c.pos.y() as i16,
dot.c.r as i16, dot.c.r as i16,
Color::RGB(200, 52, 52)); 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.x() as i16,
seg.from.y() as i16, seg.from.y() as i16,
seg.to.x() as i16, seg.to.x() as i16,
seg.to.y() as i16, seg.to.y() as i16,
seg.width as u8, seg.width as u8,
Color::RGB(200, 52, 52)); 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 _ = canvas.rectangle(envelope.lower()[0] as i16, let envelope = shape.envelope();
let _ = canvas.rectangle(
envelope.lower()[0] as i16,
envelope.lower()[1] as i16, envelope.lower()[1] as i16,
envelope.upper()[0] as i16, envelope.upper()[0] as i16,
envelope.upper()[1] as i16, envelope.upper()[1] as i16,
Color::RGB(100, 100, 100),
Color::RGB(100, 100, 100));*/ );
} }
}); });

View File

@ -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 {

View File

@ -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>;
@ -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();
}
} }
pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ { Ok(())
}
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));

View File

@ -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()
} }

View File

@ -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([(
Conditions {
lower_net: None, lower_net: None,
higher_net: None, higher_net: None,
layer: None, layer: None,
zone: None, zone: None,
}, Ruleset::new())])); },
Ruleset::new(),
)]));
me me
} }

View File

@ -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) => { Shape::Seg(other) => dot.c.pos.euclidean_distance(&other.polygon()) < dot.c.r,
dot.c.pos.euclidean_distance(&other.polygon()) < dot.c.r
},
Shape::Bend(other) => { Shape::Bend(other) => {
for point in math::circles_intersection(&dot.c, &other.inner_circle()) { for point in math::circles_intersection(&dot.c, &other.inner_circle()) {
if !math::between_vectors(point - other.center, if !math::between_vectors(
point - other.center,
other.from - other.center, other.from - other.center,
other.to - 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(
point - other.center,
other.from - other.center, other.from - other.center,
other.to - other.center) { other.to - other.center,
) {
return false; 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) => {
AABB::<[f64; 2]>::from_points(&[[seg.from.x(), seg.from.y()], let points: Vec<[f64; 2]> = seg
[seg.to.x(), seg.to.y()]]), .polygon()
Shape::Bend(bend) => .exterior()
AABB::<[f64; 2]>::from_points(&[[bend.from.x() - bend.width, .points()
bend.from.y() - bend.width], .map(|p| [p.x(), p.y()])
[bend.to.x() + bend.width, .collect();
bend.to.y() + bend.width]]), AABB::<[f64; 2]>::from_points(points.iter())
}
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],
]),
} }
} }