Cache polygon centroids to speed up annealing

This commit is contained in:
Mikolaj Wielgus 2026-06-07 20:52:28 +02:00
parent 1433c02d81
commit ec8b72823c
18 changed files with 87 additions and 75 deletions

View File

@ -156,9 +156,9 @@ impl Display {
polygon, polygon,
workspace.appearance_panel.layer_color( workspace.appearance_panel.layer_color(
ctx, ctx,
board.layer_desc(polygon.layer), board.layer_desc(polygon.spec.layer),
pin_selected, pin_selected,
(polygon.pin.is_none() && net_selected) || component_selected, (polygon.spec.pin.is_none() && net_selected) || component_selected,
), ),
); );
} }
@ -233,7 +233,7 @@ impl Display {
color: egui::Color32, color: egui::Color32,
) { ) {
let points: Vec<egui::Pos2> = polygon let points: Vec<egui::Pos2> = polygon
.vertices .spec.vertices
.iter() .iter()
.map(|v| egui::pos2(v.x as f32, v.y as f32)) .map(|v| egui::pos2(v.x as f32, v.y as f32))
.collect(); .collect();

View File

@ -97,7 +97,7 @@ impl Board {
pub fn nets_contain_polygon(&self, selection: &NetSelection, id: PolygonId) -> bool { pub fn nets_contain_polygon(&self, selection: &NetSelection, id: PolygonId) -> bool {
let polygon = self.layout.polygon(id); let polygon = self.layout.polygon(id);
let Some(net_name) = polygon.net.and_then(|net| self.net_name(net)) else { let Some(net_name) = polygon.spec.net.and_then(|net| self.net_name(net)) else {
return false; return false;
}; };

View File

@ -76,7 +76,7 @@ impl Interactor for DragSelectInteractor {
&& board && board
.layout() .layout()
.locate_polygons_prefer_layer_intersecting_rect(rect) .locate_polygons_prefer_layer_intersecting_rect(rect)
.all(|polygon_id| board.layout().polygon(polygon_id).pin.is_some()) .all(|polygon_id| board.layout().polygon(polygon_id).spec.pin.is_some())
} }
SelectionContainMode::Window => { SelectionContainMode::Window => {
board board
@ -94,7 +94,7 @@ impl Interactor for DragSelectInteractor {
&& board && board
.layout() .layout()
.locate_polygons_prefer_layer_inside_rect(rect) .locate_polygons_prefer_layer_inside_rect(rect)
.all(|polygon_id| board.layout().polygon(polygon_id).pin.is_some()) .all(|polygon_id| board.layout().polygon(polygon_id).spec.pin.is_some())
} }
}; };

View File

@ -62,7 +62,7 @@ impl Board {
} }
for polygon_id in self.layout.layer_polygons(layer_id) { for polygon_id in self.layout.layer_polygons(layer_id) {
if self.layout.polygon(polygon_id).pin != Some(pin_id) { if self.layout.polygon(polygon_id).spec.pin != Some(pin_id) {
continue; continue;
} }
@ -105,7 +105,7 @@ impl Board {
let polygon = self.layout.polygon(id); let polygon = self.layout.polygon(id);
Some(ComponentSelector { Some(ComponentSelector {
component: self.component_name(polygon.component?)?.to_string(), component: self.component_name(polygon.spec.component?)?.to_string(),
}) })
} }
@ -137,7 +137,7 @@ impl Board {
let polygon = self.layout.polygon(id); let polygon = self.layout.polygon(id);
Some(NetSelector { Some(NetSelector {
net: self.net_name(polygon.net?)?.to_string(), net: self.net_name(polygon.spec.net?)?.to_string(),
}) })
} }
@ -172,8 +172,8 @@ impl Board {
let polygon = self.layout.polygon(id); let polygon = self.layout.polygon(id);
Some(PinSelector { Some(PinSelector {
pin: self.pin_name(polygon.pin?)?.to_string(), pin: self.pin_name(polygon.spec.pin?)?.to_string(),
layer: self.layer_name(polygon.layer)?, layer: self.layer_name(polygon.spec.layer)?,
}) })
} }
} }

