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 crate::primitive::{Dot, Seg, Bend};
|
||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, TaggedWeight, Label, Path};
|
||||
use crate::graph::{BendIndex, DotIndex, Label, Path, SegIndex, TaggedIndex, TaggedWeight};
|
||||
use crate::primitive::{Bend, Dot, Seg};
|
||||
|
||||
pub struct Bow<'a> {
|
||||
seg1_dot1: DotIndex,
|
||||
|
|
@ -43,11 +43,9 @@ impl<'a> Path for Bow<'a> {
|
|||
fn interior(&self) -> Vec<TaggedIndex> {
|
||||
vec![
|
||||
TaggedIndex::Seg(self.seg1),
|
||||
|
||||
TaggedIndex::Dot(self.seg1_dot2),
|
||||
TaggedIndex::Bend(self.bend),
|
||||
TaggedIndex::Dot(self.seg2_dot1),
|
||||
|
||||
TaggedIndex::Seg(self.seg2),
|
||||
]
|
||||
}
|
||||
|
|
@ -56,11 +54,9 @@ impl<'a> Path for Bow<'a> {
|
|||
vec![
|
||||
TaggedIndex::Dot(self.seg1_dot1),
|
||||
TaggedIndex::Seg(self.seg1),
|
||||
|
||||
TaggedIndex::Dot(self.seg1_dot2),
|
||||
TaggedIndex::Bend(self.bend),
|
||||
TaggedIndex::Dot(self.seg2_dot1),
|
||||
|
||||
TaggedIndex::Seg(self.seg2),
|
||||
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 petgraph::stable_graph::NodeIndex;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::math::Circle;
|
||||
|
||||
|
|
@ -42,14 +42,14 @@ pub enum Label {
|
|||
Core,
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumAsInner, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
|
||||
pub enum TaggedIndex {
|
||||
Dot(DotIndex),
|
||||
Seg(SegIndex),
|
||||
Bend(BendIndex),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Index<T> {
|
||||
pub index: NodeIndex<usize>,
|
||||
marker: PhantomData<T>,
|
||||
|
|
@ -65,12 +65,18 @@ impl<T> Index<T> {
|
|||
|
||||
pub fn retag(&self, weight: TaggedWeight) -> TaggedIndex {
|
||||
match weight {
|
||||
TaggedWeight::Dot(..) =>
|
||||
TaggedIndex::Dot(DotIndex {index: self.index, marker: PhantomData}),
|
||||
TaggedWeight::Seg(..) =>
|
||||
TaggedIndex::Seg(SegIndex {index: self.index, marker: PhantomData}),
|
||||
TaggedWeight::Bend(..) =>
|
||||
TaggedIndex::Bend(BendIndex {index: self.index, marker: PhantomData}),
|
||||
TaggedWeight::Dot(..) => TaggedIndex::Dot(DotIndex {
|
||||
index: self.index,
|
||||
marker: PhantomData,
|
||||
}),
|
||||
TaggedWeight::Seg(..) => TaggedIndex::Seg(SegIndex {
|
||||
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::Bend($index) => $expr,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub type DotIndex = Index<DotWeight>;
|
||||
|
|
|
|||
194
src/layout.rs
194
src/layout.rs
|
|
@ -1,14 +1,14 @@
|
|||
use std::cell::{RefCell, Ref};
|
||||
use std::rc::Rc;
|
||||
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::mesh::Mesh;
|
||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, Path};
|
||||
use crate::rules::{Rules, Conditions};
|
||||
use crate::rules::{Conditions, Rules};
|
||||
use crate::shape::Shape;
|
||||
use crate::graph::{TaggedWeight, DotWeight, SegWeight, BendWeight};
|
||||
use crate::math;
|
||||
|
||||
pub struct Layout {
|
||||
mesh: Mesh,
|
||||
|
|
@ -29,18 +29,21 @@ impl Layout {
|
|||
}
|
||||
|
||||
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() {
|
||||
self.route_finish_in_bend(head, bend, to, width);
|
||||
self.route_finish_in_bend(head, bend, to, width)
|
||||
} 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 conditions = Conditions {
|
||||
|
|
@ -58,11 +61,18 @@ impl Layout {
|
|||
let from_cw = self.head_cw(&head);
|
||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None);
|
||||
|
||||
let head = self.extend_head(head, tangent_points.0);
|
||||
self.add_seg(head.dot, to, width);
|
||||
let head = self.extend_head(head, tangent_points.0)?;
|
||||
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 conditions = Conditions {
|
||||
|
|
@ -75,26 +85,42 @@ impl Layout {
|
|||
let to_circle = self.bend_circle(to_bend, width);
|
||||
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 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);
|
||||
self.add_seg(head.dot, to, width);
|
||||
let to_head = self.extend_head(to_head, tangent_points.1)?;
|
||||
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 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.reroute_outward(outer);
|
||||
head
|
||||
self.reroute_outward(outer)?;
|
||||
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 conditions = Conditions {
|
||||
|
|
@ -109,20 +135,32 @@ impl Layout {
|
|||
let from_cw = self.head_cw(&head);
|
||||
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)
|
||||
}
|
||||
|
||||
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 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.reroute_outward(outer);
|
||||
head
|
||||
self.reroute_outward(outer)?;
|
||||
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 conditions = Conditions {
|
||||
|
|
@ -137,20 +175,32 @@ impl Layout {
|
|||
let from_cw = self.head_cw(&head);
|
||||
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)
|
||||
}
|
||||
|
||||
fn route_seg_bend(&mut self, head: Head, around: TaggedIndex, to: Point, cw: bool, width: f64) -> Head {
|
||||
let head = self.route_seg(head, to, width);
|
||||
let bend_to = self.add_dot(self.mesh.primitive(head.dot).weight());
|
||||
fn route_seg_bend(
|
||||
&mut self,
|
||||
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 bend = self.mesh.add_bend(head.dot, bend_to, around, BendWeight {net, cw});
|
||||
Head {dot: bend_to, bend: Some(bend)}
|
||||
let bend = self
|
||||
.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 interiors: Vec<Vec<TaggedIndex>> = vec![];
|
||||
let cw = self.mesh.primitive(bend).weight().cw;
|
||||
|
|
@ -179,34 +229,42 @@ impl Layout {
|
|||
let width = 5.0;
|
||||
|
||||
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 {
|
||||
head = self.route_around_dot(head, core, cw, width);
|
||||
head = self.route_around_dot(head, core, cw, width)?;
|
||||
}
|
||||
|
||||
maybe_inner = head.bend;
|
||||
self.route_finish(head, ends[1], width);
|
||||
self.route_finish(head, ends[1], width)?;
|
||||
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;
|
||||
|
||||
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 {
|
||||
net,
|
||||
circle: Circle {pos: to, r: width / 2.0},
|
||||
});
|
||||
self.add_seg(head.dot, to_index, width);
|
||||
Head {dot: to_index, bend: None}
|
||||
circle: Circle {
|
||||
pos: to,
|
||||
r: width / 2.0,
|
||||
},
|
||||
})?;
|
||||
self.add_seg(head.dot, to_index, width)?;
|
||||
Ok(Head {
|
||||
dot: to_index,
|
||||
bend: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn relax_band(&mut self, bend: BendIndex) {
|
||||
let mut prev_bend = bend;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +273,7 @@ impl Layout {
|
|||
|
||||
let mut prev_bend = bend;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -230,15 +288,17 @@ impl Layout {
|
|||
self.mesh.remove_open_set(bow.interior());
|
||||
|
||||
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) {
|
||||
self.mesh.move_dot(dot, to);
|
||||
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> {
|
||||
self.mesh.move_dot(dot, to)?;
|
||||
|
||||
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 {
|
||||
|
|
@ -256,9 +316,13 @@ impl Layout {
|
|||
if let Some(inner) = self.mesh.primitive(bend).inner() {
|
||||
self.bend_guidecircle(inner, width, conditions)
|
||||
} else {
|
||||
self.dot_guidecircle(self.mesh.primitive(bend).core().unwrap(), width + 5.0, conditions)
|
||||
self.dot_guidecircle(
|
||||
self.mesh.primitive(bend).core().unwrap(),
|
||||
width + 5.0,
|
||||
conditions,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Circle {
|
||||
pos: self.mesh.primitive(head.dot).weight().circle.pos,
|
||||
r: 0.0,
|
||||
|
|
@ -290,7 +354,11 @@ impl Layout {
|
|||
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 {
|
||||
pos: core_circle.pos,
|
||||
r: core_circle.r + r + width + 5.0,
|
||||
|
|
@ -303,11 +371,11 @@ impl Layout {
|
|||
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 {
|
||||
self.extend_head_bend(head, to)
|
||||
} else {
|
||||
head
|
||||
Ok(head)
|
||||
// No assertion for now because we temporarily use floats.
|
||||
|
||||
//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 {
|
||||
self.mesh.extend_bend(head.bend.unwrap(), head.dot, to);
|
||||
head
|
||||
fn extend_head_bend(&mut self, head: Head, to: Point) -> Result<Head, ()> {
|
||||
self.mesh.extend_bend(head.bend.unwrap(), head.dot, to)?;
|
||||
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)
|
||||
}
|
||||
|
||||
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;
|
||||
self.mesh.add_seg(from, to, SegWeight { net, width })
|
||||
}
|
||||
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
268
src/main.rs
268
src/main.rs
|
|
@ -4,40 +4,42 @@ macro_rules! dbg_dot {
|
|||
($graph:expr) => {
|
||||
use petgraph::dot::Dot;
|
||||
println!("{:?}", Dot::new(&$graph));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_use] mod graph;
|
||||
mod layout;
|
||||
mod rules;
|
||||
mod mesh;
|
||||
#[macro_use]
|
||||
mod graph;
|
||||
mod bow;
|
||||
mod primitive;
|
||||
mod shape;
|
||||
mod layout;
|
||||
mod math;
|
||||
mod mesh;
|
||||
mod primitive;
|
||||
mod rules;
|
||||
mod shape;
|
||||
|
||||
use std::panic;
|
||||
use std::time::Duration;
|
||||
use geo::EuclideanDistance;
|
||||
use graph::{TaggedIndex, Tag};
|
||||
use sdl2::EventPump;
|
||||
use sdl2::pixels::Color;
|
||||
use graph::{Tag, TaggedIndex};
|
||||
use sdl2::event::Event;
|
||||
use sdl2::keyboard::Keycode;
|
||||
use sdl2::gfx::primitives::DrawRenderer;
|
||||
use sdl2::keyboard::Keycode;
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::render::Canvas;
|
||||
use sdl2::video::Window;
|
||||
use sdl2::EventPump;
|
||||
use shape::Shape;
|
||||
use std::panic;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::layout::Layout;
|
||||
use crate::graph::DotWeight;
|
||||
use crate::layout::Layout;
|
||||
use crate::math::Circle;
|
||||
|
||||
fn main() {
|
||||
let sdl_context = sdl2::init().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()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
|
@ -52,7 +54,6 @@ fn main() {
|
|||
let mut i = 0;
|
||||
let mut layout = Layout::new();
|
||||
|
||||
|
||||
/*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);
|
||||
|
||||
|
|
@ -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 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 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}});
|
||||
|
|
@ -103,86 +103,202 @@ fn main() {
|
|||
let head = layout.route_around_bend(head, bend2_2, true, 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 dot2_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 430.5).into(), r: 8.0}});
|
||||
let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 460.5).into(), r: 8.0}});
|
||||
let dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (190.5, 490.5).into(), r: 8.0}});
|
||||
let dot1_2 = layout
|
||||
.add_dot(DotWeight {
|
||||
net: 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 dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (670.5, 430.5).into(), r: 8.0}});
|
||||
let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (640.5, 460.5).into(), r: 8.0}});
|
||||
let dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (610.5, 490.5).into(), r: 8.0}});
|
||||
let barrier1_dot1 = layout
|
||||
.add_dot(DotWeight {
|
||||
net: 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 barrier1_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (250.5, 700.5).into(), r: 8.0}});
|
||||
layout.add_seg(barrier1_dot1, barrier1_dot2, 16.0);
|
||||
|
||||
let barrier2_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (450.5, 200.5).into(), r: 8.0}});
|
||||
let barrier2_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (450.5, 700.5).into(), r: 8.0}});
|
||||
layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0);
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||
let barrier2_dot1 = layout
|
||||
.add_dot(DotWeight {
|
||||
net: 0,
|
||||
circle: Circle {
|
||||
pos: (420.5, 200.5).into(),
|
||||
r: 8.0,
|
||||
},
|
||||
})
|
||||
.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_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);
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
let head = layout.route_start(dot3_1);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
let head = layout.route_start(dot4_1);
|
||||
|
||||
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);
|
||||
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);
|
||||
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, 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);
|
||||
}
|
||||
|
||||
fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout: &mut Layout,
|
||||
follower: Option<TaggedIndex>, times: i64)
|
||||
{
|
||||
fn render_times(
|
||||
event_pump: &mut EventPump,
|
||||
canvas: &mut Canvas<Window>,
|
||||
layout: &mut Layout,
|
||||
follower: Option<TaggedIndex>,
|
||||
times: i64,
|
||||
) {
|
||||
let mut i = 0;
|
||||
|
||||
'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() {
|
||||
match event {
|
||||
Event::Quit {..} |
|
||||
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
|
||||
break 'running
|
||||
}
|
||||
Event::Quit { .. }
|
||||
| Event::KeyDown {
|
||||
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 {
|
||||
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(|| {
|
||||
for shape in layout.shapes() {
|
||||
match shape {
|
||||
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.r as i16,
|
||||
Color::RGB(200, 52, 52));
|
||||
},
|
||||
Color::RGB(200, 52, 52),
|
||||
);
|
||||
}
|
||||
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.to.x() as i16,
|
||||
seg.to.y() as i16,
|
||||
seg.width as u8,
|
||||
Color::RGB(200, 52, 52));
|
||||
},
|
||||
Color::RGB(200, 52, 52),
|
||||
);
|
||||
}
|
||||
Shape::Bend(bend) => {
|
||||
let delta1 = bend.from - 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,
|
||||
angle1.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.upper()[0] as i16,
|
||||
envelope.upper()[1] as i16,
|
||||
|
||||
Color::RGB(100, 100, 100));*/
|
||||
Color::RGB(100, 100, 100),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
48
src/math.rs
48
src/math.rs
|
|
@ -1,5 +1,5 @@
|
|||
use geo::{geometry::Point, point, EuclideanDistance};
|
||||
use std::ops::Sub;
|
||||
use geo::{geometry::Point, EuclideanDistance, point};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Line {
|
||||
|
|
@ -19,7 +19,10 @@ impl Sub for Circle {
|
|||
|
||||
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: 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 {
|
||||
return (
|
||||
(line.b * (line.b * pt.x() - line.a * pt.y()) - line.a * line.c) / (line.a * line.a + line.b * line.b),
|
||||
(line.a * (-line.b * pt.x() + line.a * pt.y()) - line.b * line.c) / (line.a * line.a + line.b * line.b),
|
||||
).into();
|
||||
(line.b * (line.b * pt.x() - line.a * pt.y()) - line.a * line.c)
|
||||
/ (line.a * line.a + line.b * line.b),
|
||||
(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] {
|
||||
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[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])),
|
||||
(
|
||||
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[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);
|
||||
|
||||
for tangent_point_pair in tangent_point_pairs {
|
||||
|
|
@ -128,10 +151,7 @@ pub fn circles_intersection(circle1: &Circle, circle2: &Circle) -> Vec<Point> {
|
|||
|
||||
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 {
|
||||
|
|
|
|||
132
src/mesh.rs
132
src/mesh.rs
|
|
@ -1,14 +1,17 @@
|
|||
use geo::Point;
|
||||
use petgraph::Direction::Incoming;
|
||||
use petgraph::stable_graph::StableDiGraph;
|
||||
use petgraph::visit::EdgeRef;
|
||||
use rstar::RTree;
|
||||
use petgraph::Direction::Incoming;
|
||||
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::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>;
|
||||
|
||||
|
|
@ -47,55 +50,94 @@ impl Mesh {
|
|||
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)));
|
||||
self.rtree.insert(RTreeWrapper::new(self.primitive(dot).shape(), TaggedIndex::Dot(dot)));
|
||||
dot
|
||||
self.fail_and_remove_if_collides(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)));
|
||||
self.fail_and_remove_if_collides(seg)?;
|
||||
|
||||
self.graph.add_edge(from.index, seg.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)));
|
||||
seg
|
||||
self.insert_into_rtree(seg.tag());
|
||||
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 {
|
||||
TaggedIndex::Dot(core) =>
|
||||
self.add_core_bend(from, to, core, weight),
|
||||
TaggedIndex::Bend(around) =>
|
||||
self.add_outer_bend(from, to, around, weight),
|
||||
TaggedIndex::Dot(core) => self.add_core_bend(from, to, core, weight),
|
||||
TaggedIndex::Bend(around) => self.add_outer_bend(from, to, around, weight),
|
||||
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)));
|
||||
self.fail_and_remove_if_collides(bend)?;
|
||||
|
||||
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, core.index, Label::Core);
|
||||
|
||||
self.rtree.insert(RTreeWrapper::new(self.primitive(bend).shape(), TaggedIndex::Bend(bend)));
|
||||
bend
|
||||
self.insert_into_rtree(bend.tag());
|
||||
Ok(bend)
|
||||
}
|
||||
|
||||
pub fn add_outer_bend(&mut self, from: DotIndex, to: DotIndex, inner: BendIndex, weight: BendWeight) -> 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())
|
||||
pub fn add_outer_bend(
|
||||
&mut self,
|
||||
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))
|
||||
.collect::<Vec<DotIndex>>()
|
||||
.first()
|
||||
.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);
|
||||
bend
|
||||
Ok(bend)
|
||||
}
|
||||
|
||||
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)
|
||||
.next()
|
||||
{
|
||||
|
|
@ -104,13 +146,14 @@ impl Mesh {
|
|||
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.move_dot(dot, to);
|
||||
self.move_dot(dot, to)?;
|
||||
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();
|
||||
loop {
|
||||
match cur_bend {
|
||||
|
|
@ -119,15 +162,25 @@ impl Mesh {
|
|||
}
|
||||
|
||||
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());
|
||||
|
||||
let mut dot_weight = self.primitive(dot).weight();
|
||||
let old_weight = dot_weight;
|
||||
|
||||
dot_weight.circle.pos = to;
|
||||
*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());
|
||||
|
||||
let mut cur_bend = self.primitive(dot).outer();
|
||||
|
|
@ -138,8 +191,10 @@ impl Mesh {
|
|||
}
|
||||
|
||||
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> + '_ {
|
||||
|
|
@ -154,6 +209,25 @@ impl Mesh {
|
|||
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) {
|
||||
let shape = untag!(index, self.primitive(index).shape());
|
||||
self.rtree.insert(RTreeWrapper::new(shape, index));
|
||||
|
|
|
|||
137
src/primitive.rs
137
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::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::shape::{Shape, DotShape, SegShape, BendShape};
|
||||
use crate::shape::{BendShape, DotShape, SegShape, Shape};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Primitive<'a, Weight> {
|
||||
|
|
@ -20,9 +23,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
|
||||
pub fn shape(&self) -> Shape {
|
||||
match self.tagged_weight() {
|
||||
TaggedWeight::Dot(dot) => Shape::Dot(DotShape {
|
||||
c: dot.circle,
|
||||
}),
|
||||
TaggedWeight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }),
|
||||
TaggedWeight::Seg(seg) => {
|
||||
let ends = self.ends();
|
||||
Shape::Seg(SegShape {
|
||||
|
|
@ -30,7 +31,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
to: self.primitive(ends[1]).weight().circle.pos,
|
||||
width: seg.width,
|
||||
})
|
||||
},
|
||||
}
|
||||
TaggedWeight::Bend(bend) => {
|
||||
let ends = self.ends();
|
||||
let mut bend_shape = BendShape {
|
||||
|
|
@ -44,13 +45,19 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
swap(&mut bend_shape.from, &mut bend_shape.to);
|
||||
}
|
||||
Shape::Bend(bend_shape)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(&self) -> Option<TaggedIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Outgoing)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_end())
|
||||
self.graph
|
||||
.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()))
|
||||
.next()
|
||||
}
|
||||
|
|
@ -58,9 +65,16 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
pub fn next_akin(&self) -> Option<Index<Weight>> {
|
||||
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.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()
|
||||
{
|
||||
let weight = *self.graph.node_weight(index).unwrap();
|
||||
|
|
@ -76,8 +90,14 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
}
|
||||
|
||||
pub fn prev(&self) -> Option<TaggedIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_end())
|
||||
self.graph
|
||||
.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| {
|
||||
self.graph
|
||||
.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap())
|
||||
.unwrap()
|
||||
.is_end()
|
||||
})
|
||||
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
||||
.next()
|
||||
}
|
||||
|
|
@ -85,9 +105,16 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
pub fn prev_akin(&self) -> Option<Index<Weight>> {
|
||||
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.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()
|
||||
{
|
||||
let weight = *self.graph.node_weight(index).unwrap();
|
||||
|
|
@ -103,14 +130,21 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
}
|
||||
|
||||
pub fn core(&self) -> Option<DotIndex> {
|
||||
self.graph.neighbors(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core())
|
||||
self.graph
|
||||
.neighbors(self.index.index)
|
||||
.filter(|ni| {
|
||||
self.graph
|
||||
.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap())
|
||||
.unwrap()
|
||||
.is_core()
|
||||
})
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn tagged_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 {
|
||||
|
|
@ -128,7 +162,8 @@ impl<'a, Weight> Path for Primitive<'a, Weight> {
|
|||
}
|
||||
|
||||
fn closure(&self) -> Vec<TaggedIndex> {
|
||||
let ends: Vec<TaggedIndex> = self.ends()
|
||||
let ends: Vec<TaggedIndex> = self
|
||||
.ends()
|
||||
.into_iter()
|
||||
.map(|end| TaggedIndex::Dot(end))
|
||||
.collect();
|
||||
|
|
@ -136,8 +171,19 @@ impl<'a, Weight> Path for Primitive<'a, Weight> {
|
|||
}
|
||||
|
||||
fn ends(&self) -> [DotIndex; 2] {
|
||||
self.graph.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())
|
||||
self.graph
|
||||
.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())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.collect::<Vec<DotIndex>>()
|
||||
|
|
@ -152,16 +198,33 @@ pub type Bend<'a> = Primitive<'a, BendWeight>;
|
|||
|
||||
impl<'a> Dot<'a> {
|
||||
pub fn bend(&self) -> Option<BendIndex> {
|
||||
self.graph.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())
|
||||
self.graph
|
||||
.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())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn outer(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_core())
|
||||
self.graph
|
||||
.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| {
|
||||
self.graph
|
||||
.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap())
|
||||
.unwrap()
|
||||
.is_core()
|
||||
})
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.filter(|bend| self.primitive(*bend).inner().is_none())
|
||||
.next()
|
||||
|
|
@ -188,15 +251,27 @@ impl<'a> Bend<'a> {
|
|||
}
|
||||
|
||||
pub fn inner(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_outer())
|
||||
self.graph
|
||||
.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| {
|
||||
self.graph
|
||||
.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap())
|
||||
.unwrap()
|
||||
.is_outer()
|
||||
})
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn outer(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Outgoing)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_outer())
|
||||
self.graph
|
||||
.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))
|
||||
.next()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
pub struct Conditions {
|
||||
pub lower_net: Option<i32>,
|
||||
pub higher_net: Option<i32>,
|
||||
|
|
@ -28,12 +28,15 @@ impl Rules {
|
|||
let mut me = Self {
|
||||
rulesets: Default::default(),
|
||||
};
|
||||
me.rulesets[0] = Some(HashMap::from([(Conditions {
|
||||
me.rulesets[0] = Some(HashMap::from([(
|
||||
Conditions {
|
||||
lower_net: None,
|
||||
higher_net: None,
|
||||
layer: None,
|
||||
zone: None,
|
||||
}, Ruleset::new())]));
|
||||
},
|
||||
Ruleset::new(),
|
||||
)]));
|
||||
me
|
||||
}
|
||||
|
||||
|
|
|
|||
78
src/shape.rs
78
src/shape.rs
|
|
@ -1,17 +1,17 @@
|
|||
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 crate::graph::{TaggedWeight, DotWeight};
|
||||
use crate::math::{Circle, self};
|
||||
use crate::graph::{DotWeight, TaggedWeight};
|
||||
use crate::math::{self, Circle};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct DotShape {
|
||||
pub c: Circle,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct SegShape {
|
||||
pub from: 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 p1 = self.from - normal * self.width;
|
||||
let p2 = self.from + normal * self.width;
|
||||
let p3 = self.to + normal * self.width;
|
||||
let p4 = self.to - normal * self.width;
|
||||
let p1 = self.from - normal * (self.width / 2.);
|
||||
let p2 = self.from + normal * (self.width / 2.);
|
||||
let p3 = self.to + normal * (self.width / 2.);
|
||||
let p4 = self.to - normal * (self.width / 2.);
|
||||
|
||||
polygon![p1.0, p2.0, p3.0, p4.0]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct BendShape {
|
||||
pub from: Point,
|
||||
pub to: Point,
|
||||
|
|
@ -90,72 +90,74 @@ impl Shape {
|
|||
}
|
||||
|
||||
match self {
|
||||
Shape::Dot(dot) => {
|
||||
match other {
|
||||
Shape::Dot(dot) => match other {
|
||||
Shape::Dot(other) => {
|
||||
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) => dot.c.pos.euclidean_distance(&other.polygon()) < dot.c.r,
|
||||
Shape::Bend(other) => {
|
||||
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.to - other.center) {
|
||||
other.to - other.center,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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.to - other.center) {
|
||||
other.to - other.center,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
},
|
||||
}
|
||||
},
|
||||
Shape::Seg(seg) => {
|
||||
match other {
|
||||
Shape::Dot(..) => unreachable!(),
|
||||
Shape::Seg(other) => {
|
||||
seg.polygon().intersects(&other.polygon())
|
||||
},
|
||||
Shape::Seg(other) => seg.polygon().intersects(&other.polygon()),
|
||||
Shape::Bend(other) => {
|
||||
false // TODO.
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Shape::Bend(bend) => {
|
||||
match other {
|
||||
Shape::Dot(..) | Shape::Seg(..) => unreachable!(),
|
||||
Shape::Bend(other) => {
|
||||
false // TODO.
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn envelope(&self) -> AABB<[f64; 2]> {
|
||||
match self {
|
||||
Shape::Dot(dot) =>
|
||||
AABB::from_corners(
|
||||
Shape::Dot(dot) => 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],
|
||||
),
|
||||
Shape::Seg(seg) =>
|
||||
AABB::<[f64; 2]>::from_points(&[[seg.from.x(), seg.from.y()],
|
||||
[seg.to.x(), seg.to.y()]]),
|
||||
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]]),
|
||||
Shape::Seg(seg) => {
|
||||
let points: Vec<[f64; 2]> = seg
|
||||
.polygon()
|
||||
.exterior()
|
||||
.points()
|
||||
.map(|p| [p.x(), p.y()])
|
||||
.collect();
|
||||
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],
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue