Select best layout objects, don't be strict over layer

This commit is contained in:
Mikolaj Wielgus 2026-05-28 11:27:24 +02:00
parent 85f33f1a6c
commit 91a6088ff5
10 changed files with 782 additions and 106 deletions

View File

@ -39,7 +39,11 @@ impl Display {
let layout = board.layout();
// Start from the bottom layer so that top layers are drawn on top.
for layer in (0..*layout.layer_count()).rev().map(LayerId::new) {
// The active layer is drawn last so it stays visible above the rest.
for layer in workspace
.appearance_panel
.layers_in_display_order(*layout.layer_count())
{
if !workspace.appearance_panel.visible[layer.index()] {
continue;
}
@ -212,7 +216,10 @@ impl Display {
let board = workspace.workspace.board();
let layout = board.layout();
for layer in (0..*layout.layer_count()).rev().map(LayerId::new) {
for layer in workspace
.appearance_panel
.layers_in_display_order(*layout.layer_count())
{
if !workspace.appearance_panel.visible[layer.index()] {
continue;
}
@ -294,7 +301,10 @@ impl Display {
};
let autorouter = &autorouter_workspace.autorouter;
for layer in (0..*workspace.workspace.board().layout().layer_count()).map(LayerId::new) {
for layer in workspace
.appearance_panel
.layers_in_display_order(*workspace.workspace.board().layout().layer_count())
{
if workspace.appearance_panel.visible[layer.index()] {
for navmesh in autorouter
.router()

View File

@ -146,7 +146,7 @@ impl LayersPanel {
Self {
dark_colors,
light_colors,
active: LayerId::new(0),
active: board.layer_id("F.Cu").unwrap_or(LayerId::new(0)),
visible,
}
}
@ -207,4 +207,17 @@ impl LayersPanel {
self.colors(ctx).layers.colors(layer_desc).normal
}
}
pub fn layers_in_display_order(&self, layer_count: usize) -> Vec<LayerId> {
let active = self.active.index();
let mut layers = (0..layer_count)
.rev()
.filter(|&layer| layer != active)
.map(LayerId::new)
.collect::<Vec<_>>();
// The active layer should be drawn on top.
layers.push(self.active);
layers
}
}

View File

@ -64,12 +64,12 @@ impl DragSelectionInteractor {
SelectionContainMode::Crossing => {
self.selection
.components
.add(board.locate_components_intersecting_rect(rect));
.add(board.locate_components_prefer_layer_intersecting_rect(rect));
}
SelectionContainMode::Window => {
self.selection
.components
.add(board.locate_components_inside_rect(rect));
.add(board.locate_components_prefer_layer_inside_rect(rect));
}
}
@ -77,10 +77,12 @@ impl DragSelectionInteractor {
SelectionContainMode::Crossing => {
self.selection
.nets
.add(board.locate_nets_intersecting_rect(rect));
.add(board.locate_nets_prefer_layer_intersecting_rect(rect));
}
SelectionContainMode::Window => {
self.selection.nets.add(board.locate_nets_inside_rect(rect));
self.selection
.nets
.add(board.locate_nets_prefer_layer_inside_rect(rect));
}
}
@ -88,10 +90,12 @@ impl DragSelectionInteractor {
SelectionContainMode::Crossing => {
self.selection
.pins
.add(board.locate_pins_intersecting_rect(rect));
.add(board.locate_pins_prefer_layer_intersecting_rect(rect));
}
SelectionContainMode::Window => {
self.selection.pins.add(board.locate_pins_inside_rect(rect));
self.selection
.pins
.add(board.locate_pins_prefer_layer_inside_rect(rect));
}
}

View File

@ -47,25 +47,16 @@ impl SelectionInteractor {
if input.release && input.pointer == self.origin {
let mut selection = self.original_selection.clone();
let point = Vector3::new(input.pointer.x, input.pointer.y, layer.index() as i64);
// Pins have intentional precedence over nets and components.
if let Some(pin_selector) = board.locate_pin_at_point(Vector3::new(
input.pointer.x,
input.pointer.y,
layer.index() as i64,
)) {
if let Some(pin_selector) = board.locate_pins_prefer_layer_at_point(point).next() {
selection.pins.xor(std::iter::once(pin_selector));
} else if let Some(net_selector) = board.locate_net_at_point(Vector3::new(
input.pointer.x,
input.pointer.y,
layer.index() as i64,
)) {
} else if let Some(net_selector) = board.locate_nets_prefer_layer_at_point(point).next() {
selection.nets.xor(std::iter::once(net_selector));
} else if let Some(component_selector) = board.locate_component_at_point(Vector3::new(
input.pointer.x,
input.pointer.y,
layer.index() as i64,
)) {
} else if let Some(component_selector) =
board.locate_components_prefer_layer_at_point(point).next()
{
selection
.components
.xor(std::iter::once(component_selector));

View File

@ -11,24 +11,76 @@ use crate::{
};
impl Board {
pub fn locate_component_at_point(&self, point: Vector3<i64>) -> Option<ComponentSelector> {
if let Some(joint_id) = self.layout.locate_joints_at_point(point).next() {
return self.joint_component_selector(joint_id);
}
pub fn locate_components_prefer_layer_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = ComponentSelector> + '_ {
self.layout
.locate_joints_prefer_layer_at_point(point)
.filter_map(|joint_id| self.joint_component_selector(joint_id))
.chain(
self.layout
.locate_segments_prefer_layer_at_point(point)
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_at_point(point)
.filter_map(|via_id| self.via_component_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_prefer_layer_at_point(point)
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
)
}
if let Some(segment_id) = self.layout.locate_segments_at_point(point).next() {
return self.segment_component_selector(segment_id);
}
pub fn locate_components_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = ComponentSelector> + '_ {
self.layout
.locate_joints_at_point(point)
.filter_map(|joint_id| self.joint_component_selector(joint_id))
.chain(
self.layout
.locate_segments_at_point(point)
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_at_point(point)
.filter_map(|via_id| self.via_component_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_at_point(point)
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
)
}
if let Some(via_id) = self.layout.locate_vias_at_point(point).next() {
return self.via_component_selector(via_id);
}
if let Some(polygon_id) = self.layout.locate_polygons_at_point(point).next() {
return self.polygon_component_selector(polygon_id);
}
None
pub fn locate_components_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = ComponentSelector> + '_ {
self.layout
.locate_joints_prefer_layer_intersecting_rect(rect)
.filter_map(|joint_id| self.joint_component_selector(joint_id))
.chain(
self.layout
.locate_segments_prefer_layer_intersecting_rect(rect)
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_intersecting_rect(rect)
.filter_map(|via_id| self.via_component_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_prefer_layer_intersecting_rect(rect)
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
)
}
pub fn locate_components_intersecting_rect(
@ -55,48 +107,117 @@ impl Board {
)
}
pub fn locate_components_prefer_layer_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = ComponentSelector> + '_ {
self.layout
.locate_joints_prefer_layer_inside_rect(rect)
.filter_map(|joint_id| self.joint_component_selector(joint_id))
.chain(
self.layout
.locate_segments_prefer_layer_inside_rect(rect)
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_inside_rect(rect)
.filter_map(|via_id| self.via_component_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_prefer_layer_inside_rect(rect)
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
)
}
pub fn locate_components_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = ComponentSelector> + '_ {
self.layout
.locate_joints_inside_rect(rect)
.locate_joints_prefer_layer_inside_rect(rect)
.filter_map(|joint_id| self.joint_component_selector(joint_id))
.chain(
self.layout
.locate_segments_inside_rect(rect)
.locate_segments_prefer_layer_inside_rect(rect)
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_inside_rect(rect)
.locate_vias_prefer_layer_inside_rect(rect)
.filter_map(|via_id| self.via_component_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_inside_rect(rect)
.locate_polygons_prefer_layer_inside_rect(rect)
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
)
}
pub fn locate_net_at_point(&self, point: Vector3<i64>) -> Option<NetSelector> {
if let Some(joint_id) = self.layout.locate_joints_at_point(point).next() {
return self.joint_net_selector(joint_id);
pub fn locate_nets_prefer_layer_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = NetSelector> + '_ {
self.layout
.locate_joints_prefer_layer_at_point(point)
.filter_map(|joint_id| self.joint_net_selector(joint_id))
.chain(
self.layout
.locate_segments_prefer_layer_at_point(point)
.filter_map(|segment_id| self.segment_net_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_at_point(point)
.filter_map(|via_id| self.via_net_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_prefer_layer_at_point(point)
.filter_map(|polygon_id| self.polygon_net_selector(polygon_id)),
)
}
pub fn locate_nets_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = NetSelector> + '_ {
self.layout
.locate_joints_at_point(point)
.filter_map(|joint_id| self.joint_net_selector(joint_id))
.chain(
self.layout
.locate_segments_at_point(point)
.filter_map(|segment_id| self.segment_net_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_at_point(point)
.filter_map(|via_id| self.via_net_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_at_point(point)
.filter_map(|polygon_id| self.polygon_net_selector(polygon_id)),
)
}
pub fn locate_nets_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = NetSelector> + '_ {
let mut selectors = BTreeSet::new();
for net_id in self.layout.locate_nets_prefer_layer_intersecting_rect(rect) {
let Some(net_name) = self.net_name(net_id) else {
continue;
};
selectors.insert(NetSelector::new(net_name.to_string()));
}
if let Some(segment_id) = self.layout.locate_segments_at_point(point).next() {
return self.segment_net_selector(segment_id);
}
if let Some(via_id) = self.layout.locate_vias_at_point(point).next() {
return self.via_net_selector(via_id);
}
if let Some(polygon_id) = self.layout.locate_polygons_at_point(point).next() {
return self.polygon_net_selector(polygon_id);
}
None
selectors.into_iter()
}
pub fn locate_nets_intersecting_rect(
@ -116,6 +237,23 @@ impl Board {
selectors.into_iter()
}
pub fn locate_nets_prefer_layer_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = NetSelector> + '_ {
let mut selectors = BTreeSet::new();
for net_id in self.layout.locate_nets_prefer_layer_inside_rect(rect) {
let Some(net_name) = self.net_name(net_id) else {
continue;
};
selectors.insert(NetSelector::new(net_name.to_string()));
}
selectors.into_iter()
}
pub fn locate_nets_inside_rect(
&self,
rect: Rect3<i64>,
@ -133,25 +271,76 @@ impl Board {
selectors.into_iter()
}
pub fn locate_pin_at_point(&self, point: Vector3<i64>) -> Option<PinSelector> {
// Polygons have intentional precedence for pins.
if let Some(polygon_id) = self.layout.locate_polygons_at_point(point).next() {
return self.polygon_pin_selector(polygon_id);
}
pub fn locate_pins_prefer_layer_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = PinSelector> + '_ {
self.layout
.locate_polygons_prefer_layer_at_point(point)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
.chain(
self.layout
.locate_joints_prefer_layer_at_point(point)
.filter_map(|joint_id| self.joint_pin_selector(joint_id)),
)
.chain(
self.layout
.locate_segments_prefer_layer_at_point(point)
.filter_map(|segment_id| self.segment_pin_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_at_point(point)
.filter_map(|via_id| self.via_pin_selector(via_id)),
)
}
if let Some(joint_id) = self.layout.locate_joints_at_point(point).next() {
return self.joint_pin_selector(joint_id);
}
pub fn locate_pins_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = PinSelector> + '_ {
self.layout
.locate_polygons_at_point(point)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
.chain(
self.layout
.locate_joints_at_point(point)
.filter_map(|joint_id| self.joint_pin_selector(joint_id)),
)
.chain(
self.layout
.locate_segments_at_point(point)
.filter_map(|segment_id| self.segment_pin_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_at_point(point)
.filter_map(|via_id| self.via_pin_selector(via_id)),
)
}
if let Some(segment_id) = self.layout.locate_segments_at_point(point).next() {
return self.segment_pin_selector(segment_id);
}
if let Some(via_id) = self.layout.locate_vias_at_point(point).next() {
return self.via_pin_selector(via_id);
}
None
pub fn locate_pins_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = PinSelector> + '_ {
self.layout
.locate_polygons_prefer_layer_intersecting_rect(rect)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
.chain(
self.layout
.locate_joints_prefer_layer_intersecting_rect(rect)
.filter_map(|joint_id| self.joint_pin_selector(joint_id)),
)
.chain(
self.layout
.locate_segments_prefer_layer_intersecting_rect(rect)
.filter_map(|segment_id| self.segment_pin_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_intersecting_rect(rect)
.filter_map(|via_id| self.via_pin_selector(via_id)),
)
}
pub fn locate_pins_intersecting_rect(
@ -159,8 +348,13 @@ impl Board {
rect: Rect3<i64>,
) -> impl Iterator<Item = PinSelector> + '_ {
self.layout
.locate_joints_intersecting_rect(rect)
.filter_map(|joint_id| self.joint_pin_selector(joint_id))
.locate_polygons_intersecting_rect(rect)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
.chain(
self.layout
.locate_joints_intersecting_rect(rect)
.filter_map(|joint_id| self.joint_pin_selector(joint_id)),
)
.chain(
self.layout
.locate_segments_intersecting_rect(rect)
@ -171,10 +365,29 @@ impl Board {
.locate_vias_intersecting_rect(rect)
.filter_map(|via_id| self.via_pin_selector(via_id)),
)
}
pub fn locate_pins_prefer_layer_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = PinSelector> + '_ {
self.layout
.locate_polygons_prefer_layer_inside_rect(rect)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
.chain(
self.layout
.locate_polygons_intersecting_rect(rect)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id)),
.locate_joints_prefer_layer_inside_rect(rect)
.filter_map(|joint_id| self.joint_pin_selector(joint_id)),
)
.chain(
self.layout
.locate_segments_prefer_layer_inside_rect(rect)
.filter_map(|segment_id| self.segment_pin_selector(segment_id)),
)
.chain(
self.layout
.locate_vias_prefer_layer_inside_rect(rect)
.filter_map(|via_id| self.via_pin_selector(via_id)),
)
}
@ -183,8 +396,13 @@ impl Board {
rect: Rect3<i64>,
) -> impl Iterator<Item = PinSelector> + '_ {
self.layout
.locate_joints_inside_rect(rect)
.filter_map(|joint_id| self.joint_pin_selector(joint_id))
.locate_polygons_inside_rect(rect)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
.chain(
self.layout
.locate_joints_inside_rect(rect)
.filter_map(|joint_id| self.joint_pin_selector(joint_id)),
)
.chain(
self.layout
.locate_segments_inside_rect(rect)
@ -195,10 +413,5 @@ impl Board {
.locate_vias_inside_rect(rect)
.filter_map(|via_id| self.via_pin_selector(via_id)),
)
.chain(
self.layout
.locate_polygons_inside_rect(rect)
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id)),
)
}
}

View File

@ -4,20 +4,65 @@
use std::collections::BTreeSet;
use rstar::AABB;
use crate::{
Rect3, Vector3,
layout::{LayerId, Layout, compounds::NetId},
Rect2, Rect3, Vector2, Vector3,
layout::{Layout, compounds::NetId},
primitives::{JointId, PolygonId, SegmentId, ViaId},
};
impl Layout {
pub fn locate_joints_prefer_layer_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = JointId> {
let at_point = self.locate_joints_at_point(point).collect::<Vec<_>>();
let joints = if at_point.is_empty() {
self.locate_joints_any_layer_at_point(point.xy()).collect()
} else {
at_point
};
joints.into_iter()
}
pub fn locate_joints_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = JointId> {
let point2 = point.xy();
self.joints_rtree
.as_ref()
.locate_all_at_point(&[point.x, point.y, point.z])
.map(|geom_with_data| geom_with_data.data)
.filter(move |&joint_id| self.joints[joint_id.index()].contains_point(point2))
.filter(move |&joint_id| self.joints[joint_id.index()].contains_point2(point.xy()))
}
pub fn locate_joints_any_layer_at_point(&self, point: Vector2<i64>) -> impl Iterator<Item = JointId> {
let max_layer = (self.layer_count() - 1) as i64;
let envelope = AABB::from_corners([point.x, point.y, 0], [point.x, point.y, max_layer]);
self.joints_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&joint_id| self.joints[joint_id.index()].contains_point2(point))
}
pub fn locate_joints_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = JointId> {
let at_rect = self
.locate_joints_intersecting_rect(rect)
.collect::<Vec<_>>();
let joints = if at_rect.is_empty() {
self.locate_joints_any_layer_intersecting_rect(rect.rect2())
.collect()
} else {
at_rect
};
joints.into_iter()
}
pub fn locate_joints_intersecting_rect(
@ -35,6 +80,42 @@ impl Layout {
})
}
pub fn locate_joints_any_layer_intersecting_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = JointId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.joints_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&joint_id| {
let joint = self.joint(joint_id);
rect.intersects_circle(joint.spec.position, joint.spec.radius as i64)
})
}
pub fn locate_joints_prefer_layer_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = JointId> {
let at_rect = self.locate_joints_inside_rect(rect).collect::<Vec<_>>();
let joints = if at_rect.is_empty() {
self.locate_joints_any_layer_inside_rect(rect.rect2()).collect()
} else {
at_rect
};
joints.into_iter()
}
pub fn locate_joints_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = JointId> {
self.joints_rtree
.as_ref()
@ -47,12 +128,80 @@ impl Layout {
})
}
pub fn locate_joints_any_layer_inside_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = JointId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.joints_rtree
.as_ref()
.locate_in_envelope(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&joint_id| {
let joint = self.joint(joint_id);
rect.intersects_circle(joint.spec.position, joint.spec.radius as i64)
})
}
pub fn locate_segments_prefer_layer_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = SegmentId> {
let at_point = self.locate_segments_at_point(point).collect::<Vec<_>>();
let segments = if at_point.is_empty() {
self.locate_segments_any_layer_at_point(point.xy()).collect()
} else {
at_point
};
segments.into_iter()
}
pub fn locate_segments_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = SegmentId> {
self.segments_rtree
.as_ref()
.locate_all_at_point(&[point.x, point.y, point.z])
.map(|geom_with_data| geom_with_data.data)
.filter(move |&segment_id| self.segment(segment_id).contains_point(point.xy()))
.filter(move |&segment_id| self.segment(segment_id).contains_point2(point.xy()))
}
pub fn locate_segments_any_layer_at_point(
&self,
point: Vector2<i64>,
) -> impl Iterator<Item = SegmentId> {
let max_layer = (self.layer_count() - 1) as i64;
let envelope = AABB::from_corners([point.x, point.y, 0], [point.x, point.y, max_layer]);
self.segments_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&segment_id| self.segments[segment_id.index()].contains_point2(point))
}
pub fn locate_segments_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = SegmentId> {
let at_point = self
.locate_segments_intersecting_rect(rect)
.collect::<Vec<_>>();
let joints = if at_point.is_empty() {
self.locate_segments_any_layer_intersecting_rect(rect.rect2())
.collect()
} else {
at_point
};
joints.into_iter()
}
pub fn locate_segments_intersecting_rect(
@ -70,6 +219,43 @@ impl Layout {
})
}
pub fn locate_segments_any_layer_intersecting_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = SegmentId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.segments_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&segment_id| {
let segment = self.segment(segment_id);
rect.intersects_polygon(&segment.bounding_rectangle())
})
}
pub fn locate_segments_prefer_layer_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = SegmentId> {
let at_point = self.locate_segments_inside_rect(rect).collect::<Vec<_>>();
let joints = if at_point.is_empty() {
self.locate_segments_any_layer_inside_rect(rect.rect2())
.collect()
} else {
at_point
};
joints.into_iter()
}
pub fn locate_segments_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = SegmentId> {
self.segments_rtree
.as_ref()
@ -81,13 +267,72 @@ impl Layout {
})
}
pub fn locate_segments_any_layer_inside_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = SegmentId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.segments_rtree
.as_ref()
.locate_in_envelope(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&segment_id| {
let segment = self.segment(segment_id);
rect.contains_polygon(&segment.bounding_rectangle())
})
}
pub fn locate_vias_prefer_layer_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = ViaId> {
let at_point = self.locate_vias_at_point(point).collect::<Vec<_>>();
let vias = if at_point.is_empty() {
self.locate_vias_any_layer_at_point(point.xy()).collect()
} else {
at_point
};
vias.into_iter()
}
pub fn locate_vias_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = ViaId> {
let layer = LayerId::new(point.z as usize);
self.vias_rtree
.as_ref()
.locate_all_at_point(&[point.x, point.y, point.z])
.map(|geom_with_data| geom_with_data.data)
.filter(move |&via_id| self.vias[via_id.index()].contains_point(layer, point.xy()))
.filter(move |&via_id| self.vias[via_id.index()].contains_point2(point.xy()))
}
pub fn locate_vias_any_layer_at_point(&self, point: Vector2<i64>) -> impl Iterator<Item = ViaId> {
let max_layer = (self.layer_count() - 1) as i64;
let envelope = AABB::from_corners([point.x, point.y, 0], [point.x, point.y, max_layer]);
self.vias_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&via_id| self.vias[via_id.index()].contains_point2(point))
}
pub fn locate_vias_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = ViaId> {
let at_point = self.locate_vias_intersecting_rect(rect).collect::<Vec<_>>();
let vias = if at_point.is_empty() {
self.locate_vias_any_layer_intersecting_rect(rect.rect2())
.collect()
} else {
at_point
};
vias.into_iter()
}
pub fn locate_vias_intersecting_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
@ -102,6 +347,39 @@ impl Layout {
})
}
pub fn locate_vias_any_layer_intersecting_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = ViaId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.vias_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&via_id| {
let via = self.via(via_id);
rect.intersects_circle(via.position, via.spec.radius as i64)
})
}
pub fn locate_vias_prefer_layer_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
let at_rect = self.locate_vias_inside_rect(rect).collect::<Vec<_>>();
let vias = if at_rect.is_empty() {
self.locate_vias_any_layer_inside_rect(rect.rect2()).collect()
} else {
at_rect
};
vias.into_iter()
}
pub fn locate_vias_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
self.vias_rtree
.as_ref()
@ -114,13 +392,79 @@ impl Layout {
})
}
pub fn locate_vias_any_layer_inside_rect(&self, rect: Rect2<i64>) -> impl Iterator<Item = ViaId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.vias_rtree
.as_ref()
.locate_in_envelope(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&via_id| {
let via = self.via(via_id);
rect.contains_circle(via.position, via.spec.radius as i64)
})
}
pub fn locate_polygons_prefer_layer_at_point(
&self,
point: Vector3<i64>,
) -> impl Iterator<Item = PolygonId> {
let at_point = self.locate_polygons_at_point(point).collect::<Vec<_>>();
let polygons = if at_point.is_empty() {
self.locate_polygons_any_layer_at_point(point.xy()).collect()
} else {
at_point
};
polygons.into_iter()
}
pub fn locate_polygons_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = PolygonId> {
let point2 = point.xy();
self.polygons_rtree
.as_ref()
.locate_all_at_point(&[point.x, point.y, point.z])
.map(|geom_with_data| geom_with_data.data)
.filter(move |&polygon_id| self.polygons[polygon_id.index()].contains_point(point2))
.filter(move |&polygon_id| {
self.polygons[polygon_id.index()].contains_point2(point.xy())
})
}
pub fn locate_polygons_any_layer_at_point(
&self,
point: Vector2<i64>,
) -> impl Iterator<Item = PolygonId> {
let max_layer = (self.layer_count() - 1) as i64;
let envelope = AABB::from_corners([point.x, point.y, 0], [point.x, point.y, max_layer]);
self.polygons_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&polygon_id| self.polygons[polygon_id.index()].contains_point2(point))
}
pub fn locate_polygons_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = PolygonId> {
let at_rect = self
.locate_polygons_intersecting_rect(rect)
.collect::<Vec<_>>();
let polygons = if at_rect.is_empty() {
self.locate_polygons_any_layer_intersecting_rect(rect.rect2())
.collect()
} else {
at_rect
};
polygons.into_iter()
}
pub fn locate_polygons_intersecting_rect(
@ -137,6 +481,43 @@ impl Layout {
})
}
pub fn locate_polygons_any_layer_intersecting_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = PolygonId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.polygons_rtree
.as_ref()
.locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&polygon_id| {
let polygon = self.polygon(polygon_id);
rect.intersects_polygon(&polygon.vertices)
})
}
pub fn locate_polygons_prefer_layer_inside_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = PolygonId> {
let at_rect = self.locate_polygons_inside_rect(rect).collect::<Vec<_>>();
let polygons = if at_rect.is_empty() {
self.locate_polygons_any_layer_inside_rect(rect.rect2())
.collect()
} else {
at_rect
};
polygons.into_iter()
}
pub fn locate_polygons_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = PolygonId> {
self.polygons_rtree
.as_ref()
@ -148,6 +529,52 @@ impl Layout {
})
}
pub fn locate_polygons_any_layer_inside_rect(
&self,
rect: Rect2<i64>,
) -> impl Iterator<Item = PolygonId> {
let max_layer = (self.layer_count() - 1) as i64;
let corners = rect.corners();
let envelope = AABB::from_corners(
[corners[0].x, corners[0].y, 0],
[corners[2].x, corners[2].y, max_layer],
);
self.polygons_rtree
.as_ref()
.locate_in_envelope(&envelope)
.map(|geom_with_data| geom_with_data.data)
.filter(move |&polygon_id| {
let polygon = self.polygon(polygon_id);
rect.contains_polygon(&polygon.vertices)
})
}
pub fn locate_nets_prefer_layer_intersecting_rect(
&self,
rect: Rect3<i64>,
) -> impl Iterator<Item = NetId> {
let mut nets = BTreeSet::new();
for joint_id in self.locate_joints_prefer_layer_intersecting_rect(rect) {
nets.insert(self.joint(joint_id).spec.net);
}
for segment_id in self.locate_segments_prefer_layer_intersecting_rect(rect) {
nets.insert(self.segment(segment_id).net);
}
for via_id in self.locate_vias_prefer_layer_intersecting_rect(rect) {
nets.insert(self.via(via_id).net);
}
for polygon_id in self.locate_polygons_prefer_layer_intersecting_rect(rect) {
nets.insert(self.polygon(polygon_id).net);
}
nets.into_iter()
}
pub fn locate_nets_intersecting_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = NetId> {
let mut nets = BTreeSet::new();
@ -170,6 +597,28 @@ impl Layout {
nets.into_iter()
}
pub fn locate_nets_prefer_layer_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = NetId> {
let mut nets = BTreeSet::new();
for joint_id in self.locate_joints_prefer_layer_inside_rect(rect) {
nets.insert(self.joint(joint_id).spec.net);
}
for segment_id in self.locate_segments_prefer_layer_inside_rect(rect) {
nets.insert(self.segment(segment_id).net);
}
for via_id in self.locate_vias_prefer_layer_inside_rect(rect) {
nets.insert(self.via(via_id).net);
}
for polygon_id in self.locate_polygons_prefer_layer_inside_rect(rect) {
nets.insert(self.polygon(polygon_id).net);
}
nets.into_iter()
}
pub fn locate_nets_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = NetId> {
let mut nets = BTreeSet::new();

View File

@ -72,7 +72,7 @@ impl Joint {
))
}
pub fn contains_point(&self, point: Vector2<i64>) -> bool {
pub fn contains_point2(&self, point: Vector2<i64>) -> bool {
(point.x - self.spec.position.x).pow(2) as u64
+ (point.y - self.spec.position.y).pow(2) as u64
<= self.spec.radius.pow(2)

View File

@ -61,7 +61,7 @@ impl Polygon {
Vector2::<i64>::polygon_centroid(&self.vertices)
}
pub fn contains_point(&self, point: Vector2<i64>) -> bool {
pub fn contains_point2(&self, point: Vector2<i64>) -> bool {
point.inside_polygon(&self.vertices)
}
}

View File

@ -57,7 +57,7 @@ impl Segment {
(self.endpoints[0] + self.endpoints[1]) / 2
}
pub fn contains_point(&self, point: Vector2<i64>) -> bool {
pub fn contains_point2(&self, point: Vector2<i64>) -> bool {
let vertices = crate::math::inflated_segment(
self.endpoints[0].x,
self.endpoints[0].y,

View File

@ -54,11 +54,7 @@ pub struct Via {
}
impl Via {
pub fn contains_point(&self, layer: LayerId, point: Vector2<i64>) -> bool {
if layer < self.min_layer || layer > self.max_layer {
return false;
}
pub fn contains_point2(&self, point: Vector2<i64>) -> bool {
(point.x - self.position.x).pow(2) as u64 + (point.y - self.position.y).pow(2) as u64
<= self.spec.radius.pow(2)
}