View File

@ -35,7 +35,7 @@ impl Board {
for polygon_id in self for polygon_id in self
.resolve_net_polygons(selection.clone()) .resolve_net_polygons(selection.clone())
.filter(|&polygon_id| self.layout.polygon(polygon_id).pin.is_none()) .filter(|&polygon_id| self.layout.polygon(polygon_id).spec.pin.is_none())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.clone() .clone()
{ {

View File

@ -101,7 +101,7 @@ impl Layout {
count += 1; count += 1;
} }
for &polygon_id in &pin.polygons { for &polygon_id in &pin.polygons {
sum = sum + self.polygon(polygon_id).center(); sum = sum + self.polygon(polygon_id).centroid;
count += 1; count += 1;
} }

View File

@ -98,8 +98,8 @@ impl Layout {
pub fn delete_polygon(&mut self, polygon_id: PolygonId) { pub fn delete_polygon(&mut self, polygon_id: PolygonId) {
let polygon = self.polygon(polygon_id); let polygon = self.polygon(polygon_id);
let bbox = polygon.bbox(); let bbox = polygon.bbox();
let component = polygon.component; let component = polygon.spec.component;
let pin = polygon.pin; let pin = polygon.spec.pin;
if let Some(component_id) = component { if let Some(component_id) = component {
self.components.modify(component_id.index(), |component| { self.components.modify(component_id.index(), |component| {

View File

@ -431,7 +431,7 @@ impl Layout {
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.component, PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.component,
PrimitiveId::Segment(segment_id) => self.segment(segment_id).spec.component, PrimitiveId::Segment(segment_id) => self.segment(segment_id).spec.component,
PrimitiveId::Via(via_id) => self.via(via_id).spec.component, PrimitiveId::Via(via_id) => self.via(via_id).spec.component,
PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).component, PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).spec.component,
} }
} }
@ -449,7 +449,7 @@ impl Layout {
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.net, PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.net,
PrimitiveId::Segment(segment_id) => self.segment(segment_id).net, PrimitiveId::Segment(segment_id) => self.segment(segment_id).net,
PrimitiveId::Via(via_id) => self.via(via_id).net, PrimitiveId::Via(via_id) => self.via(via_id).net,
PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).net, PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).spec.net,
} }
} }

View File

@ -147,8 +147,8 @@ impl Layout {
pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId { pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId {
let bbox = polygon.bbox(); let bbox = polygon.bbox();
let component_id = polygon.component; let component_id = polygon.spec.component;
let pin_id = polygon.pin; let pin_id = polygon.spec.pin;
let polygon_id = PolygonId::new(self.polygons.push(polygon)); let polygon_id = PolygonId::new(self.polygons.push(polygon));
self.polygons_rtree self.polygons_rtree

View File

@ -462,7 +462,7 @@ impl Layout {
.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.xy().intersects_polygon(&polygon.vertices) rect.xy().intersects_polygon(&polygon.spec.vertices)
}) })
} }
@ -478,7 +478,7 @@ impl Layout {
.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.intersects_polygon(&polygon.vertices) rect.intersects_polygon(&polygon.spec.vertices)
}) })
} }
@ -505,7 +505,7 @@ impl Layout {
.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.xy().contains_polygon(&polygon.vertices) rect.xy().contains_polygon(&polygon.spec.vertices)
}) })
} }
@ -521,7 +521,7 @@ impl Layout {
.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.contains_polygon(&polygon.vertices) rect.contains_polygon(&polygon.spec.vertices)
}) })
} }
@ -550,7 +550,7 @@ impl Layout {
} }
for polygon_id in self.locate_polygons_prefer_layer_intersecting_rect(rect) { for polygon_id in self.locate_polygons_prefer_layer_intersecting_rect(rect) {
if let Some(net) = self.polygon(polygon_id).net { if let Some(net) = self.polygon(polygon_id).spec.net {
nets.insert(net); nets.insert(net);
} }
} }
@ -580,7 +580,7 @@ impl Layout {
} }
for polygon_id in self.locate_polygons_intersecting_rect(rect) { for polygon_id in self.locate_polygons_intersecting_rect(rect) {
if let Some(net) = self.polygon(polygon_id).net { if let Some(net) = self.polygon(polygon_id).spec.net {
nets.insert(net); nets.insert(net);
} }
} }
@ -613,7 +613,7 @@ impl Layout {
} }
for polygon_id in self.locate_polygons_prefer_layer_inside_rect(rect) { for polygon_id in self.locate_polygons_prefer_layer_inside_rect(rect) {
if let Some(net) = self.polygon(polygon_id).net { if let Some(net) = self.polygon(polygon_id).spec.net {
nets.insert(net); nets.insert(net);
} }
} }
@ -643,7 +643,7 @@ impl Layout {
} }
for polygon_id in self.locate_polygons_inside_rect(rect) { for polygon_id in self.locate_polygons_inside_rect(rect) {
if let Some(net) = self.polygon(polygon_id).net { if let Some(net) = self.polygon(polygon_id).spec.net {
nets.insert(net); nets.insert(net);
} }
} }

