mirror of https://codeberg.org/topola/topola.git
fix(BboxSelection): make intersection calculations against Polygons more accurate
This commit is contained in:
parent
c7d50fd79f
commit
59154c380f
|
|
@ -10,7 +10,10 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::{
|
||||
board::{mesadata::AccessMesadata, BandName, Board, ResolvedSelector},
|
||||
drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex},
|
||||
geometry::{shape::AccessShape, GenericNode},
|
||||
geometry::{
|
||||
shape::{AccessShape, Shape},
|
||||
GenericNode,
|
||||
},
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
layout::{poly::PolyWeight, CompoundWeight, NodeIndex},
|
||||
};
|
||||
|
|
@ -161,11 +164,11 @@ pub enum BboxSelectionKind {
|
|||
}
|
||||
|
||||
impl BboxSelectionKind {
|
||||
pub fn matches(&self, bigger: &AABB<[f64; 2]>, smaller: &AABB<[f64; 2]>) -> bool {
|
||||
pub fn matches(&self, bigger: &AABB<[f64; 2]>, smaller: &Shape) -> bool {
|
||||
use rstar::Envelope;
|
||||
match self {
|
||||
Self::CompletelyInside => bigger.contains_envelope(&smaller),
|
||||
Self::MerelyIntersects => bigger.intersection_area(&smaller) > 0.0,
|
||||
Self::CompletelyInside => bigger.contains_envelope(&smaller.bbox_without_margin()),
|
||||
Self::MerelyIntersects => smaller.intersects_with_bbox(bigger),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +212,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_shape(node).bbox(0.0)) {
|
||||
if kind.matches(aabb, &layout.node_shape(node)) {
|
||||
rseli.1.insert(node);
|
||||
}
|
||||
}
|
||||
|
|
@ -234,7 +237,7 @@ impl Selection {
|
|||
) {
|
||||
let node = geom.data;
|
||||
if layout.is_node_in_layer(node, active_layer)
|
||||
&& kind.matches(aabb, &layout.node_shape(node).bbox(0.0))
|
||||
&& kind.matches(aabb, &layout.node_shape(node))
|
||||
{
|
||||
if let Some(rsel) = ResolvedSelector::try_from_node(board, node) {
|
||||
selectors.insert(rsel);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use geo::algorithm::line_measures::{Euclidean, Length};
|
||||
use geo::algorithm::{
|
||||
line_measures::{Euclidean, Length},
|
||||
Intersects,
|
||||
};
|
||||
use geo::{Centroid, Contains, Point, Polygon};
|
||||
use rstar::AABB;
|
||||
|
||||
|
|
@ -39,4 +42,8 @@ impl AccessShape for Polygon {
|
|||
.iter(),
|
||||
)
|
||||
}
|
||||
|
||||
fn intersects_with_bbox(&self, bbox: &AABB<[f64; 2]>) -> bool {
|
||||
geo::Rect::new(bbox.lower(), bbox.upper()).intersects(self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,13 +161,20 @@ impl AccessShape for SegShape {
|
|||
(self.from + self.to) / 2.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn contains_point(&self, p: Point) -> bool {
|
||||
self.polygon().contains(&p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bbox_without_margin(&self) -> AABB<[f64; 2]> {
|
||||
self.polygon().bbox_without_margin()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intersects_with_bbox(&self, bbox: &AABB<[f64; 2]>) -> bool {
|
||||
self.polygon().intersects_with_bbox(bbox)
|
||||
}
|
||||
}
|
||||
|
||||
impl AccessPrimitiveShape for SegShape {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ pub trait AccessShape: MeasureLength {
|
|||
[aabb.upper()[0] + margin, aabb.upper()[1] + margin],
|
||||
)
|
||||
}
|
||||
|
||||
fn intersects_with_bbox(&self, bbox: &AABB<[f64; 2]>) -> bool {
|
||||
use rstar::Envelope;
|
||||
bbox.intersection_area(&self.bbox_without_margin()) > 0.0
|
||||
}
|
||||
}
|
||||
|
||||
#[enum_dispatch(MeasureLength, AccessShape)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue