mirror of https://codeberg.org/topola/topola.git
shape: Use `enum_dispatch` for `Shape`
This commit is contained in:
parent
26778e7d47
commit
b7ff507302
|
|
@ -12,11 +12,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[enum_dispatch]
|
#[enum_dispatch]
|
||||||
pub trait HeadDot {
|
pub trait HeadTrait {
|
||||||
fn dot(&self) -> DotIndex;
|
fn dot(&self) -> DotIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[enum_dispatch(HeadDot)]
|
#[enum_dispatch(HeadTrait)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Head {
|
pub enum Head {
|
||||||
Bare(BareHead),
|
Bare(BareHead),
|
||||||
|
|
@ -28,7 +28,7 @@ pub struct BareHead {
|
||||||
pub dot: DotIndex,
|
pub dot: DotIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeadDot for BareHead {
|
impl HeadTrait for BareHead {
|
||||||
fn dot(&self) -> DotIndex {
|
fn dot(&self) -> DotIndex {
|
||||||
self.dot
|
self.dot
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ pub struct SegbendHead {
|
||||||
pub segbend: Segbend,
|
pub segbend: Segbend,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeadDot for SegbendHead {
|
impl HeadTrait for SegbendHead {
|
||||||
fn dot(&self) -> DotIndex {
|
fn dot(&self) -> DotIndex {
|
||||||
self.dot
|
self.dot
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use geo::Line;
|
use geo::Line;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
draw::{Head, HeadDot, SegbendHead},
|
draw::{Head, HeadTrait, SegbendHead},
|
||||||
graph::{BendIndex, DotIndex},
|
graph::{BendIndex, DotIndex},
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
math::{self, Circle},
|
math::{self, Circle},
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use petgraph::stable_graph::StableDiGraph;
|
||||||
use petgraph::visit::EdgeRef;
|
use petgraph::visit::EdgeRef;
|
||||||
use petgraph::Direction::Incoming;
|
use petgraph::Direction::Incoming;
|
||||||
use rstar::primitives::GeomWithData;
|
use rstar::primitives::GeomWithData;
|
||||||
use rstar::RTree;
|
use rstar::{RTree, RTreeObject};
|
||||||
use spade::Triangulation;
|
use spade::Triangulation;
|
||||||
|
|
||||||
use crate::band::Band;
|
use crate::band::Band;
|
||||||
|
|
@ -15,7 +15,7 @@ use crate::graph::{
|
||||||
};
|
};
|
||||||
use crate::primitive::Primitive;
|
use crate::primitive::Primitive;
|
||||||
use crate::segbend::Segbend;
|
use crate::segbend::Segbend;
|
||||||
use crate::shape::Shape;
|
use crate::shape::{Shape, ShapeTrait};
|
||||||
|
|
||||||
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ impl Layout {
|
||||||
let shape = primitive.shape();
|
let shape = primitive.shape();
|
||||||
|
|
||||||
self.rtree
|
self.rtree
|
||||||
.locate_in_envelope_intersecting(&shape.envelope())
|
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
|
||||||
.filter(|wrapper| {
|
.filter(|wrapper| {
|
||||||
let other_index = wrapper.data;
|
let other_index = wrapper.data;
|
||||||
!untag!(other_index, primitive.connectable(other_index))
|
!untag!(other_index, primitive.connectable(other_index))
|
||||||
|
|
@ -358,7 +358,7 @@ impl Layout {
|
||||||
let wrapper = RTreeWrapper::new(shape, index);
|
let wrapper = RTreeWrapper::new(shape, index);
|
||||||
!self
|
!self
|
||||||
.rtree
|
.rtree
|
||||||
.locate_in_envelope(&shape.envelope())
|
.locate_in_envelope(&RTreeObject::envelope(&shape))
|
||||||
.any(|w| *w == wrapper)
|
.any(|w| *w == wrapper)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
src/main.rs
29
src/main.rs
|
|
@ -30,6 +30,7 @@ use layout::Layout;
|
||||||
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
||||||
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
||||||
use router::RouterObserver;
|
use router::RouterObserver;
|
||||||
|
use rstar::RTreeObject;
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
use sdl2::gfx::primitives::DrawRenderer;
|
use sdl2::gfx::primitives::DrawRenderer;
|
||||||
use sdl2::keyboard::Keycode;
|
use sdl2::keyboard::Keycode;
|
||||||
|
|
@ -68,7 +69,7 @@ impl<'a> DebugRouterObserver<'a> {
|
||||||
|
|
||||||
impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) {
|
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) {
|
||||||
/*render_times(
|
render_times(
|
||||||
self.event_pump,
|
self.event_pump,
|
||||||
self.canvas,
|
self.canvas,
|
||||||
RouterOrLayout::Layout(tracer.layout),
|
RouterOrLayout::Layout(tracer.layout),
|
||||||
|
|
@ -77,13 +78,13 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
Some(tracer.mesh.clone()),
|
Some(tracer.mesh.clone()),
|
||||||
&trace.path,
|
&trace.path,
|
||||||
20,
|
20,
|
||||||
);*/
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {
|
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {
|
||||||
let mut path = trace.path.clone();
|
let mut path = trace.path.clone();
|
||||||
path.push(edge.target());
|
path.push(edge.target());
|
||||||
/*render_times(
|
render_times(
|
||||||
self.event_pump,
|
self.event_pump,
|
||||||
self.canvas,
|
self.canvas,
|
||||||
RouterOrLayout::Layout(tracer.layout),
|
RouterOrLayout::Layout(tracer.layout),
|
||||||
|
|
@ -92,11 +93,11 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
Some(tracer.mesh.clone()),
|
Some(tracer.mesh.clone()),
|
||||||
&path,
|
&path,
|
||||||
5,
|
5,
|
||||||
);*/
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {
|
fn on_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {
|
||||||
/*render_times(
|
render_times(
|
||||||
self.event_pump,
|
self.event_pump,
|
||||||
self.canvas,
|
self.canvas,
|
||||||
RouterOrLayout::Layout(tracer.layout),
|
RouterOrLayout::Layout(tracer.layout),
|
||||||
|
|
@ -105,7 +106,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
Some(tracer.mesh.clone()),
|
Some(tracer.mesh.clone()),
|
||||||
&trace.path,
|
&trace.path,
|
||||||
5,
|
5,
|
||||||
);*/
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
|
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
|
||||||
|
|
@ -335,7 +336,7 @@ fn main() {
|
||||||
},
|
},
|
||||||
);*/
|
);*/
|
||||||
|
|
||||||
render_times(
|
/*render_times(
|
||||||
&mut event_pump,
|
&mut event_pump,
|
||||||
&mut canvas,
|
&mut canvas,
|
||||||
RouterOrLayout::Layout(&router.layout),
|
RouterOrLayout::Layout(&router.layout),
|
||||||
|
|
@ -355,6 +356,12 @@ fn main() {
|
||||||
None,
|
None,
|
||||||
&[],
|
&[],
|
||||||
-1,
|
-1,
|
||||||
|
);*/
|
||||||
|
|
||||||
|
let _ = router.enroute(
|
||||||
|
dot1,
|
||||||
|
dot_end,
|
||||||
|
&mut DebugRouterObserver::new(&mut event_pump, &mut canvas),
|
||||||
);
|
);
|
||||||
|
|
||||||
render_times(
|
render_times(
|
||||||
|
|
@ -486,17 +493,17 @@ fn render_times(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*let envelope = shape.envelope();
|
let envelope = shape.envelope();
|
||||||
let _ = canvas.rectangle(
|
let _ = canvas.rectangle(
|
||||||
envelope.lower()[0] as i16,
|
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),
|
||||||
);*/
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if let Some(ref mesh) = mesh {
|
if let Some(ref mesh) = mesh {
|
||||||
for edge in mesh.edge_references() {
|
for edge in mesh.edge_references() {
|
||||||
let endpoints = (mesh.position(edge.source()), mesh.position(edge.target()));
|
let endpoints = (mesh.position(edge.source()), mesh.position(edge.target()));
|
||||||
|
|
||||||
|
|
@ -514,7 +521,7 @@ fn render_times(
|
||||||
color,
|
color,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
//});
|
//});
|
||||||
|
|
||||||
canvas.present();
|
canvas.present();
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,12 @@ use spade::{
|
||||||
DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation,
|
DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::shape::ShapeTrait;
|
||||||
use crate::{graph::DotIndex, layout::Layout};
|
use crate::{graph::DotIndex, layout::Layout};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
pub dot: DotIndex,
|
dot: DotIndex,
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use crate::graph::{
|
||||||
TaggedIndex, TaggedWeight,
|
TaggedIndex, TaggedWeight,
|
||||||
};
|
};
|
||||||
use crate::math::{self, Circle};
|
use crate::math::{self, Circle};
|
||||||
use crate::shape::{BendShape, DotShape, SegShape, Shape};
|
use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Primitive<'a, Weight> {
|
pub struct Primitive<'a, Weight> {
|
||||||
|
|
|
||||||
296
src/shape.rs
296
src/shape.rs
|
|
@ -1,14 +1,80 @@
|
||||||
use enum_as_inner::EnumAsInner;
|
use enum_as_inner::EnumAsInner;
|
||||||
|
use enum_dispatch::enum_dispatch;
|
||||||
use geo::{point, polygon, EuclideanDistance, Intersects, Point, Polygon, Rotate};
|
use geo::{point, polygon, EuclideanDistance, Intersects, Point, Polygon, Rotate};
|
||||||
use rstar::{RTreeObject, AABB};
|
use rstar::{RTreeObject, AABB};
|
||||||
|
|
||||||
use crate::math::{self, Circle};
|
use crate::math::{self, Circle};
|
||||||
|
|
||||||
|
#[enum_dispatch]
|
||||||
|
pub trait ShapeTrait {
|
||||||
|
fn priority(&self) -> u64;
|
||||||
|
fn center(&self) -> Point;
|
||||||
|
fn intersects(&self, other: &Shape) -> bool;
|
||||||
|
fn envelope(&self) -> AABB<[f64; 2]>;
|
||||||
|
fn width(&self) -> f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[enum_dispatch(ShapeTrait)]
|
||||||
|
#[derive(Debug, Clone, Copy, EnumAsInner, PartialEq)]
|
||||||
|
pub enum Shape {
|
||||||
|
// Intentionally in different order to reorder `self.intersects(...)` properly.
|
||||||
|
Dot(DotShape),
|
||||||
|
Seg(SegShape),
|
||||||
|
Bend(BendShape),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct DotShape {
|
pub struct DotShape {
|
||||||
pub c: Circle,
|
pub c: Circle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShapeTrait for DotShape {
|
||||||
|
fn priority(&self) -> u64 {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn center(&self) -> Point {
|
||||||
|
self.c.pos
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersects(&self, other: &Shape) -> bool {
|
||||||
|
if self.priority() < other.priority() {
|
||||||
|
return other.intersects(&Shape::from(*self));
|
||||||
|
}
|
||||||
|
|
||||||
|
match other {
|
||||||
|
Shape::Dot(other) => self.c.pos.euclidean_distance(&other.c.pos) < self.c.r + other.c.r,
|
||||||
|
Shape::Seg(other) => self.c.pos.euclidean_distance(&other.polygon()) < self.c.r,
|
||||||
|
Shape::Bend(other) => {
|
||||||
|
for point in math::intersect_circles(&self.c, &other.inner_circle()) {
|
||||||
|
if other.between_ends(point) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for point in math::intersect_circles(&self.c, &other.outer_circle()) {
|
||||||
|
if other.between_ends(point) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn envelope(&self) -> AABB<[f64; 2]> {
|
||||||
|
AABB::from_corners(
|
||||||
|
[self.c.pos.x() - self.c.r, self.c.pos.y() - self.c.r],
|
||||||
|
[self.c.pos.x() + self.c.r, self.c.pos.y() + self.c.r],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(&self) -> f64 {
|
||||||
|
self.c.r * 2.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct SegShape {
|
pub struct SegShape {
|
||||||
pub from: Point,
|
pub from: Point,
|
||||||
|
|
@ -33,6 +99,61 @@ impl SegShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ShapeTrait for SegShape {
|
||||||
|
fn priority(&self) -> u64 {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn center(&self) -> Point {
|
||||||
|
(self.from + self.to) / 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersects(&self, other: &Shape) -> bool {
|
||||||
|
if self.priority() < other.priority() {
|
||||||
|
return other.intersects(&Shape::from(*self));
|
||||||
|
}
|
||||||
|
|
||||||
|
match other {
|
||||||
|
Shape::Dot(..) => unreachable!(),
|
||||||
|
Shape::Seg(other) => self.polygon().intersects(&other.polygon()),
|
||||||
|
Shape::Bend(other) => {
|
||||||
|
for segment in self.polygon().exterior().lines() {
|
||||||
|
let inner_circle = other.inner_circle();
|
||||||
|
let outer_circle = other.outer_circle();
|
||||||
|
|
||||||
|
for point in math::intersect_circle_segment(&inner_circle, &segment) {
|
||||||
|
if other.between_ends(point) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for point in math::intersect_circle_segment(&outer_circle, &segment) {
|
||||||
|
if other.between_ends(point) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn envelope(&self) -> AABB<[f64; 2]> {
|
||||||
|
let points: Vec<[f64; 2]> = self
|
||||||
|
.polygon()
|
||||||
|
.exterior()
|
||||||
|
.points()
|
||||||
|
.map(|p| [p.x(), p.y()])
|
||||||
|
.collect();
|
||||||
|
AABB::<[f64; 2]>::from_points(points.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(&self) -> f64 {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct BendShape {
|
pub struct BendShape {
|
||||||
pub from: Point,
|
pub from: Point,
|
||||||
|
|
@ -69,172 +190,69 @@ impl BendShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use enum_dispatch.
|
impl ShapeTrait for BendShape {
|
||||||
#[derive(Debug, Clone, Copy, EnumAsInner, PartialEq)]
|
fn priority(&self) -> u64 {
|
||||||
pub enum Shape {
|
1
|
||||||
// Intentionally in different order to reorder `self.intersects(...)` properly.
|
|
||||||
Dot(DotShape),
|
|
||||||
Seg(SegShape),
|
|
||||||
Bend(BendShape),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Shape {
|
|
||||||
pub fn principal_point(&self) -> Point {
|
|
||||||
match self {
|
|
||||||
Shape::Dot(dot) => dot.c.pos,
|
|
||||||
Shape::Seg(seg) => seg.from,
|
|
||||||
Shape::Bend(bend) => bend.from,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn center(&self) -> Point {
|
fn center(&self) -> Point {
|
||||||
match self {
|
let sum = (self.from - self.c.pos) + (self.to - self.c.pos);
|
||||||
Shape::Dot(dot) => dot.c.pos,
|
self.c.pos + (sum / sum.euclidean_distance(&point! {x: 0.0, y: 0.0})) * self.c.r
|
||||||
Shape::Seg(seg) => (seg.from + seg.to) / 2.0,
|
|
||||||
Shape::Bend(bend) => {
|
|
||||||
let sum = (bend.from - bend.c.pos) + (bend.to - bend.c.pos);
|
|
||||||
bend.c.pos + (sum / sum.euclidean_distance(&point! {x: 0.0, y: 0.0})) * bend.c.r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn priority(&self) -> i64 {
|
fn intersects(&self, other: &Shape) -> bool {
|
||||||
match self {
|
|
||||||
Shape::Dot(..) => 3,
|
|
||||||
Shape::Seg(..) => 2,
|
|
||||||
Shape::Bend(..) => 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intersects(&self, other: &Shape) -> bool {
|
|
||||||
if self.priority() < other.priority() {
|
if self.priority() < other.priority() {
|
||||||
return other.intersects(self);
|
return other.intersects(&Shape::from(*self));
|
||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match other {
|
||||||
Shape::Dot(dot) => match other {
|
Shape::Dot(..) | Shape::Seg(..) => unreachable!(),
|
||||||
Shape::Dot(other) => {
|
Shape::Bend(other) => {
|
||||||
dot.c.pos.euclidean_distance(&other.c.pos) < dot.c.r + other.c.r
|
for point in math::intersect_circles(&self.inner_circle(), &other.inner_circle()) {
|
||||||
|
if self.between_ends(point) && other.between_ends(point) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Shape::Seg(other) => dot.c.pos.euclidean_distance(&other.polygon()) < dot.c.r,
|
|
||||||
Shape::Bend(other) => {
|
|
||||||
for point in math::intersect_circles(&dot.c, &other.inner_circle()) {
|
|
||||||
if other.between_ends(point) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for point in math::intersect_circles(&dot.c, &other.outer_circle()) {
|
for point in math::intersect_circles(&self.inner_circle(), &other.outer_circle()) {
|
||||||
if other.between_ends(point) {
|
if self.between_ends(point) && other.between_ends(point) {
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Shape::Seg(seg) => match other {
|
|
||||||
Shape::Dot(..) => unreachable!(),
|
|
||||||
Shape::Seg(other) => seg.polygon().intersects(&other.polygon()),
|
|
||||||
Shape::Bend(other) => {
|
|
||||||
for segment in seg.polygon().exterior().lines() {
|
|
||||||
let inner_circle = other.inner_circle();
|
|
||||||
let outer_circle = other.outer_circle();
|
|
||||||
|
|
||||||
for point in math::intersect_circle_segment(&inner_circle, &segment) {
|
for point in math::intersect_circles(&self.outer_circle(), &other.inner_circle()) {
|
||||||
if other.between_ends(point) {
|
if self.between_ends(point) && other.between_ends(point) {
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for point in math::intersect_circle_segment(&outer_circle, &segment) {
|
|
||||||
if other.between_ends(point) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Shape::Bend(bend) => match other {
|
|
||||||
Shape::Dot(..) | Shape::Seg(..) => unreachable!(),
|
|
||||||
Shape::Bend(other) => {
|
|
||||||
for point in
|
|
||||||
math::intersect_circles(&bend.inner_circle(), &other.inner_circle())
|
|
||||||
{
|
|
||||||
if bend.between_ends(point) && other.between_ends(point) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for point in
|
for point in math::intersect_circles(&self.outer_circle(), &other.outer_circle()) {
|
||||||
math::intersect_circles(&bend.inner_circle(), &other.outer_circle())
|
if self.between_ends(point) && other.between_ends(point) {
|
||||||
{
|
return true;
|
||||||
if bend.between_ends(point) && other.between_ends(point) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for point in
|
|
||||||
math::intersect_circles(&bend.outer_circle(), &other.inner_circle())
|
|
||||||
{
|
|
||||||
if bend.between_ends(point) && other.between_ends(point) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for point in
|
|
||||||
math::intersect_circles(&bend.outer_circle(), &other.outer_circle())
|
|
||||||
{
|
|
||||||
if bend.between_ends(point) && other.between_ends(point) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn envelope(&self) -> AABB<[f64; 2]> {
|
false
|
||||||
match self {
|
|
||||||
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) => {
|
|
||||||
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) => {
|
|
||||||
let halfwidth = bend.c.r + bend.width;
|
|
||||||
AABB::from_corners(
|
|
||||||
[bend.c.pos.x() - halfwidth, bend.c.pos.y() - halfwidth],
|
|
||||||
[bend.c.pos.x() + halfwidth, bend.c.pos.y() + halfwidth],
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&self) -> f64 {
|
fn envelope(&self) -> AABB<[f64; 2]> {
|
||||||
match self {
|
let halfwidth = self.c.r + self.width;
|
||||||
Shape::Dot(dot) => dot.c.r * 2.0,
|
AABB::from_corners(
|
||||||
Shape::Seg(seg) => seg.width,
|
[self.c.pos.x() - halfwidth, self.c.pos.y() - halfwidth],
|
||||||
Shape::Bend(bend) => bend.width,
|
[self.c.pos.x() + halfwidth, self.c.pos.y() + halfwidth],
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn width(&self) -> f64 {
|
||||||
|
self.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RTreeObject for Shape {
|
impl RTreeObject for Shape {
|
||||||
type Envelope = AABB<[f64; 2]>;
|
type Envelope = AABB<[f64; 2]>;
|
||||||
fn envelope(&self) -> Self::Envelope {
|
fn envelope(&self) -> Self::Envelope {
|
||||||
return self.envelope();
|
return ShapeTrait::envelope(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use contracts::debug_ensures;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bow::Bow,
|
bow::Bow,
|
||||||
draw::{BareHead, Draw, Head, HeadDot, SegbendHead},
|
draw::{BareHead, Draw, Head, HeadTrait, SegbendHead},
|
||||||
graph::{BendIndex, DotIndex, Ends},
|
graph::{BendIndex, DotIndex, Ends},
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
mesh::{Mesh, MeshEdgeReference, VertexIndex},
|
mesh::{Mesh, MeshEdgeReference, VertexIndex},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue