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::{
|
use crate::{
|
||||||
board::{mesadata::AccessMesadata, BandName, Board, ResolvedSelector},
|
board::{mesadata::AccessMesadata, BandName, Board, ResolvedSelector},
|
||||||
drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex},
|
drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex},
|
||||||
geometry::{shape::AccessShape, GenericNode},
|
geometry::{
|
||||||
|
shape::{AccessShape, Shape},
|
||||||
|
GenericNode,
|
||||||
|
},
|
||||||
graph::{GenericIndex, GetPetgraphIndex},
|
graph::{GenericIndex, GetPetgraphIndex},
|
||||||
layout::{poly::PolyWeight, CompoundWeight, NodeIndex},
|
layout::{poly::PolyWeight, CompoundWeight, NodeIndex},
|
||||||
};
|
};
|
||||||
|
|
@ -161,11 +164,11 @@ pub enum BboxSelectionKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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;
|
use rstar::Envelope;
|
||||||
match self {
|
match self {
|
||||||
Self::CompletelyInside => bigger.contains_envelope(&smaller),
|
Self::CompletelyInside => bigger.contains_envelope(&smaller.bbox_without_margin()),
|
||||||
Self::MerelyIntersects => bigger.intersection_area(&smaller) > 0.0,
|
Self::MerelyIntersects => smaller.intersects_with_bbox(bigger),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +212,7 @@ impl Selection {
|
||||||
if let Some(rsel) = ResolvedSelector::try_from_node(board, node) {
|
if let Some(rsel) = ResolvedSelector::try_from_node(board, node) {
|
||||||
let rseli = selectors.entry(rsel).or_default();
|
let rseli = selectors.entry(rsel).or_default();
|
||||||
rseli.0.insert(node);
|
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);
|
rseli.1.insert(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +237,7 @@ impl Selection {
|
||||||
) {
|
) {
|
||||||
let node = geom.data;
|
let node = geom.data;
|
||||||
if layout.is_node_in_layer(node, active_layer)
|
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) {
|
if let Some(rsel) = ResolvedSelector::try_from_node(board, node) {
|
||||||
selectors.insert(rsel);
|
selectors.insert(rsel);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// 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 geo::{Centroid, Contains, Point, Polygon};
|
||||||
use rstar::AABB;
|
use rstar::AABB;
|
||||||
|
|
||||||
|
|
@ -39,4 +42,8 @@ impl AccessShape for Polygon {
|
||||||
.iter(),
|
.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
|
(self.from + self.to) / 2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn contains_point(&self, p: Point) -> bool {
|
fn contains_point(&self, p: Point) -> bool {
|
||||||
self.polygon().contains(&p)
|
self.polygon().contains(&p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bbox_without_margin(&self) -> AABB<[f64; 2]> {
|
fn bbox_without_margin(&self) -> AABB<[f64; 2]> {
|
||||||
self.polygon().bbox_without_margin()
|
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 {
|
impl AccessPrimitiveShape for SegShape {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ pub trait AccessShape: MeasureLength {
|
||||||
[aabb.upper()[0] + margin, aabb.upper()[1] + margin],
|
[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)]
|
#[enum_dispatch(MeasureLength, AccessShape)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue