diff --git a/crates/topola-egui/src/overlay.rs b/crates/topola-egui/src/overlay.rs index 067c5bb..5f84efa 100644 --- a/crates/topola-egui/src/overlay.rs +++ b/crates/topola-egui/src/overlay.rs @@ -12,7 +12,6 @@ use topola::{ selection::{BboxSelectionKind, Selection}, }, board::{AccessMesadata, Board}, - geometry::shape::AccessShape, layout::NodeIndex, router::planar_incr_embed, }; @@ -191,29 +190,14 @@ impl Overlay { return; } - let geoms: Vec<_> = board - .layout() - .drawing() - .rtree() - .locate_in_envelope_intersecting(&AABB::<[f64; 3]>::from_corners( - [at.x(), at.y(), -f64::INFINITY], - [at.x(), at.y(), f64::INFINITY], - )) - .collect(); - - if let Some(geom) = geoms.iter().find(|&&geom| { - board.layout().node_shape(geom.data).contains_point(at) - // TODO: fix which layers to query - && board - .layout() - .drawing() - // This should use: - // `.is_node_in_any_layer_of(geom.data, &appearance_panel.visible[..])` - // instead, but that doesn't work reliably - .is_node_in_layer(geom.data, 0) - }) { - self.selection.toggle_at_node(board, geom.data); - } + let old_selection = self.take_selection(); + self.select_all_in_bbox( + board, + appearance_panel, + &AABB::from_point([at.x(), at.y()]), + BboxSelectionKind::MerelyIntersects, + ); + self.selection ^= &old_selection; } pub fn select_all_in_bbox( diff --git a/src/drawing/guide.rs b/src/drawing/guide.rs index 330c720..21e78ff 100644 --- a/src/drawing/guide.rs +++ b/src/drawing/guide.rs @@ -5,10 +5,7 @@ use geo::Line; use crate::{ - geometry::{ - primitive::{AccessPrimitiveShape, PrimitiveShape}, - shape::AccessShape, - }, + geometry::{primitive::PrimitiveShape, shape::AccessShape, GetWidth}, math::{self, Circle, NoTangents, RotationSense}, }; diff --git a/src/geometry/primitive.rs b/src/geometry/primitive.rs index bc37e1b..11701fd 100644 --- a/src/geometry/primitive.rs +++ b/src/geometry/primitive.rs @@ -6,20 +6,22 @@ use std::f64::consts::TAU; use enum_dispatch::enum_dispatch; use geo::algorithm::line_measures::{Distance, Euclidean}; -use geo::{point, polygon, Contains, Intersects, Line, Point, Polygon, Rotate}; +use geo::{point, polygon, Contains, Intersects, Line, Point, Polygon, Rect, Rotate}; use rstar::{RTreeObject, AABB}; use crate::{ - geometry::shape::{AccessShape, MeasureLength}, + geometry::{ + shape::{AccessShape, MeasureLength}, + GetWidth, + }, math::{self, Circle}, }; #[enum_dispatch] -pub trait AccessPrimitiveShape: AccessShape { +pub trait AccessPrimitiveShape: AccessShape + GetWidth { fn priority(&self) -> usize; fn inflate(&self, margin: f64) -> PrimitiveShape; fn intersects(&self, other: &PrimitiveShape) -> bool; - fn width(&self) -> f64; fn envelope_3d(&self, margin: f64, layer: usize) -> AABB<[f64; 3]> { let envelope = self.bbox(margin); @@ -42,7 +44,7 @@ pub trait AccessPrimitiveShape: AccessShape { } } -#[enum_dispatch(MeasureLength, AccessShape, AccessPrimitiveShape)] +#[enum_dispatch(AccessShape, AccessPrimitiveShape, GetWidth, MeasureLength)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum PrimitiveShape { // Intentionally in different order to reorder `self.intersects(...)` properly. @@ -74,6 +76,11 @@ impl AccessShape for DotShape { fn bbox_without_margin(&self) -> AABB<[f64; 2]> { self.circle.bbox(0.0) } + + fn intersects_with_bbox(&self, bbox: &AABB<[f64; 2]>) -> bool { + let bbox = Rect::new(bbox.lower(), bbox.upper()); + Euclidean::distance(&self.circle.pos, &bbox.to_polygon()) < self.circle.r + } } impl AccessPrimitiveShape for DotShape { @@ -120,7 +127,9 @@ impl AccessPrimitiveShape for DotShape { } } } +} +impl GetWidth for DotShape { fn width(&self) -> f64 { self.circle.r * 2.0 } @@ -157,6 +166,13 @@ impl SegShape { } } +impl From for Polygon { + #[inline(always)] + fn from(x: SegShape) -> Polygon { + x.polygon() + } +} + impl MeasureLength for SegShape { fn length(&self) -> f64 { Euclidean::distance(&self.to, &self.from) @@ -227,7 +243,9 @@ impl AccessPrimitiveShape for SegShape { } } } +} +impl GetWidth for SegShape { fn width(&self) -> f64 { self.width } @@ -382,7 +400,9 @@ impl AccessPrimitiveShape for BendShape { } } } +} +impl GetWidth for BendShape { fn width(&self) -> f64 { self.width }