mirror of https://codeberg.org/topola/topola.git
Select best layout objects, don't be strict over layer
This commit is contained in:
parent
85f33f1a6c
commit
9221663d66
|
|
@ -10,6 +10,7 @@ resolver = "2"
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
derive-getters = "0.5"
|
derive-getters = "0.5"
|
||||||
derive_more = { version = "2.1", features = ["full"] }
|
derive_more = { version = "2.1", features = ["full"] }
|
||||||
|
num-traits = "0.2"
|
||||||
serde = { version = "1", features = ["derive", "rc"] }
|
serde = { version = "1", features = ["derive", "rc"] }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
undoredo = { version = "0.10", features = ["derive", "bidimap", "stable-vec", "rstar"] }
|
undoredo = { version = "0.10", features = ["derive", "bidimap", "stable-vec", "rstar"] }
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,11 @@ impl Display {
|
||||||
let layout = board.layout();
|
let layout = board.layout();
|
||||||
|
|
||||||
// Start from the bottom layer so that top layers are drawn on top.
|
// 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()] {
|
if !workspace.appearance_panel.visible[layer.index()] {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -212,7 +216,10 @@ impl Display {
|
||||||
let board = workspace.workspace.board();
|
let board = workspace.workspace.board();
|
||||||
let layout = board.layout();
|
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()] {
|
if !workspace.appearance_panel.visible[layer.index()] {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +301,10 @@ impl Display {
|
||||||
};
|
};
|
||||||
let autorouter = &autorouter_workspace.autorouter;
|
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()] {
|
if workspace.appearance_panel.visible[layer.index()] {
|
||||||
for navmesh in autorouter
|
for navmesh in autorouter
|
||||||
.router()
|
.router()
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ impl LayersPanel {
|
||||||
Self {
|
Self {
|
||||||
dark_colors,
|
dark_colors,
|
||||||
light_colors,
|
light_colors,
|
||||||
active: LayerId::new(0),
|
active: board.layer_id("F.Cu").unwrap_or(LayerId::new(0)),
|
||||||
visible,
|
visible,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -207,4 +207,17 @@ impl LayersPanel {
|
||||||
self.colors(ctx).layers.colors(layer_desc).normal
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ dearcut = { version = "0.3", features = ["serde", "undoredo"] }
|
||||||
derive-getters.workspace = true
|
derive-getters.workspace = true
|
||||||
derive_more.workspace = true
|
derive_more.workspace = true
|
||||||
i_triangle = "0.40"
|
i_triangle = "0.40"
|
||||||
|
num-traits.workspace = true
|
||||||
polygon_unionfind = "0.7"
|
polygon_unionfind = "0.7"
|
||||||
rstar = "0.12"
|
rstar = "0.12"
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,12 @@ impl DragSelectionInteractor {
|
||||||
SelectionContainMode::Crossing => {
|
SelectionContainMode::Crossing => {
|
||||||
self.selection
|
self.selection
|
||||||
.components
|
.components
|
||||||
.add(board.locate_components_intersecting_rect(rect));
|
.add(board.locate_components_prefer_layer_intersecting_rect(rect));
|
||||||
}
|
}
|
||||||
SelectionContainMode::Window => {
|
SelectionContainMode::Window => {
|
||||||
self.selection
|
self.selection
|
||||||
.components
|
.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 => {
|
SelectionContainMode::Crossing => {
|
||||||
self.selection
|
self.selection
|
||||||
.nets
|
.nets
|
||||||
.add(board.locate_nets_intersecting_rect(rect));
|
.add(board.locate_nets_prefer_layer_intersecting_rect(rect));
|
||||||
}
|
}
|
||||||
SelectionContainMode::Window => {
|
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 => {
|
SelectionContainMode::Crossing => {
|
||||||
self.selection
|
self.selection
|
||||||
.pins
|
.pins
|
||||||
.add(board.locate_pins_intersecting_rect(rect));
|
.add(board.locate_pins_prefer_layer_intersecting_rect(rect));
|
||||||
}
|
}
|
||||||
SelectionContainMode::Window => {
|
SelectionContainMode::Window => {
|
||||||
self.selection.pins.add(board.locate_pins_inside_rect(rect));
|
self.selection
|
||||||
|
.pins
|
||||||
|
.add(board.locate_pins_prefer_layer_inside_rect(rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,25 +47,16 @@ impl SelectionInteractor {
|
||||||
|
|
||||||
if input.release && input.pointer == self.origin {
|
if input.release && input.pointer == self.origin {
|
||||||
let mut selection = self.original_selection.clone();
|
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.
|
// Pins have intentional precedence over nets and components.
|
||||||
if let Some(pin_selector) = board.locate_pin_at_point(Vector3::new(
|
if let Some(pin_selector) = board.locate_pins_prefer_layer_at_point(point).next() {
|
||||||
input.pointer.x,
|
|
||||||
input.pointer.y,
|
|
||||||
layer.index() as i64,
|
|
||||||
)) {
|
|
||||||
selection.pins.xor(std::iter::once(pin_selector));
|
selection.pins.xor(std::iter::once(pin_selector));
|
||||||
} else if let Some(net_selector) = board.locate_net_at_point(Vector3::new(
|
} else if let Some(net_selector) = board.locate_nets_prefer_layer_at_point(point).next() {
|
||||||
input.pointer.x,
|
|
||||||
input.pointer.y,
|
|
||||||
layer.index() as i64,
|
|
||||||
)) {
|
|
||||||
selection.nets.xor(std::iter::once(net_selector));
|
selection.nets.xor(std::iter::once(net_selector));
|
||||||
} else if let Some(component_selector) = board.locate_component_at_point(Vector3::new(
|
} else if let Some(component_selector) =
|
||||||
input.pointer.x,
|
board.locate_components_prefer_layer_at_point(point).next()
|
||||||
input.pointer.y,
|
{
|
||||||
layer.index() as i64,
|
|
||||||
)) {
|
|
||||||
selection
|
selection
|
||||||
.components
|
.components
|
||||||
.xor(std::iter::once(component_selector));
|
.xor(std::iter::once(component_selector));
|
||||||
|
|
|
||||||
|
|
@ -11,24 +11,76 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
pub fn locate_component_at_point(&self, point: Vector3<i64>) -> Option<ComponentSelector> {
|
pub fn locate_components_prefer_layer_at_point(
|
||||||
if let Some(joint_id) = self.layout.locate_joints_at_point(point).next() {
|
&self,
|
||||||
return self.joint_component_selector(joint_id);
|
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() {
|
pub fn locate_components_at_point(
|
||||||
return self.segment_component_selector(segment_id);
|
&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() {
|
pub fn locate_components_prefer_layer_intersecting_rect(
|
||||||
return self.via_component_selector(via_id);
|
&self,
|
||||||
}
|
rect: Rect3<i64>,
|
||||||
|
) -> impl Iterator<Item = ComponentSelector> + '_ {
|
||||||
if let Some(polygon_id) = self.layout.locate_polygons_at_point(point).next() {
|
self.layout
|
||||||
return self.polygon_component_selector(polygon_id);
|
.locate_joints_prefer_layer_intersecting_rect(rect)
|
||||||
}
|
.filter_map(|joint_id| self.joint_component_selector(joint_id))
|
||||||
|
.chain(
|
||||||
None
|
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(
|
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(
|
pub fn locate_components_inside_rect(
|
||||||
&self,
|
&self,
|
||||||
rect: Rect3<i64>,
|
rect: Rect3<i64>,
|
||||||
) -> impl Iterator<Item = ComponentSelector> + '_ {
|
) -> impl Iterator<Item = ComponentSelector> + '_ {
|
||||||
self.layout
|
self.layout
|
||||||
.locate_joints_inside_rect(rect)
|
.locate_joints_prefer_layer_inside_rect(rect)
|
||||||
.filter_map(|joint_id| self.joint_component_selector(joint_id))
|
.filter_map(|joint_id| self.joint_component_selector(joint_id))
|
||||||
.chain(
|
.chain(
|
||||||
self.layout
|
self.layout
|
||||||
.locate_segments_inside_rect(rect)
|
.locate_segments_prefer_layer_inside_rect(rect)
|
||||||
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
|
.filter_map(|segment_id| self.segment_component_selector(segment_id)),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.layout
|
self.layout
|
||||||
.locate_vias_inside_rect(rect)
|
.locate_vias_prefer_layer_inside_rect(rect)
|
||||||
.filter_map(|via_id| self.via_component_selector(via_id)),
|
.filter_map(|via_id| self.via_component_selector(via_id)),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.layout
|
self.layout
|
||||||
.locate_polygons_inside_rect(rect)
|
.locate_polygons_prefer_layer_inside_rect(rect)
|
||||||
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
|
.filter_map(|polygon_id| self.polygon_component_selector(polygon_id)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_net_at_point(&self, point: Vector3<i64>) -> Option<NetSelector> {
|
pub fn locate_nets_prefer_layer_at_point(
|
||||||
if let Some(joint_id) = self.layout.locate_joints_at_point(point).next() {
|
&self,
|
||||||
return self.joint_net_selector(joint_id);
|
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() {
|
selectors.into_iter()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_nets_intersecting_rect(
|
pub fn locate_nets_intersecting_rect(
|
||||||
|
|
@ -116,6 +237,23 @@ impl Board {
|
||||||
selectors.into_iter()
|
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(
|
pub fn locate_nets_inside_rect(
|
||||||
&self,
|
&self,
|
||||||
rect: Rect3<i64>,
|
rect: Rect3<i64>,
|
||||||
|
|
@ -133,25 +271,76 @@ impl Board {
|
||||||
selectors.into_iter()
|
selectors.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_pin_at_point(&self, point: Vector3<i64>) -> Option<PinSelector> {
|
pub fn locate_pins_prefer_layer_at_point(
|
||||||
// Polygons have intentional precedence for pins.
|
&self,
|
||||||
if let Some(polygon_id) = self.layout.locate_polygons_at_point(point).next() {
|
point: Vector3<i64>,
|
||||||
return self.polygon_pin_selector(polygon_id);
|
) -> 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() {
|
pub fn locate_pins_at_point(
|
||||||
return self.joint_pin_selector(joint_id);
|
&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() {
|
pub fn locate_pins_prefer_layer_intersecting_rect(
|
||||||
return self.segment_pin_selector(segment_id);
|
&self,
|
||||||
}
|
rect: Rect3<i64>,
|
||||||
|
) -> impl Iterator<Item = PinSelector> + '_ {
|
||||||
if let Some(via_id) = self.layout.locate_vias_at_point(point).next() {
|
self.layout
|
||||||
return self.via_pin_selector(via_id);
|
.locate_polygons_prefer_layer_intersecting_rect(rect)
|
||||||
}
|
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id))
|
||||||
|
.chain(
|
||||||
None
|
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(
|
pub fn locate_pins_intersecting_rect(
|
||||||
|
|
@ -159,8 +348,13 @@ impl Board {
|
||||||
rect: Rect3<i64>,
|
rect: Rect3<i64>,
|
||||||
) -> impl Iterator<Item = PinSelector> + '_ {
|
) -> impl Iterator<Item = PinSelector> + '_ {
|
||||||
self.layout
|
self.layout
|
||||||
.locate_joints_intersecting_rect(rect)
|
.locate_polygons_intersecting_rect(rect)
|
||||||
.filter_map(|joint_id| self.joint_pin_selector(joint_id))
|
.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(
|
.chain(
|
||||||
self.layout
|
self.layout
|
||||||
.locate_segments_intersecting_rect(rect)
|
.locate_segments_intersecting_rect(rect)
|
||||||
|
|
@ -171,10 +365,29 @@ impl Board {
|
||||||
.locate_vias_intersecting_rect(rect)
|
.locate_vias_intersecting_rect(rect)
|
||||||
.filter_map(|via_id| self.via_pin_selector(via_id)),
|
.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(
|
.chain(
|
||||||
self.layout
|
self.layout
|
||||||
.locate_polygons_intersecting_rect(rect)
|
.locate_joints_prefer_layer_inside_rect(rect)
|
||||||
.filter_map(|polygon_id| self.polygon_pin_selector(polygon_id)),
|
.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>,
|
rect: Rect3<i64>,
|
||||||
) -> impl Iterator<Item = PinSelector> + '_ {
|
) -> impl Iterator<Item = PinSelector> + '_ {
|
||||||
self.layout
|
self.layout
|
||||||
.locate_joints_inside_rect(rect)
|
.locate_polygons_inside_rect(rect)
|
||||||
.filter_map(|joint_id| self.joint_pin_selector(joint_id))
|
.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(
|
.chain(
|
||||||
self.layout
|
self.layout
|
||||||
.locate_segments_inside_rect(rect)
|
.locate_segments_inside_rect(rect)
|
||||||
|
|
@ -195,10 +413,5 @@ impl Board {
|
||||||
.locate_vias_inside_rect(rect)
|
.locate_vias_inside_rect(rect)
|
||||||
.filter_map(|via_id| self.via_pin_selector(via_id)),
|
.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)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,64 @@
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Rect3, Vector3,
|
Rect2, Rect3, Vector2, Vector3,
|
||||||
layout::{LayerId, Layout, compounds::NetId},
|
layout::{Layout, compounds::NetId},
|
||||||
primitives::{JointId, PolygonId, SegmentId, ViaId},
|
primitives::{JointId, PolygonId, SegmentId, ViaId},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Layout {
|
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> {
|
pub fn locate_joints_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = JointId> {
|
||||||
let point2 = point.xy();
|
|
||||||
self.joints_rtree
|
self.joints_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point.x, point.y, point.z])
|
.locate_all_at_point(&[point.x, point.y, point.z])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.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 envelope = point.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_rect
|
||||||
|
};
|
||||||
|
|
||||||
|
joints.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_joints_intersecting_rect(
|
pub fn locate_joints_intersecting_rect(
|
||||||
|
|
@ -26,33 +71,128 @@ impl Layout {
|
||||||
) -> impl Iterator<Item = JointId> {
|
) -> impl Iterator<Item = JointId> {
|
||||||
self.joints_rtree
|
self.joints_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope_intersecting(&rect.aabb3())
|
.locate_in_envelope_intersecting(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&joint_id| {
|
.filter(move |&joint_id| {
|
||||||
let joint = self.joint(joint_id);
|
let joint = self.joint(joint_id);
|
||||||
rect.rect2()
|
rect.xy()
|
||||||
.intersects_circle(joint.spec.position, joint.spec.radius as i64)
|
.intersects_circle(joint.spec.position, joint.spec.radius as i64)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_joints_any_layer_intersecting_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = JointId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_rect
|
||||||
|
};
|
||||||
|
|
||||||
|
joints.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locate_joints_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = JointId> {
|
pub fn locate_joints_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = JointId> {
|
||||||
self.joints_rtree
|
self.joints_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope(&rect.aabb3())
|
.locate_in_envelope(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&joint_id| {
|
.filter(move |&joint_id| {
|
||||||
let joint = self.joint(joint_id);
|
let joint = self.joint(joint_id);
|
||||||
rect.rect2()
|
rect.xy()
|
||||||
.contains_circle(joint.spec.position, joint.spec.radius as i64)
|
.contains_circle(joint.spec.position, joint.spec.radius as i64)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_joints_any_layer_inside_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = JointId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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> {
|
pub fn locate_segments_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = SegmentId> {
|
||||||
self.segments_rtree
|
self.segments_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point.x, point.y, point.z])
|
.locate_all_at_point(&[point.x, point.y, point.z])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.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 envelope = point.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_point
|
||||||
|
};
|
||||||
|
|
||||||
|
joints.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_segments_intersecting_rect(
|
pub fn locate_segments_intersecting_rect(
|
||||||
|
|
@ -61,66 +201,251 @@ impl Layout {
|
||||||
) -> impl Iterator<Item = SegmentId> {
|
) -> impl Iterator<Item = SegmentId> {
|
||||||
self.segments_rtree
|
self.segments_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope_intersecting(&rect.aabb3())
|
.locate_in_envelope_intersecting(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&segment_id| {
|
.filter(move |&segment_id| {
|
||||||
let segment = self.segment(segment_id);
|
let segment = self.segment(segment_id);
|
||||||
rect.rect2()
|
rect.xy().intersects_polygon(&segment.bounding_rectangle())
|
||||||
.intersects_polygon(&segment.bounding_rectangle())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_segments_any_layer_intersecting_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = SegmentId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_point
|
||||||
|
};
|
||||||
|
|
||||||
|
joints.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locate_segments_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = SegmentId> {
|
pub fn locate_segments_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = SegmentId> {
|
||||||
self.segments_rtree
|
self.segments_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope(&rect.aabb3())
|
.locate_in_envelope(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&segment_id| {
|
.filter(move |&segment_id| {
|
||||||
let segment = self.segment(segment_id);
|
let segment = self.segment(segment_id);
|
||||||
rect.rect2().contains_polygon(&segment.bounding_rectangle())
|
rect.xy().contains_polygon(&segment.bounding_rectangle())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_segments_any_layer_inside_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = SegmentId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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> {
|
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
|
self.vias_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point.x, point.y, point.z])
|
.locate_all_at_point(&[point.x, point.y, point.z])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.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 envelope = point.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_point
|
||||||
|
};
|
||||||
|
|
||||||
|
vias.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_vias_intersecting_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
|
pub fn locate_vias_intersecting_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
|
||||||
self.vias_rtree
|
self.vias_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope_intersecting(&rect.aabb3())
|
.locate_in_envelope_intersecting(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&via_id| {
|
.filter(move |&via_id| {
|
||||||
let via = self.via(via_id);
|
let via = self.via(via_id);
|
||||||
rect.rect2()
|
rect.xy()
|
||||||
.intersects_circle(via.position, via.spec.radius as i64)
|
.intersects_circle(via.position, via.spec.radius as i64)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_vias_any_layer_intersecting_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = ViaId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy()).collect()
|
||||||
|
} else {
|
||||||
|
at_rect
|
||||||
|
};
|
||||||
|
|
||||||
|
vias.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locate_vias_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
|
pub fn locate_vias_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = ViaId> {
|
||||||
self.vias_rtree
|
self.vias_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope(&rect.aabb3())
|
.locate_in_envelope(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&via_id| {
|
.filter(move |&via_id| {
|
||||||
let via = self.via(via_id);
|
let via = self.via(via_id);
|
||||||
rect.rect2()
|
rect.xy()
|
||||||
.contains_circle(via.position, via.spec.radius as i64)
|
.contains_circle(via.position, via.spec.radius as i64)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_vias_any_layer_inside_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = ViaId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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> {
|
pub fn locate_polygons_at_point(&self, point: Vector3<i64>) -> impl Iterator<Item = PolygonId> {
|
||||||
let point2 = point.xy();
|
|
||||||
self.polygons_rtree
|
self.polygons_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point.x, point.y, point.z])
|
.locate_all_at_point(&[point.x, point.y, point.z])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.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 envelope = point.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_rect
|
||||||
|
};
|
||||||
|
|
||||||
|
polygons.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate_polygons_intersecting_rect(
|
pub fn locate_polygons_intersecting_rect(
|
||||||
|
|
@ -129,25 +454,98 @@ impl Layout {
|
||||||
) -> impl Iterator<Item = PolygonId> {
|
) -> impl Iterator<Item = PolygonId> {
|
||||||
self.polygons_rtree
|
self.polygons_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope_intersecting(&rect.aabb3())
|
.locate_in_envelope_intersecting(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&polygon_id| {
|
.filter(move |&polygon_id| {
|
||||||
let polygon = self.polygon(polygon_id);
|
let polygon = self.polygon(polygon_id);
|
||||||
rect.rect2().intersects_polygon(&polygon.vertices)
|
rect.xy().intersects_polygon(&polygon.vertices)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_polygons_any_layer_intersecting_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = PolygonId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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.xy())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
at_rect
|
||||||
|
};
|
||||||
|
|
||||||
|
polygons.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locate_polygons_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = PolygonId> {
|
pub fn locate_polygons_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = PolygonId> {
|
||||||
self.polygons_rtree
|
self.polygons_rtree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_in_envelope(&rect.aabb3())
|
.locate_in_envelope(&rect.aabb())
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |&polygon_id| {
|
.filter(move |&polygon_id| {
|
||||||
let polygon = self.polygon(polygon_id);
|
let polygon = self.polygon(polygon_id);
|
||||||
rect.rect2().contains_polygon(&polygon.vertices)
|
rect.xy().contains_polygon(&polygon.vertices)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn locate_polygons_any_layer_inside_rect(
|
||||||
|
&self,
|
||||||
|
rect: Rect2<i64>,
|
||||||
|
) -> impl Iterator<Item = PolygonId> {
|
||||||
|
let envelope = rect.z_extruded_infinitely().aabb();
|
||||||
|
|
||||||
|
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> {
|
pub fn locate_nets_intersecting_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = NetId> {
|
||||||
let mut nets = BTreeSet::new();
|
let mut nets = BTreeSet::new();
|
||||||
|
|
||||||
|
|
@ -170,6 +568,31 @@ impl Layout {
|
||||||
nets.into_iter()
|
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> {
|
pub fn locate_nets_inside_rect(&self, rect: Rect3<i64>) -> impl Iterator<Item = NetId> {
|
||||||
let mut nets = BTreeSet::new();
|
let mut nets = BTreeSet::new();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.x - self.spec.position.x).pow(2) as u64
|
||||||
+ (point.y - self.spec.position.y).pow(2) as u64
|
+ (point.y - self.spec.position.y).pow(2) as u64
|
||||||
<= self.spec.radius.pow(2)
|
<= self.spec.radius.pow(2)
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ impl Polygon {
|
||||||
Vector2::<i64>::polygon_centroid(&self.vertices)
|
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)
|
point.inside_polygon(&self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ impl Segment {
|
||||||
(self.endpoints[0] + self.endpoints[1]) / 2
|
(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(
|
let vertices = crate::math::inflated_segment(
|
||||||
self.endpoints[0].x,
|
self.endpoints[0].x,
|
||||||
self.endpoints[0].y,
|
self.endpoints[0].y,
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,7 @@ pub struct Via {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Via {
|
impl Via {
|
||||||
pub fn contains_point(&self, layer: LayerId, point: Vector2<i64>) -> bool {
|
pub fn contains_point2(&self, point: Vector2<i64>) -> bool {
|
||||||
if layer < self.min_layer || layer > self.max_layer {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
(point.x - self.position.x).pow(2) as u64 + (point.y - self.position.y).pow(2) as u64
|
(point.x - self.position.x).pow(2) as u64 + (point.y - self.position.y).pow(2) as u64
|
||||||
<= self.spec.radius.pow(2)
|
<= self.spec.radius.pow(2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,37 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
use derive_getters::Getters;
|
use derive_getters::Getters;
|
||||||
|
use derive_more::Constructor;
|
||||||
|
use num_traits::Bounded;
|
||||||
use rstar::{AABB, RTreeNum};
|
use rstar::{AABB, RTreeNum};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{Vector2, Vector3};
|
use crate::{Vector2, Vector3};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Getters, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(
|
||||||
|
Clone, Constructor, Copy, Debug, Deserialize, Eq, Getters, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
)]
|
||||||
pub struct Rect2<T> {
|
pub struct Rect2<T> {
|
||||||
min: Vector2<T>,
|
pub min: Vector2<T>,
|
||||||
max: Vector2<T>,
|
pub max: Vector2<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy + Ord> Rect2<T> {
|
||||||
|
pub fn z_extruded(self, from: T, to: T) -> Rect3<T> {
|
||||||
|
Rect3 {
|
||||||
|
min: Vector3::new(self.min.x, self.min.y, std::cmp::min(from, to)),
|
||||||
|
max: Vector3::new(self.max.x, self.max.y, std::cmp::max(from, to)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Bounded + Copy> Rect2<T> {
|
||||||
|
pub fn z_extruded_infinitely(self) -> Rect3<T> {
|
||||||
|
Rect3 {
|
||||||
|
min: Vector3::new(self.min.x, self.min.y, Bounded::min_value()),
|
||||||
|
max: Vector3::new(self.max.x, self.max.y, Bounded::max_value()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy> Rect2<T> {
|
impl<T: Copy> Rect2<T> {
|
||||||
|
|
@ -25,18 +47,9 @@ impl<T: Copy> Rect2<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + Ord> Rect2<T> {
|
|
||||||
pub fn new(from: Vector2<T>, to: Vector2<T>) -> Self {
|
|
||||||
Self {
|
|
||||||
min: Vector2::new(std::cmp::min(from.x, to.x), std::cmp::min(from.y, to.y)),
|
|
||||||
max: Vector2::new(std::cmp::max(from.x, to.x), std::cmp::max(from.y, to.y)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RTreeNum> Rect2<T> {
|
impl<T: RTreeNum> Rect2<T> {
|
||||||
pub fn aabb3(self, z: T) -> AABB<[T; 3]> {
|
pub fn aabb(self) -> AABB<[T; 2]> {
|
||||||
AABB::from_corners([self.min.x, self.min.y, z], [self.max.x, self.max.y, z])
|
AABB::from_corners([self.min.x, self.min.y], [self.max.x, self.max.y])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,8 +185,8 @@ impl_rect2_intersects_polygon!(f64);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Getters, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Getters, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
pub struct Rect3<T> {
|
pub struct Rect3<T> {
|
||||||
min: Vector3<T>,
|
pub min: Vector3<T>,
|
||||||
max: Vector3<T>,
|
pub max: Vector3<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Ord + Copy> Rect3<T> {
|
impl<T: Ord + Copy> Rect3<T> {
|
||||||
|
|
@ -194,13 +207,13 @@ impl<T: Ord + Copy> Rect3<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + Ord> Rect3<T> {
|
impl<T: Copy + Ord> Rect3<T> {
|
||||||
pub fn rect2(&self) -> Rect2<T> {
|
pub fn xy(self) -> Rect2<T> {
|
||||||
Rect2::new(self.min.xy(), self.max.xy())
|
Rect2::new(self.min.xy(), self.max.xy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RTreeNum> Rect3<T> {
|
impl<T: RTreeNum> Rect3<T> {
|
||||||
pub fn aabb3(&self) -> AABB<[T; 3]> {
|
pub fn aabb(self) -> AABB<[T; 3]> {
|
||||||
AABB::from_corners(
|
AABB::from_corners(
|
||||||
[self.min.x, self.min.y, self.min.z],
|
[self.min.x, self.min.y, self.min.z],
|
||||||
[self.max.x, self.max.y, self.max.z],
|
[self.max.x, self.max.y, self.max.z],
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,11 @@
|
||||||
use derive_more::{
|
use derive_more::{
|
||||||
Add, AddAssign, Constructor, Div, DivAssign, From, Into, Mul, MulAssign, Sub, SubAssign,
|
Add, AddAssign, Constructor, Div, DivAssign, From, Into, Mul, MulAssign, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
|
use num_traits::Bounded;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::Rect3;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Add,
|
Add,
|
||||||
AddAssign,
|
AddAssign,
|
||||||
|
|
@ -34,40 +37,6 @@ pub struct Vector2<T> {
|
||||||
pub y: T,
|
pub y: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Add,
|
|
||||||
AddAssign,
|
|
||||||
Clone,
|
|
||||||
Constructor,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
Deserialize,
|
|
||||||
Div,
|
|
||||||
DivAssign,
|
|
||||||
Eq,
|
|
||||||
From,
|
|
||||||
Into,
|
|
||||||
Mul,
|
|
||||||
MulAssign,
|
|
||||||
Ord,
|
|
||||||
PartialEq,
|
|
||||||
PartialOrd,
|
|
||||||
Serialize,
|
|
||||||
Sub,
|
|
||||||
SubAssign,
|
|
||||||
)]
|
|
||||||
pub struct Vector3<T> {
|
|
||||||
pub x: T,
|
|
||||||
pub y: T,
|
|
||||||
pub z: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Copy> Vector3<T> {
|
|
||||||
pub fn xy(self) -> Vector2<T> {
|
|
||||||
Vector2::new(self.x, self.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Copy> From<[T; 2]> for Vector2<T> {
|
impl<T: Copy> From<[T; 2]> for Vector2<T> {
|
||||||
fn from(from: [T; 2]) -> Self {
|
fn from(from: [T; 2]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -83,6 +52,24 @@ impl<T: Copy> From<Vector2<T>> for [T; 2] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Copy + Ord> Vector2<T> {
|
||||||
|
pub fn z_extruded(self, from: T, to: T) -> Rect3<T> {
|
||||||
|
Rect3 {
|
||||||
|
min: Vector3::new(self.x, self.y, std::cmp::min(from, to)),
|
||||||
|
max: Vector3::new(self.x, self.y, std::cmp::max(from, to)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Bounded + Copy> Vector2<T> {
|
||||||
|
pub fn z_extruded_infinitely(self) -> Rect3<T> {
|
||||||
|
Rect3 {
|
||||||
|
min: Vector3::new(self.x, self.y, Bounded::min_value()),
|
||||||
|
max: Vector3::new(self.x, self.y, Bounded::max_value()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_vector2_inside_polygon {
|
macro_rules! impl_vector2_inside_polygon {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
impl Vector2<$type> {
|
impl Vector2<$type> {
|
||||||
|
|
@ -216,3 +203,37 @@ impl_polygon_centroid!(u32);
|
||||||
impl_polygon_centroid!(u64);
|
impl_polygon_centroid!(u64);
|
||||||
impl_polygon_centroid!(f32);
|
impl_polygon_centroid!(f32);
|
||||||
impl_polygon_centroid!(f64);
|
impl_polygon_centroid!(f64);
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Add,
|
||||||
|
AddAssign,
|
||||||
|
Clone,
|
||||||
|
Constructor,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
Deserialize,
|
||||||
|
Div,
|
||||||
|
DivAssign,
|
||||||
|
Eq,
|
||||||
|
From,
|
||||||
|
Into,
|
||||||
|
Mul,
|
||||||
|
MulAssign,
|
||||||
|
Ord,
|
||||||
|
PartialEq,
|
||||||
|
PartialOrd,
|
||||||
|
Serialize,
|
||||||
|
Sub,
|
||||||
|
SubAssign,
|
||||||
|
)]
|
||||||
|
pub struct Vector3<T> {
|
||||||
|
pub x: T,
|
||||||
|
pub y: T,
|
||||||
|
pub z: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy> Vector3<T> {
|
||||||
|
pub fn xy(self) -> Vector2<T> {
|
||||||
|
Vector2::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue