diff --git a/topola/Cargo.toml b/topola/Cargo.toml index d330eb8..714ee95 100644 --- a/topola/Cargo.toml +++ b/topola/Cargo.toml @@ -13,6 +13,7 @@ bimap = "0.6" dearcut = { version = "0.1", features = ["undoredo"] } derive-getters.workspace = true derive_more.workspace = true +rstar = "0.12" serde.workspace = true specctra = { path = "../specctra" } stable-vec = "0.4" diff --git a/topola/src/layout.rs b/topola/src/layout.rs index 7fc73cd..f6af321 100644 --- a/topola/src/layout.rs +++ b/topola/src/layout.rs @@ -6,6 +6,10 @@ use std::collections::BTreeMap; use derive_getters::{Dissolve, Getters}; use derive_more::Constructor; +use rstar::{ + RTree, + primitives::{GeomWithData, Rectangle}, +}; use serde::{Deserialize, Serialize}; use stable_vec::StableVec; use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder}; @@ -64,10 +68,16 @@ pub struct Layout { layer_count: usize, pins: StableVec, + joints: Recorder>, segments: Recorder>, vias: Recorder>, polygons: Recorder>, + + joints_rtree: Recorder, JointId>>>, + segments_rtree: Recorder, SegmentId>>>, + vias_rtree: Recorder, ViaId>>>, + polygons_rtree: Recorder, PolygonId>>>, } impl Layout { @@ -78,10 +88,16 @@ impl Layout { layer_count, pins: StableVec::new(), + joints: Recorder::new(StableVec::new()), segments: Recorder::new(StableVec::new()), vias: Recorder::new(StableVec::new()), polygons: Recorder::new(StableVec::new()), + + joints_rtree: Recorder::new(RTree::new()), + segments_rtree: Recorder::new(RTree::new()), + vias_rtree: Recorder::new(RTree::new()), + polygons_rtree: Recorder::new(RTree::new()), } } @@ -90,9 +106,13 @@ impl Layout { } pub fn add_joint(&mut self, joint: Joint) -> JointId { + let bbox = joint.bbox(); let pin_id = joint.pin; let joint_id = JointId::new(self.joints.push(joint)); + self.joints_rtree + .insert(GeomWithData::new(bbox, joint_id), ()); + if let Some(pin_id) = pin_id { self.pins[pin_id.id()].joints.push(joint_id); } @@ -103,6 +123,10 @@ impl Layout { pub fn add_segment(&mut self, segment: Segment) -> SegmentId { let pin_id = segment.pin; let segment_id = SegmentId::new(self.segments.push(segment)); + let bbox = self.segment_bbox(segment_id); + + self.segments_rtree + .insert(GeomWithData::new(bbox, segment_id), ()); if let Some(pin_id) = pin_id { self.pins[pin_id.id()].segments.push(segment_id); @@ -112,9 +136,12 @@ impl Layout { } pub fn add_via(&mut self, via: Via) -> ViaId { + //let bbox = via.bbox(); let pin_id = via.pin; let via_id = ViaId::new(self.vias.push(via)); + //self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ()); + if let Some(pin_id) = pin_id { self.pins[pin_id.id()].vias.push(via_id); } @@ -123,9 +150,13 @@ impl Layout { } pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId { + let bbox = polygon.bbox(); let pin_id = polygon.pin; let polygon_id = PolygonId::new(self.polygons.push(polygon)); + self.polygons_rtree + .insert(GeomWithData::new(bbox, polygon_id), ()); + if let Some(pin_id) = pin_id { self.pins[pin_id.id()].polygons.push(polygon_id); } @@ -133,14 +164,27 @@ impl Layout { polygon_id } - pub fn segment_endpoints(&self, segment: SegmentId) -> [[i64; 2]; 2] { - let endjoints = self.segments.get(&segment.id()).unwrap().endjoints; + pub fn segment_endpoints(&self, segment_id: SegmentId) -> [[i64; 2]; 2] { + let endjoints = self.segments.get(&segment_id.id()).unwrap().endjoints; [ self.joints.get(&endjoints[0].id()).unwrap().position, self.joints.get(&endjoints[1].id()).unwrap().position, ] } + pub fn segment_bbox(&self, segment_id: SegmentId) -> Rectangle<[i64; 3]> { + let endpoints = self.segment_endpoints(segment_id); + let layer = self.segments.get(&segment_id.id()).unwrap().layer as i64; + let half_width = self.segments.get(&segment_id.id()).unwrap().half_width as i64; + + let min_x = std::cmp::min(endpoints[0][0], endpoints[1][0]) - half_width; + let min_y = std::cmp::min(endpoints[0][1], endpoints[1][1]) - half_width; + let max_x = std::cmp::max(endpoints[0][0], endpoints[1][0]) + half_width; + let max_y = std::cmp::max(endpoints[0][1], endpoints[1][1]) + half_width; + + Rectangle::from_corners([min_x, min_y, layer], [max_x, max_y, layer]) + } + pub fn pin(&self, pin: PinId) -> &Pin { &self.pins[pin.id()] } diff --git a/topola/src/primitives.rs b/topola/src/primitives.rs index 76a21be..21d5d4b 100644 --- a/topola/src/primitives.rs +++ b/topola/src/primitives.rs @@ -2,7 +2,8 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use derive_more::{Constructor, From}; +use derive_more::Constructor; +use rstar::{AABB, Envelope, primitives::Rectangle}; use serde::{Deserialize, Serialize}; use crate::{ @@ -10,14 +11,6 @@ use crate::{ selection::PinSelector, }; -#[derive(Clone, Copy, Debug, Deserialize, Eq, From, Ord, PartialEq, PartialOrd, Serialize)] -pub enum PrimitiveId { - Joint(JointId), - Segment(SegmentId), - Via(ViaId), - Polygon(PolygonId), -} - #[derive( Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, )] @@ -41,6 +34,21 @@ pub struct Joint { } impl Joint { + pub fn bbox(&self) -> Rectangle<[i64; 3]> { + Rectangle::from_aabb(AABB::from_corners( + [ + self.position[0] - self.radius as i64, + self.position[1] - self.radius as i64, + self.layer as i64, + ], + [ + self.position[0] + self.radius as i64, + self.position[1] + self.radius as i64, + self.layer as i64, + ], + )) + } + pub fn pin_selector(&self) -> Option { Some(PinSelector { pin: self.pin?, @@ -95,7 +103,7 @@ impl ViaId { #[derive(Clone, Copy, Debug)] pub struct Via { - pub endpoints: [JointId; 2], + pub endjoints: [JointId; 2], pub layer: usize, // ??? This should be a range. pub radius: u64, pub net: NetId, @@ -103,6 +111,10 @@ pub struct Via { } impl Via { + /*pub fn bbox(&self) -> Rectangle<[i64; 3]> { + // + }*/ + pub fn pin_selector(&self) -> Option { Some(PinSelector { pin: self.pin?, @@ -133,6 +145,15 @@ pub struct Polygon { } impl Polygon { + pub fn bbox(&self) -> Rectangle<[i64; 3]> { + Rectangle::from_aabb(self.vertices.clone().into_iter().fold( + AABB::new_empty(), + |aabb, vertex| { + aabb.merged(&AABB::from_point([vertex[0], vertex[1], self.layer as i64])) + }, + )) + } + pub fn pin_selector(&self) -> Option { Some(PinSelector { pin: self.pin?,