mirror of https://codeberg.org/topola/topola.git
Filter out bbox-located primitives for which hit-test fails
This commit is contained in:
parent
7aed12dda9
commit
6992369041
|
|
@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use stable_vec::StableVec;
|
use stable_vec::StableVec;
|
||||||
use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
|
use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
|
||||||
|
|
||||||
use crate::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId, Vector2};
|
use crate::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2, Via, ViaId};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
|
@ -172,6 +172,19 @@ impl Layout {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn segment_contains_point(&self, segment_id: SegmentId, point: Vector2<i64>) -> bool {
|
||||||
|
let endpoints = self.segment_endpoints(segment_id);
|
||||||
|
let segment = self.segments.get(&segment_id.id()).unwrap();
|
||||||
|
let vertices = crate::math::inflated_segment(
|
||||||
|
endpoints[0].x,
|
||||||
|
endpoints[0].y,
|
||||||
|
endpoints[1].x,
|
||||||
|
endpoints[1].y,
|
||||||
|
segment.half_width,
|
||||||
|
);
|
||||||
|
point.inside_polygon(&vertices)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn segment_bbox(&self, segment_id: SegmentId) -> Rectangle<[i64; 3]> {
|
pub fn segment_bbox(&self, segment_id: SegmentId) -> Rectangle<[i64; 3]> {
|
||||||
let endpoints = self.segment_endpoints(segment_id);
|
let endpoints = self.segment_endpoints(segment_id);
|
||||||
let layer = self.segments.get(&segment_id.id()).unwrap().layer as i64;
|
let layer = self.segments.get(&segment_id.id()).unwrap().layer as i64;
|
||||||
|
|
@ -188,23 +201,30 @@ impl Layout {
|
||||||
pub fn locate_joints_at_point(
|
pub fn locate_joints_at_point(
|
||||||
&self,
|
&self,
|
||||||
layer: usize,
|
layer: usize,
|
||||||
point: [i64; 2],
|
point: Vector2<i64>,
|
||||||
) -> impl Iterator<Item = JointId> {
|
) -> impl Iterator<Item = JointId> {
|
||||||
self.joints_rtree
|
self.joints_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point[0], point[1], layer as i64])
|
.locate_all_at_point(&[point.x, point.y, layer as i64])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
|
.filter(move |joint_id| {
|
||||||
|
self.joints
|
||||||
|
.get(&joint_id.id())
|
||||||
|
.unwrap()
|
||||||
|
.contains_point(point)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_segments_at_point(
|
pub fn locate_segments_at_point(
|
||||||
&self,
|
&self,
|
||||||
layer: usize,
|
layer: usize,
|
||||||
point: [i64; 2],
|
point: Vector2<i64>,
|
||||||
) -> impl Iterator<Item = SegmentId> {
|
) -> impl Iterator<Item = SegmentId> {
|
||||||
self.segments_rtree
|
self.segments_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point[0], point[1], layer as i64])
|
.locate_all_at_point(&[point.x, point.y, layer as i64])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
|
.filter(move |segment_id| self.segment_contains_point(*segment_id, point))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: vias.
|
// TODO: vias.
|
||||||
|
|
@ -212,12 +232,18 @@ impl Layout {
|
||||||
pub fn locate_polygons_at_point(
|
pub fn locate_polygons_at_point(
|
||||||
&self,
|
&self,
|
||||||
layer: usize,
|
layer: usize,
|
||||||
point: [i64; 2],
|
point: Vector2<i64>,
|
||||||
) -> impl Iterator<Item = PolygonId> {
|
) -> impl Iterator<Item = PolygonId> {
|
||||||
self.polygons_rtree
|
self.polygons_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point[0], point[1], layer as i64])
|
.locate_all_at_point(&[point.x, point.y, layer as i64])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
|
.filter(move |polygon_id| {
|
||||||
|
self.polygons
|
||||||
|
.get(&polygon_id.id())
|
||||||
|
.unwrap()
|
||||||
|
.contains_point(point)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pin(&self, pin: PinId) -> &Pin {
|
pub fn pin(&self, pin: PinId) -> &Pin {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,33 @@ impl_inside_polygon!(f64);
|
||||||
impl_inside_polygon!(i32);
|
impl_inside_polygon!(i32);
|
||||||
impl_inside_polygon!(i64);
|
impl_inside_polygon!(i64);
|
||||||
|
|
||||||
|
/// Returns the four vertices of a segment inflated by `half_width`, forming a convex
|
||||||
|
/// quadrilateral. The segment goes from (x1, y1) to (x2, y2).
|
||||||
|
pub fn inflated_segment(
|
||||||
|
x1: i64,
|
||||||
|
y1: i64,
|
||||||
|
x2: i64,
|
||||||
|
y2: i64,
|
||||||
|
half_width: u64,
|
||||||
|
) -> [Vector2<i64>; 4] {
|
||||||
|
let dx = x2 - x1;
|
||||||
|
let dy = y2 - y1;
|
||||||
|
|
||||||
|
let approx_len =
|
||||||
|
std::cmp::max(dx.abs(), dy.abs()) + 3 * std::cmp::min(dx.abs(), dy.abs()) / 8;
|
||||||
|
|
||||||
|
// Perpendicular vector scaled to half-width.
|
||||||
|
let px = -dy * (half_width as i64) / approx_len;
|
||||||
|
let py = dx * (half_width as i64) / approx_len;
|
||||||
|
|
||||||
|
[
|
||||||
|
Vector2::new(x1 + px, y1 + py),
|
||||||
|
Vector2::new(x2 + px, y2 + py),
|
||||||
|
Vector2::new(x2 - px, y2 - py),
|
||||||
|
Vector2::new(x1 - px, y1 - py),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_rotate_around_point {
|
macro_rules! impl_rotate_around_point {
|
||||||
($t:ty) => {
|
($t:ty) => {
|
||||||
impl Vector2<$t> {
|
impl Vector2<$t> {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use dearcut::RecordingTriangulator;
|
||||||
use derive_getters::Getters;
|
use derive_getters::Getters;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
math,
|
||||||
Board,
|
Board,
|
||||||
primitives::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId},
|
primitives::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId},
|
||||||
};
|
};
|
||||||
|
|
@ -162,35 +163,18 @@ impl NavmesherBoard {
|
||||||
|
|
||||||
navmesher.insert_polygon(
|
navmesher.insert_polygon(
|
||||||
segment.layer,
|
segment.layer,
|
||||||
Self::inflated_segment(
|
math::inflated_segment(
|
||||||
endpoints[0].x,
|
endpoints[0].x,
|
||||||
endpoints[0].y,
|
endpoints[0].y,
|
||||||
endpoints[1].x,
|
endpoints[1].x,
|
||||||
endpoints[1].y,
|
endpoints[1].y,
|
||||||
segment.half_width,
|
segment.half_width,
|
||||||
),
|
)
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inflated_segment(x1: i64, y1: i64, x2: i64, y2: i64, half_width: u64) -> [[i64; 2]; 4] {
|
|
||||||
let dx = x2 - x1;
|
|
||||||
let dy = y2 - y1;
|
|
||||||
|
|
||||||
let approx_len =
|
|
||||||
std::cmp::max(dx.abs(), dy.abs()) + 3 * std::cmp::min(dx.abs(), dy.abs()) / 8;
|
|
||||||
|
|
||||||
// Perpendicular vector scaled to half-width.
|
|
||||||
let px = -dy * (half_width as i64) / approx_len;
|
|
||||||
let py = dx * (half_width as i64) / approx_len;
|
|
||||||
|
|
||||||
[
|
|
||||||
[x1 + px, y1 + py],
|
|
||||||
[x2 + px, y2 + py],
|
|
||||||
[x2 - px, y2 - py],
|
|
||||||
[x1 - px, y1 - py],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_via(&mut self, via: Via) -> ViaId {
|
pub fn insert_via(&mut self, via: Via) -> ViaId {
|
||||||
// TODO: Insert into navmesh.
|
// TODO: Insert into navmesh.
|
||||||
self.board.add_via(via)
|
self.board.add_via(via)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue