From e536e940390fedd9e8205e8860272dd56a6e494e Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Mon, 18 May 2026 23:29:59 +0200 Subject: [PATCH] Add new type of compound, component --- topola/src/board.rs | 6 ++++- topola/src/compounds/component.rs | 39 +++++++++++++++++++++++++++++++ topola/src/compounds/mod.rs | 2 ++ topola/src/compounds/pin.rs | 8 +++---- topola/src/layout.rs | 36 +++++++++++++++++++++++++++- topola/src/primitives/joint.rs | 3 ++- topola/src/primitives/polygon.rs | 3 ++- topola/src/primitives/segment.rs | 3 ++- topola/src/primitives/via.rs | 3 ++- topola/src/specctra.rs | 23 ++++++++++++++++-- 10 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 topola/src/compounds/component.rs diff --git a/topola/src/board.rs b/topola/src/board.rs index f5bba03..1ec6929 100644 --- a/topola/src/board.rs +++ b/topola/src/board.rs @@ -7,7 +7,7 @@ use derive_getters::{Dissolve, Getters}; use undoredo::{ApplyDelta, Delta, FlushDelta}; use crate::{ - compounds::{NetId, PinId}, + compounds::{ComponentId, NetId, PinId}, layout::{Layout, LayoutHalfDelta}, math::Vector2, primitives::{ @@ -63,6 +63,10 @@ impl Board { pin_id } + pub fn add_component(&mut self) -> ComponentId { + self.layout.add_component() + } + pub fn add_joint(&mut self, spec: JointSpec) -> JointId { self.layout.add_joint(spec) } diff --git a/topola/src/compounds/component.rs b/topola/src/compounds/component.rs new file mode 100644 index 0000000..0379d97 --- /dev/null +++ b/topola/src/compounds/component.rs @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2026 Topola contributors +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use derive_more::Constructor; +use serde::{Deserialize, Serialize}; + +use crate::primitives::{JointId, PolygonId, SegmentId, ViaId}; + +#[derive( + Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, +)] +pub struct ComponentId(usize); + +impl ComponentId { + #[inline] + pub fn index(self) -> usize { + self.0 + } +} + +#[derive(Clone, Debug)] +pub struct Component { + pub joints: Vec, + pub segments: Vec, + pub vias: Vec, + pub polygons: Vec, +} + +impl Component { + pub fn new() -> Self { + Self { + joints: Vec::new(), + segments: Vec::new(), + vias: Vec::new(), + polygons: Vec::new(), + } + } +} diff --git a/topola/src/compounds/mod.rs b/topola/src/compounds/mod.rs index 3be1f75..4899ef6 100644 --- a/topola/src/compounds/mod.rs +++ b/topola/src/compounds/mod.rs @@ -2,8 +2,10 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +mod component; mod net; mod pin; +pub use component::{Component, ComponentId}; pub use net::NetId; pub use pin::{Pin, PinId}; diff --git a/topola/src/compounds/pin.rs b/topola/src/compounds/pin.rs index 18a15f6..35d2877 100644 --- a/topola/src/compounds/pin.rs +++ b/topola/src/compounds/pin.rs @@ -21,10 +21,10 @@ impl PinId { #[derive(Clone, Debug)] pub struct Pin { - pub(crate) joints: Vec, - pub(crate) segments: Vec, - pub(crate) vias: Vec, - pub(crate) polygons: Vec, + pub joints: Vec, + pub segments: Vec, + pub vias: Vec, + pub polygons: Vec, } impl Pin { diff --git a/topola/src/layout.rs b/topola/src/layout.rs index be152ec..ed8a7f7 100644 --- a/topola/src/layout.rs +++ b/topola/src/layout.rs @@ -12,7 +12,7 @@ use undoredo::aliases::RTreeHalfDelta; use undoredo::{Delta, Recorder}; use crate::{ - compounds::{Pin, PinId}, + compounds::{Component, ComponentId, Pin, PinId}, math::Vector2, primitives::{ Joint, JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId, @@ -29,6 +29,7 @@ pub struct Layout { #[undoredo(skip)] layer_count: usize, + components: Recorder>, pins: Recorder>, joints: Recorder>, @@ -61,6 +62,7 @@ impl Layout { place_boundary: boundary, layer_count, + components: Recorder::new(StableVec::new()), pins: Recorder::new(StableVec::new()), joints: Recorder::new(StableVec::new()), @@ -75,6 +77,10 @@ impl Layout { } } + pub fn add_component(&mut self) -> ComponentId { + ComponentId::new(self.components.push(Component::new())) + } + pub fn add_pin(&mut self) -> PinId { PinId::new(self.pins.push(Pin::new())) } @@ -86,12 +92,19 @@ impl Layout { vias: Vec::new(), }; let bbox = joint.bbox(); + let component_id = joint.spec.component; let pin_id = joint.spec.pin; let joint_id = JointId::new(self.joints.push(joint)); self.joints_rtree .insert(GeomWithData::new(bbox, joint_id), ()); + if let Some(component_id) = component_id { + self.components.modify(component_id.index(), |component| { + component.joints.push(joint_id) + }); + } + if let Some(pin_id) = pin_id { self.pins .modify(pin_id.index(), |pin| pin.joints.push(joint_id)); @@ -144,6 +157,7 @@ impl Layout { } pub fn add_segment_raw(&mut self, segment: Segment) -> SegmentId { + let component_id = segment.spec.component; let pin_id = segment.spec.pin; let bbox = segment.bbox(); let segment_id = SegmentId::new(self.segments.push(segment)); @@ -160,6 +174,12 @@ impl Layout { self.segments_rtree .insert(GeomWithData::new(bbox, segment_id), ()); + if let Some(component_id) = component_id { + self.components.modify(component_id.index(), |component| { + component.segments.push(segment_id) + }); + } + if let Some(pin_id) = pin_id { self.pins .modify(pin_id.index(), |pin| pin.segments.push(segment_id)); @@ -219,6 +239,7 @@ impl Layout { pub fn add_via_raw(&mut self, via: Via) -> ViaId { let bbox = via.bbox(); + let component_id = via.spec.component; let pin_id = via.spec.pin; let via_id = ViaId::new(self.vias.push(via)); @@ -231,6 +252,12 @@ impl Layout { self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ()); + if let Some(component_id) = component_id { + self.components.modify(component_id.index(), |component| { + component.vias.push(via_id) + }); + } + if let Some(pin_id) = pin_id { self.pins .modify(pin_id.index(), |pin| pin.vias.push(via_id)); @@ -278,12 +305,19 @@ impl Layout { pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId { let bbox = polygon.bbox(); + let component_id = polygon.component; 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(component_id) = component_id { + self.components.modify(component_id.index(), |component| { + component.polygons.push(polygon_id) + }); + } + if let Some(pin_id) = pin_id { self.pins .modify(pin_id.index(), |pin| pin.polygons.push(polygon_id)); diff --git a/topola/src/primitives/joint.rs b/topola/src/primitives/joint.rs index 1eb6a57..ac4d150 100644 --- a/topola/src/primitives/joint.rs +++ b/topola/src/primitives/joint.rs @@ -6,7 +6,7 @@ use derive_more::Constructor; use rstar::{AABB, primitives::Rectangle}; use serde::{Deserialize, Serialize}; -use crate::compounds::{NetId, PinId}; +use crate::compounds::{ComponentId, NetId, PinId}; use crate::math::Vector2; use crate::primitives::{SegmentId, ViaId}; @@ -29,6 +29,7 @@ pub struct JointSpec { pub layer: usize, pub radius: u64, pub net: NetId, + pub component: Option, pub pin: Option, } diff --git a/topola/src/primitives/polygon.rs b/topola/src/primitives/polygon.rs index 3ebdf8d..32b5a6e 100644 --- a/topola/src/primitives/polygon.rs +++ b/topola/src/primitives/polygon.rs @@ -6,7 +6,7 @@ use derive_more::Constructor; use rstar::{AABB, Envelope, primitives::Rectangle}; use serde::{Deserialize, Serialize}; -use crate::compounds::{NetId, PinId}; +use crate::compounds::{ComponentId, NetId, PinId}; use crate::math::Vector2; #[derive( @@ -27,6 +27,7 @@ pub struct Polygon { pub vertices: Vec>, pub layer: usize, pub net: NetId, + pub component: Option, pub pin: Option, } diff --git a/topola/src/primitives/segment.rs b/topola/src/primitives/segment.rs index 6f62f22..6730c71 100644 --- a/topola/src/primitives/segment.rs +++ b/topola/src/primitives/segment.rs @@ -6,7 +6,7 @@ use derive_more::Constructor; use rstar::primitives::Rectangle; use serde::{Deserialize, Serialize}; -use crate::compounds::{NetId, PinId}; +use crate::compounds::{ComponentId, NetId, PinId}; use crate::math::Vector2; use crate::primitives::JointId; @@ -27,6 +27,7 @@ impl SegmentId { pub struct SegmentSpec { pub endjoints: [JointId; 2], pub half_width: u64, + pub component: Option, pub pin: Option, } diff --git a/topola/src/primitives/via.rs b/topola/src/primitives/via.rs index bd78493..c7ae366 100644 --- a/topola/src/primitives/via.rs +++ b/topola/src/primitives/via.rs @@ -6,7 +6,7 @@ use derive_more::Constructor; use rstar::{AABB, primitives::Rectangle}; use serde::{Deserialize, Serialize}; -use crate::compounds::{NetId, PinId}; +use crate::compounds::{ComponentId, NetId, PinId}; use crate::math::Vector2; use crate::primitives::JointId; @@ -27,6 +27,7 @@ impl ViaId { pub struct ViaSpec { pub endjoints: [JointId; 2], pub radius: u64, + pub component: Option, pub pin: Option, } diff --git a/topola/src/specctra.rs b/topola/src/specctra.rs index f419738..9be4ef0 100644 --- a/topola/src/specctra.rs +++ b/topola/src/specctra.rs @@ -12,8 +12,7 @@ use specctra::{ use crate::{ board::Board, - compounds::NetId, - compounds::PinId, + compounds::{ComponentId, NetId, PinId}, math::Vector2, primitives::{JointSpec, Polygon, Segment, SegmentSpec}, }; @@ -98,6 +97,7 @@ impl Board { .unwrap(); for place in &component.places { + let component_id = board.add_component(); let place_side_is_front = place.side == "front"; let get_layer = |board: &Board, name: &str| { Self::layer(board, &dsn.pcb.structure.layers, name, place_side_is_front) @@ -124,6 +124,7 @@ impl Board { (circle.diameter / 2.0) as u64, layer, net, + Some(component_id), Some(pin_id), !place_side_is_front, ) @@ -140,6 +141,7 @@ impl Board { rect.y2, layer, net, + Some(component_id), Some(pin_id), !place_side_is_front, ) @@ -154,6 +156,7 @@ impl Board { path.width, layer, net, + Some(component_id), Some(pin_id), !place_side_is_front, ) @@ -168,6 +171,7 @@ impl Board { polygon.width, layer, net, + Some(component_id), Some(pin_id), !place_side_is_front, ) @@ -198,6 +202,7 @@ impl Board { layer, net, None, + None, false, ) } @@ -214,6 +219,7 @@ impl Board { layer, net, None, + None, false, ) } @@ -228,6 +234,7 @@ impl Board { layer, net, None, + None, false, ) } @@ -242,6 +249,7 @@ impl Board { layer, net, None, + None, false, ) } @@ -262,6 +270,7 @@ impl Board { layer, net, None, + None, false, ); } @@ -276,6 +285,7 @@ impl Board { radius: u64, layer: usize, net: NetId, + component: Option, pin: Option, flip: bool, ) { @@ -283,6 +293,7 @@ impl Board { position: Self::pos(place, pin_pos, 0.0, 0.0, flip), layer, net, + component, pin, radius, }); @@ -298,6 +309,7 @@ impl Board { y2: f64, layer: usize, net: NetId, + component: Option, pin: Option, flip: bool, ) { @@ -310,6 +322,7 @@ impl Board { ], layer, net, + component, pin, }); } @@ -322,6 +335,7 @@ impl Board { width: f64, layer: usize, net: NetId, + component: Option, pin: Option, flip: bool, ) { @@ -332,6 +346,7 @@ impl Board { layer, radius: (width / 2.0) as u64, net, + component, pin, }); @@ -348,6 +363,7 @@ impl Board { layer, radius: (width / 2.0) as u64, net, + component, pin, }); @@ -356,6 +372,7 @@ impl Board { spec: SegmentSpec { endjoints: [prev_joint, joint], half_width: (width / 2.0) as u64, + component, pin, }, endpoints: [prev_pos, pos], @@ -376,6 +393,7 @@ impl Board { _width: f64, layer: usize, net: NetId, + component: Option, pin: Option, flip: bool, ) { @@ -387,6 +405,7 @@ impl Board { vertices, layer, net, + component, pin, }); }