View File

@ -158,7 +158,7 @@ impl Layout {
.as_ref() .as_ref()
.locate_in_envelope_intersecting(&envelope) .locate_in_envelope_intersecting(&envelope)
.map(|geom_with_data| geom_with_data.data) .map(|geom_with_data| geom_with_data.data)
.filter(move |&id| self.polygon(id).layer == layer) .filter(move |&id| self.polygon(id).spec.layer == layer)
} }
fn whole_layer_aabb(layer: LayerId) -> AABB<[i64; 3]> { fn whole_layer_aabb(layer: LayerId) -> AABB<[i64; 3]> {

View File

@ -34,7 +34,7 @@ impl Layout {
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.pin, PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.pin,
PrimitiveId::Segment(segment_id) => self.segment(segment_id).spec.pin, PrimitiveId::Segment(segment_id) => self.segment(segment_id).spec.pin,
PrimitiveId::Via(via_id) => self.via(via_id).spec.pin, PrimitiveId::Via(via_id) => self.via(via_id).spec.pin,
PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).pin, PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).spec.pin,
} }
} }

View File

@ -34,7 +34,7 @@ impl PolygonId {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Polygon { pub struct PolygonSpec {
pub vertices: Vec<Vector2<i64>>, pub vertices: Vec<Vector2<i64>>,
pub layer: LayerId, pub layer: LayerId,
pub net: Option<NetId>, pub net: Option<NetId>,
@ -42,20 +42,26 @@ pub struct Polygon {
pub pin: Option<PinId>, pub pin: Option<PinId>,
} }
#[derive(Clone, Debug)]
pub struct Polygon {
pub spec: PolygonSpec,
pub centroid: Vector2<i64>,
}
impl Polygon { impl Polygon {
pub fn bbox(&self) -> Rect3<i64> { pub fn bbox(&self) -> Rect3<i64> {
let layer = self.layer.index() as i64; let layer = self.spec.layer.index() as i64;
let mut min = Vector2::new(i64::MAX, i64::MAX); let mut min = Vector2::new(i64::MAX, i64::MAX);
let mut max = Vector2::new(i64::MIN, i64::MIN); let mut max = Vector2::new(i64::MIN, i64::MIN);
for vertex in &self.vertices { for vertex in &self.spec.vertices {
min.x = std::cmp::min(min.x, vertex.x); min.x = std::cmp::min(min.x, vertex.x);
min.y = std::cmp::min(min.y, vertex.y); min.y = std::cmp::min(min.y, vertex.y);
max.x = std::cmp::max(max.x, vertex.x); max.x = std::cmp::max(max.x, vertex.x);
max.y = std::cmp::max(max.y, vertex.y); max.y = std::cmp::max(max.y, vertex.y);
} }
if self.vertices.is_empty() { if self.spec.vertices.is_empty() {
return Rect3::new(Vector3::new(0, 0, layer), Vector3::new(0, 0, layer)); return Rect3::new(Vector3::new(0, 0, layer), Vector3::new(0, 0, layer));
} }
@ -65,12 +71,7 @@ impl Polygon {
) )
} }
pub fn center(&self) -> Vector2<i64> {
crate::profile_function!();
Vector2::<i64>::polygon_centroid(&self.vertices)
}
pub fn contains_point2(&self, point: Vector2<i64>) -> bool { pub fn contains_point2(&self, point: Vector2<i64>) -> bool {
point.inside_polygon(&self.vertices) point.inside_polygon(&self.spec.vertices)
} }
} }

View File

@ -160,7 +160,7 @@ impl Layout {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.joint_polygon_rect_overlap(infringer, infringee), self.joint_polygon_rect_overlap(infringer, infringee),
self.joint(infringer).center(), self.joint(infringer).center(),
self.polygon(infringee).center(), self.polygon(infringee).centroid,
orientation, orientation,
) )
} }
@ -238,7 +238,7 @@ impl Layout {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.segment_polygon_rect_overlap(infringer, infringee), self.segment_polygon_rect_overlap(infringer, infringee),
self.segment(infringer).center(), self.segment(infringer).center(),
self.polygon(infringee).center(), self.polygon(infringee).centroid,
orientation, orientation,
) )
} }
@ -316,7 +316,7 @@ impl Layout {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.via_polygon_rect_overlap(infringer, infringee), self.via_polygon_rect_overlap(infringer, infringee),
self.via(infringer).position, self.via(infringer).position,
self.polygon(infringee).center(), self.polygon(infringee).centroid,
orientation, orientation,
) )
} }
@ -351,7 +351,7 @@ impl Layout {
) -> Vector2<i64> { ) -> Vector2<i64> {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.polygon_joint_rect_overlap(infringer, infringee), self.polygon_joint_rect_overlap(infringer, infringee),
self.polygon(infringer).center(), self.polygon(infringer).centroid,
self.joint(infringee).center(), self.joint(infringee).center(),
orientation, orientation,
) )
@ -365,7 +365,7 @@ impl Layout {
) -> Vector2<i64> { ) -> Vector2<i64> {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.polygon_segment_rect_overlap(infringer, infringee), self.polygon_segment_rect_overlap(infringer, infringee),
self.polygon(infringer).center(), self.polygon(infringer).centroid,
self.segment(infringee).center(), self.segment(infringee).center(),
orientation, orientation,
) )
@ -379,7 +379,7 @@ impl Layout {
) -> Vector2<i64> { ) -> Vector2<i64> {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.polygon_via_rect_overlap(infringer, infringee), self.polygon_via_rect_overlap(infringer, infringee),
self.polygon(infringer).center(), self.polygon(infringer).centroid,
self.via(infringee).position, self.via(infringee).position,
orientation, orientation,
) )
@ -393,8 +393,8 @@ impl Layout {
) -> Vector2<i64> { ) -> Vector2<i64> {
Self::repulsion_from_rect_overlap( Self::repulsion_from_rect_overlap(
self.polygon_polygon_rect_overlap(infringer, infringee), self.polygon_polygon_rect_overlap(infringer, infringee),
self.polygon(infringer).center(), self.polygon(infringer).centroid,
self.polygon(infringee).center(), self.polygon(infringee).centroid,
orientation, orientation,
) )
} }

