diff --git a/src/autorouter/selection.rs b/src/autorouter/selection.rs index 90cfe8e..2397fc4 100644 --- a/src/autorouter/selection.rs +++ b/src/autorouter/selection.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; use crate::{ board::{mesadata::AccessMesadata, BandName, Board, ResolvedSelector}, drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex}, - geometry::GenericNode, + geometry::{shape::AccessShape, GenericNode}, graph::{GenericIndex, GetPetgraphIndex}, layout::{poly::PolyWeight, CompoundWeight, NodeIndex}, }; @@ -209,7 +209,7 @@ impl Selection { if let Some(rsel) = ResolvedSelector::try_from_node(board, node) { let rseli = selectors.entry(rsel).or_default(); rseli.0.insert(node); - if kind.matches(aabb, &layout.node_bbox(node)) { + if kind.matches(aabb, &layout.node_shape(node).bbox(0.0)) { rseli.1.insert(node); } } @@ -234,7 +234,7 @@ impl Selection { ) { let node = geom.data; if layout.is_node_in_layer(node, active_layer) - && kind.matches(aabb, &layout.node_bbox(node)) + && kind.matches(aabb, &layout.node_shape(node).bbox(0.0)) { if let Some(rsel) = ResolvedSelector::try_from_node(board, node) { selectors.insert(rsel); diff --git a/src/geometry/poly.rs b/src/geometry/poly.rs index 910a52a..e16877c 100644 --- a/src/geometry/poly.rs +++ b/src/geometry/poly.rs @@ -4,6 +4,7 @@ use geo::algorithm::line_measures::{Euclidean, Length}; use geo::{Centroid, Contains, Point, Polygon}; +use rstar::AABB; use crate::geometry::shape::{AccessShape, MeasureLength}; @@ -32,4 +33,16 @@ impl AccessShape for PolyShape { fn contains_point(&self, p: Point) -> bool { self.polygon.contains(&p) } + + fn bbox_without_margin(&self) -> AABB<[f64; 2]> { + AABB::from_points( + self.polygon + .exterior() + .0 + .iter() + .map(|coord| [coord.x, coord.y]) + .collect::>() + .iter(), + ) + } } diff --git a/src/geometry/primitive.rs b/src/geometry/primitive.rs index 7937b9c..c62625d 100644 --- a/src/geometry/primitive.rs +++ b/src/geometry/primitive.rs @@ -19,7 +19,6 @@ pub trait AccessPrimitiveShape: AccessShape { fn priority(&self) -> usize; fn inflate(&self, margin: f64) -> PrimitiveShape; fn intersects(&self, other: &PrimitiveShape) -> bool; - fn bbox(&self, margin: f64) -> AABB<[f64; 2]>; fn width(&self) -> f64; fn envelope_3d(&self, margin: f64, layer: usize) -> AABB<[f64; 3]> { @@ -71,6 +70,10 @@ impl AccessShape for DotShape { fn contains_point(&self, p: Point) -> bool { Euclidean::distance(&p, &self.circle.pos) <= self.circle.r } + + fn bbox_without_margin(&self) -> AABB<[f64; 2]> { + self.circle.bbox(0.0) + } } impl AccessPrimitiveShape for DotShape { @@ -118,19 +121,6 @@ impl AccessPrimitiveShape for DotShape { } } - fn bbox(&self, margin: f64) -> AABB<[f64; 2]> { - AABB::from_corners( - [ - self.circle.pos.x() - self.circle.r - margin, - self.circle.pos.y() - self.circle.r - margin, - ], - [ - self.circle.pos.x() + self.circle.r + margin, - self.circle.pos.y() + self.circle.r + margin, - ], - ) - } - fn width(&self) -> f64 { self.circle.r * 2.0 } @@ -174,6 +164,13 @@ impl AccessShape for SegShape { fn contains_point(&self, p: Point) -> bool { self.polygon().contains(&p) } + + fn bbox_without_margin(&self) -> AABB<[f64; 2]> { + super::poly::PolyShape { + polygon: self.polygon(), + } + .bbox_without_margin() + } } impl AccessPrimitiveShape for SegShape { @@ -220,22 +217,6 @@ impl AccessPrimitiveShape for SegShape { } } - fn bbox(&self, margin: f64) -> AABB<[f64; 2]> { - let points: Vec<[f64; 2]> = self - .polygon() - .exterior() - .points() - .map(|p| [p.x(), p.y()]) - .collect(); - - let aabb = AABB::<[f64; 2]>::from_points(points.iter()); - - // Inflate. - let lower = [aabb.lower()[0] - margin, aabb.lower()[1] - margin]; - let upper = [aabb.upper()[0] + margin, aabb.upper()[1] + margin]; - AABB::<[f64; 2]>::from_corners(lower, upper) - } - fn width(&self) -> f64 { self.width } @@ -331,6 +312,10 @@ impl AccessShape for BendShape { let d = Euclidean::distance(&p, &self.inner_circle.pos); self.between_ends(p) && d >= self.inner_circle().r && d <= self.outer_circle().r } + + fn bbox_without_margin(&self) -> AABB<[f64; 2]> { + self.inner_circle.bbox(self.width) + } } impl AccessPrimitiveShape for BendShape { @@ -387,20 +372,6 @@ impl AccessPrimitiveShape for BendShape { } } - fn bbox(&self, _margin: f64) -> AABB<[f64; 2]> { - let halfwidth = self.inner_circle.r + self.width; - AABB::from_corners( - [ - self.inner_circle.pos.x() - halfwidth, - self.inner_circle.pos.y() - halfwidth, - ], - [ - self.inner_circle.pos.x() + halfwidth, - self.inner_circle.pos.y() + halfwidth, - ], - ) - } - fn width(&self) -> f64 { self.width } @@ -409,6 +380,6 @@ impl AccessPrimitiveShape for BendShape { impl RTreeObject for PrimitiveShape { type Envelope = AABB<[f64; 2]>; fn envelope(&self) -> Self::Envelope { - AccessPrimitiveShape::bbox(self, 0.0) + AccessShape::bbox(self, 0.0) } } diff --git a/src/geometry/shape.rs b/src/geometry/shape.rs index bfc7fca..3359023 100644 --- a/src/geometry/shape.rs +++ b/src/geometry/shape.rs @@ -4,6 +4,7 @@ use enum_dispatch::enum_dispatch; use geo::Point; +use rstar::AABB; use crate::geometry::{ poly::PolyShape, @@ -19,6 +20,15 @@ pub trait MeasureLength { pub trait AccessShape: MeasureLength { fn center(&self) -> Point; fn contains_point(&self, p: Point) -> bool; + fn bbox_without_margin(&self) -> AABB<[f64; 2]>; + + fn bbox(&self, margin: f64) -> AABB<[f64; 2]> { + let aabb = self.bbox_without_margin(); + AABB::<[f64; 2]>::from_corners( + [aabb.lower()[0] - margin, aabb.lower()[1] - margin], + [aabb.upper()[0] + margin, aabb.upper()[1] + margin], + ) + } } #[enum_dispatch(MeasureLength, AccessShape)] diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 8279f03..8c6666a 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -353,32 +353,6 @@ impl Layout { } } - pub fn node_bbox(&self, index: NodeIndex) -> AABB<[f64; 2]> { - use crate::geometry::primitive::AccessPrimitiveShape; - match index { - NodeIndex::Primitive(primitive) => primitive.primitive(&self.drawing).shape().bbox(0.0), - NodeIndex::Compound(compound) => match self.drawing.compound_weight(compound) { - CompoundWeight::Poly(_) => { - let coord_string = self - .poly(GenericIndex::::new(compound.petgraph_index())) - .shape() - .polygon - .exterior() - .0 - .iter() - .map(|coord| [coord.x, coord.y]) - .collect::>(); - - AABB::from_points(&coord_string[..]) - } - CompoundWeight::Via(_) => self - .via(GenericIndex::::new(compound.petgraph_index())) - .shape() - .bbox(0.0), - }, - } - } - pub fn rules(&self) -> &R { self.drawing.rules() }