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 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(
|
||||
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]> {
|
||||
let endpoints = self.segment_endpoints(segment_id);
|
||||
let layer = self.segments.get(&segment_id.id()).unwrap().layer as i64;
|
||||
|
|
@ -188,23 +201,30 @@ impl Layout {
|
|||
pub fn locate_joints_at_point(
|
||||
&self,
|
||||
layer: usize,
|
||||
point: [i64; 2],
|
||||
point: Vector2<i64>,
|
||||
) -> impl Iterator<Item = JointId> {
|
||||
self.joints_rtree
|
||||
.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)
|
||||
.filter(move |joint_id| {
|
||||
self.joints
|
||||
.get(&joint_id.id())
|
||||
.unwrap()
|
||||
.contains_point(point)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn locate_segments_at_point(
|
||||
&self,
|
||||
layer: usize,
|
||||
point: [i64; 2],
|
||||
point: Vector2<i64>,
|
||||
) -> impl Iterator<Item = SegmentId> {
|
||||
self.segments_rtree
|
||||
.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)
|
||||
.filter(move |segment_id| self.segment_contains_point(*segment_id, point))
|
||||
}
|
||||
|
||||
// TODO: vias.
|
||||
|
|
@ -212,12 +232,18 @@ impl Layout {
|
|||
pub fn locate_polygons_at_point(
|
||||
&self,
|
||||
layer: usize,
|
||||
point: [i64; 2],
|
||||
point: Vector2<i64>,
|
||||
) -> impl Iterator<Item = PolygonId> {
|
||||
self.polygons_rtree
|
||||
.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)
|
||||
.filter(move |polygon_id| {
|
||||
self.polygons
|
||||
.get(&polygon_id.id())
|
||||
.unwrap()
|
||||
.contains_point(point)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pin(&self, pin: PinId) -> &Pin {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,33 @@ impl_inside_polygon!(f64);
|
|||
impl_inside_polygon!(i32);
|
||||
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 {
|
||||
($t:ty) => {
|
||||
impl Vector2<$t> {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use dearcut::RecordingTriangulator;
|
|||
use derive_getters::Getters;
|
||||
|
||||
use crate::{
|
||||
math,
|
||||
Board,
|
||||
primitives::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId},
|
||||
};
|
||||
|
|
@ -162,35 +163,18 @@ impl NavmesherBoard {
|
|||
|
||||
navmesher.insert_polygon(
|
||||
segment.layer,
|
||||
Self::inflated_segment(
|
||||
math::inflated_segment(
|
||||
endpoints[0].x,
|
||||
endpoints[0].y,
|
||||
endpoints[1].x,
|
||||
endpoints[1].y,
|
||||
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 {
|
||||
// TODO: Insert into navmesh.
|
||||
self.board.add_via(via)
|
||||
|
|
|
|||
Loading…
Reference in New Issue