View File

@ -32,9 +32,10 @@ impl Layout {
for &polygon_id in &component.polygons { for &polygon_id in &component.polygons {
self.modify_polygon(polygon_id, |polygon| { self.modify_polygon(polygon_id, |polygon| {
polygon polygon
.vertices .spec.vertices
.iter_mut() .iter_mut()
.for_each(|vertex| *vertex += translation) .for_each(|vertex| *vertex += translation);
polygon.centroid += translation;
}); });
} }
} }

View File

@ -236,7 +236,7 @@ impl NavmesherBoard {
this.polygon_multiobstacles.insert( this.polygon_multiobstacles.insert(
i, i,
this.navmesher this.navmesher
.insert_multiobstacle(polygon.layer, polygon.vertices.clone()), .insert_multiobstacle(polygon.spec.layer, polygon.spec.vertices.clone()),
); );
}*/ }*/
@ -293,7 +293,7 @@ impl NavmesherBoard {
self.polygon_multiobstacles.insert( self.polygon_multiobstacles.insert(
polygon_id.index(), polygon_id.index(),
self.navmesher self.navmesher
.insert_multiobstacle(polygon.layer, polygon.vertices), .insert_multiobstacle(polygon.spec.layer, polygon.spec.vertices),
); );
polygon_id polygon_id

View File

@ -86,19 +86,19 @@ impl Ratsnest {
} }
for (i, polygon) in board.layout().polygons().container().iter() { for (i, polygon) in board.layout().polygons().container().iter() {
let Some(net) = polygon.net else { let Some(net) = polygon.spec.net else {
continue; continue;
}; };
let _ = triangulations let _ = triangulations
.entry((net, polygon.layer)) .entry((net, polygon.spec.layer))
.or_insert_with(DelaunayTriangulation::new) .or_insert_with(DelaunayTriangulation::new)
.insert(DelaunayVertex { .insert(DelaunayVertex {
layer: polygon.layer, layer: polygon.spec.layer,
center: polygon.center(), center: polygon.centroid,
position: spade::Point2::new( position: spade::Point2::new(
polygon.center().x as f64, polygon.centroid.x as f64,
polygon.center().y as f64, polygon.centroid.y as f64,
), ),
primitive_id: PrimitiveId::Polygon(PolygonId::new(i)), primitive_id: PrimitiveId::Polygon(PolygonId::new(i)),
}); });

View File

@ -12,7 +12,7 @@ use specctra::{
use crate::{ use crate::{
board::{Board, LayerDesc, LayerSide, LayerType}, board::{Board, LayerDesc, LayerSide, LayerType},
layout::primitives::{JointSpec, Polygon, Segment, SegmentSpec}, layout::primitives::{JointSpec, Polygon, PolygonSpec, Segment, SegmentSpec},
layout::{ layout::{
LayerId, LayerId,
compounds::{ComponentId, NetId, PinId, PinSpec}, compounds::{ComponentId, NetId, PinId, PinSpec},
@ -383,17 +383,22 @@ impl Board {
flip: bool, flip: bool,
coordinate_scale: f64, coordinate_scale: f64,
) { ) {
board.insert_polygon(Polygon { board.insert_polygon({
vertices: vec![ let spec = PolygonSpec {
Self::pos(place, pin_pos, x1, y1, flip, coordinate_scale), vertices: vec![
Self::pos(place, pin_pos, x2, y1, flip, coordinate_scale), Self::pos(place, pin_pos, x1, y1, flip, coordinate_scale),
Self::pos(place, pin_pos, x2, y2, flip, coordinate_scale), Self::pos(place, pin_pos, x2, y1, flip, coordinate_scale),
Self::pos(place, pin_pos, x1, y2, flip, coordinate_scale), Self::pos(place, pin_pos, x2, y2, flip, coordinate_scale),
], Self::pos(place, pin_pos, x1, y2, flip, coordinate_scale),
layer, ],
net, layer,
component, net,
pin, component,
pin,
};
let centroid = Vector2::<i64>::polygon_centroid(&spec.vertices);
Polygon { spec, centroid }
}); });
} }
@ -477,12 +482,17 @@ impl Board {
.iter() .iter()
.map(|coord| Self::pos(place, pin_pos, coord.x, coord.y, flip, coordinate_scale)) .map(|coord| Self::pos(place, pin_pos, coord.x, coord.y, flip, coordinate_scale))
.collect(); .collect();
board.insert_polygon(Polygon { board.insert_polygon({
vertices, let spec = PolygonSpec {
layer, vertices,
net, layer,
component, net,
pin, component,
pin,
};
let centroid = Vector2::<i64>::polygon_centroid(&spec.vertices);
Polygon { spec, centroid }
}); });
} }