Add new type of compound, component

This commit is contained in:
Mikolaj Wielgus 2026-05-18 23:29:59 +02:00
parent bc5e205b90
commit e536e94039
10 changed files with 114 additions and 12 deletions

View File

@ -7,7 +7,7 @@ use derive_getters::{Dissolve, Getters};
use undoredo::{ApplyDelta, Delta, FlushDelta}; use undoredo::{ApplyDelta, Delta, FlushDelta};
use crate::{ use crate::{
compounds::{NetId, PinId}, compounds::{ComponentId, NetId, PinId},
layout::{Layout, LayoutHalfDelta}, layout::{Layout, LayoutHalfDelta},
math::Vector2, math::Vector2,
primitives::{ primitives::{
@ -63,6 +63,10 @@ impl Board {
pin_id pin_id
} }
pub fn add_component(&mut self) -> ComponentId {
self.layout.add_component()
}
pub fn add_joint(&mut self, spec: JointSpec) -> JointId { pub fn add_joint(&mut self, spec: JointSpec) -> JointId {
self.layout.add_joint(spec) self.layout.add_joint(spec)
} }

View File

@ -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<JointId>,
pub segments: Vec<SegmentId>,
pub vias: Vec<ViaId>,
pub polygons: Vec<PolygonId>,
}
impl Component {
pub fn new() -> Self {
Self {
joints: Vec::new(),
segments: Vec::new(),
vias: Vec::new(),
polygons: Vec::new(),
}
}
}

View File

@ -2,8 +2,10 @@
// //
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
mod component;
mod net; mod net;
mod pin; mod pin;
pub use component::{Component, ComponentId};
pub use net::NetId; pub use net::NetId;
pub use pin::{Pin, PinId}; pub use pin::{Pin, PinId};

View File

@ -21,10 +21,10 @@ impl PinId {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Pin { pub struct Pin {
pub(crate) joints: Vec<JointId>, pub joints: Vec<JointId>,
pub(crate) segments: Vec<SegmentId>, pub segments: Vec<SegmentId>,
pub(crate) vias: Vec<ViaId>, pub vias: Vec<ViaId>,
pub(crate) polygons: Vec<PolygonId>, pub polygons: Vec<PolygonId>,
} }
impl Pin { impl Pin {

View File

@ -12,7 +12,7 @@ use undoredo::aliases::RTreeHalfDelta;
use undoredo::{Delta, Recorder}; use undoredo::{Delta, Recorder};
use crate::{ use crate::{
compounds::{Pin, PinId}, compounds::{Component, ComponentId, Pin, PinId},
math::Vector2, math::Vector2,
primitives::{ primitives::{
Joint, JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId, Joint, JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId,
@ -29,6 +29,7 @@ pub struct Layout {
#[undoredo(skip)] #[undoredo(skip)]
layer_count: usize, layer_count: usize,
components: Recorder<StableVec<Component>>,
pins: Recorder<StableVec<Pin>>, pins: Recorder<StableVec<Pin>>,
joints: Recorder<StableVec<Joint>>, joints: Recorder<StableVec<Joint>>,
@ -61,6 +62,7 @@ impl Layout {
place_boundary: boundary, place_boundary: boundary,
layer_count, layer_count,
components: Recorder::new(StableVec::new()),
pins: Recorder::new(StableVec::new()), pins: Recorder::new(StableVec::new()),
joints: 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 { pub fn add_pin(&mut self) -> PinId {
PinId::new(self.pins.push(Pin::new())) PinId::new(self.pins.push(Pin::new()))
} }
@ -86,12 +92,19 @@ impl Layout {
vias: Vec::new(), vias: Vec::new(),
}; };
let bbox = joint.bbox(); let bbox = joint.bbox();
let component_id = joint.spec.component;
let pin_id = joint.spec.pin; let pin_id = joint.spec.pin;
let joint_id = JointId::new(self.joints.push(joint)); let joint_id = JointId::new(self.joints.push(joint));
self.joints_rtree self.joints_rtree
.insert(GeomWithData::new(bbox, joint_id), ()); .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 { if let Some(pin_id) = pin_id {
self.pins self.pins
.modify(pin_id.index(), |pin| pin.joints.push(joint_id)); .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 { pub fn add_segment_raw(&mut self, segment: Segment) -> SegmentId {
let component_id = segment.spec.component;
let pin_id = segment.spec.pin; let pin_id = segment.spec.pin;
let bbox = segment.bbox(); let bbox = segment.bbox();
let segment_id = SegmentId::new(self.segments.push(segment)); let segment_id = SegmentId::new(self.segments.push(segment));
@ -160,6 +174,12 @@ impl Layout {
self.segments_rtree self.segments_rtree
.insert(GeomWithData::new(bbox, segment_id), ()); .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 { if let Some(pin_id) = pin_id {
self.pins self.pins
.modify(pin_id.index(), |pin| pin.segments.push(segment_id)); .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 { pub fn add_via_raw(&mut self, via: Via) -> ViaId {
let bbox = via.bbox(); let bbox = via.bbox();
let component_id = via.spec.component;
let pin_id = via.spec.pin; let pin_id = via.spec.pin;
let via_id = ViaId::new(self.vias.push(via)); let via_id = ViaId::new(self.vias.push(via));
@ -231,6 +252,12 @@ impl Layout {
self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ()); 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 { if let Some(pin_id) = pin_id {
self.pins self.pins
.modify(pin_id.index(), |pin| pin.vias.push(via_id)); .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 { pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
let bbox = polygon.bbox(); let bbox = polygon.bbox();
let component_id = polygon.component;
let pin_id = polygon.pin; let pin_id = polygon.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
.insert(GeomWithData::new(bbox, polygon_id), ()); .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 { if let Some(pin_id) = pin_id {
self.pins self.pins
.modify(pin_id.index(), |pin| pin.polygons.push(polygon_id)); .modify(pin_id.index(), |pin| pin.polygons.push(polygon_id));

View File

@ -6,7 +6,7 @@ use derive_more::Constructor;
use rstar::{AABB, primitives::Rectangle}; use rstar::{AABB, primitives::Rectangle};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::compounds::{NetId, PinId}; use crate::compounds::{ComponentId, NetId, PinId};
use crate::math::Vector2; use crate::math::Vector2;
use crate::primitives::{SegmentId, ViaId}; use crate::primitives::{SegmentId, ViaId};
@ -29,6 +29,7 @@ pub struct JointSpec {
pub layer: usize, pub layer: usize,
pub radius: u64, pub radius: u64,
pub net: NetId, pub net: NetId,
pub component: Option<ComponentId>,
pub pin: Option<PinId>, pub pin: Option<PinId>,
} }

View File

@ -6,7 +6,7 @@ use derive_more::Constructor;
use rstar::{AABB, Envelope, primitives::Rectangle}; use rstar::{AABB, Envelope, primitives::Rectangle};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::compounds::{NetId, PinId}; use crate::compounds::{ComponentId, NetId, PinId};
use crate::math::Vector2; use crate::math::Vector2;
#[derive( #[derive(
@ -27,6 +27,7 @@ pub struct Polygon {
pub vertices: Vec<Vector2<i64>>, pub vertices: Vec<Vector2<i64>>,
pub layer: usize, pub layer: usize,
pub net: NetId, pub net: NetId,
pub component: Option<ComponentId>,
pub pin: Option<PinId>, pub pin: Option<PinId>,
} }

View File

@ -6,7 +6,7 @@ use derive_more::Constructor;
use rstar::primitives::Rectangle; use rstar::primitives::Rectangle;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::compounds::{NetId, PinId}; use crate::compounds::{ComponentId, NetId, PinId};
use crate::math::Vector2; use crate::math::Vector2;
use crate::primitives::JointId; use crate::primitives::JointId;
@ -27,6 +27,7 @@ impl SegmentId {
pub struct SegmentSpec { pub struct SegmentSpec {
pub endjoints: [JointId; 2], pub endjoints: [JointId; 2],
pub half_width: u64, pub half_width: u64,
pub component: Option<ComponentId>,
pub pin: Option<PinId>, pub pin: Option<PinId>,
} }

View File

@ -6,7 +6,7 @@ use derive_more::Constructor;
use rstar::{AABB, primitives::Rectangle}; use rstar::{AABB, primitives::Rectangle};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::compounds::{NetId, PinId}; use crate::compounds::{ComponentId, NetId, PinId};
use crate::math::Vector2; use crate::math::Vector2;
use crate::primitives::JointId; use crate::primitives::JointId;
@ -27,6 +27,7 @@ impl ViaId {
pub struct ViaSpec { pub struct ViaSpec {
pub endjoints: [JointId; 2], pub endjoints: [JointId; 2],
pub radius: u64, pub radius: u64,
pub component: Option<ComponentId>,
pub pin: Option<PinId>, pub pin: Option<PinId>,
} }

View File

@ -12,8 +12,7 @@ use specctra::{
use crate::{ use crate::{
board::Board, board::Board,
compounds::NetId, compounds::{ComponentId, NetId, PinId},
compounds::PinId,
math::Vector2, math::Vector2,
primitives::{JointSpec, Polygon, Segment, SegmentSpec}, primitives::{JointSpec, Polygon, Segment, SegmentSpec},
}; };
@ -98,6 +97,7 @@ impl Board {
.unwrap(); .unwrap();
for place in &component.places { for place in &component.places {
let component_id = board.add_component();
let place_side_is_front = place.side == "front"; let place_side_is_front = place.side == "front";
let get_layer = |board: &Board, name: &str| { let get_layer = |board: &Board, name: &str| {
Self::layer(board, &dsn.pcb.structure.layers, name, place_side_is_front) Self::layer(board, &dsn.pcb.structure.layers, name, place_side_is_front)
@ -124,6 +124,7 @@ impl Board {
(circle.diameter / 2.0) as u64, (circle.diameter / 2.0) as u64,
layer, layer,
net, net,
Some(component_id),
Some(pin_id), Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
@ -140,6 +141,7 @@ impl Board {
rect.y2, rect.y2,
layer, layer,
net, net,
Some(component_id),
Some(pin_id), Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
@ -154,6 +156,7 @@ impl Board {
path.width, path.width,
layer, layer,
net, net,
Some(component_id),
Some(pin_id), Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
@ -168,6 +171,7 @@ impl Board {
polygon.width, polygon.width,
layer, layer,
net, net,
Some(component_id),
Some(pin_id), Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
@ -198,6 +202,7 @@ impl Board {
layer, layer,
net, net,
None, None,
None,
false, false,
) )
} }
@ -214,6 +219,7 @@ impl Board {
layer, layer,
net, net,
None, None,
None,
false, false,
) )
} }
@ -228,6 +234,7 @@ impl Board {
layer, layer,
net, net,
None, None,
None,
false, false,
) )
} }
@ -242,6 +249,7 @@ impl Board {
layer, layer,
net, net,
None, None,
None,
false, false,
) )
} }
@ -262,6 +270,7 @@ impl Board {
layer, layer,
net, net,
None, None,
None,
false, false,
); );
} }
@ -276,6 +285,7 @@ impl Board {
radius: u64, radius: u64,
layer: usize, layer: usize,
net: NetId, net: NetId,
component: Option<ComponentId>,
pin: Option<PinId>, pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
@ -283,6 +293,7 @@ impl Board {
position: Self::pos(place, pin_pos, 0.0, 0.0, flip), position: Self::pos(place, pin_pos, 0.0, 0.0, flip),
layer, layer,
net, net,
component,
pin, pin,
radius, radius,
}); });
@ -298,6 +309,7 @@ impl Board {
y2: f64, y2: f64,
layer: usize, layer: usize,
net: NetId, net: NetId,
component: Option<ComponentId>,
pin: Option<PinId>, pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
@ -310,6 +322,7 @@ impl Board {
], ],
layer, layer,
net, net,
component,
pin, pin,
}); });
} }
@ -322,6 +335,7 @@ impl Board {
width: f64, width: f64,
layer: usize, layer: usize,
net: NetId, net: NetId,
component: Option<ComponentId>,
pin: Option<PinId>, pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
@ -332,6 +346,7 @@ impl Board {
layer, layer,
radius: (width / 2.0) as u64, radius: (width / 2.0) as u64,
net, net,
component,
pin, pin,
}); });
@ -348,6 +363,7 @@ impl Board {
layer, layer,
radius: (width / 2.0) as u64, radius: (width / 2.0) as u64,
net, net,
component,
pin, pin,
}); });
@ -356,6 +372,7 @@ impl Board {
spec: SegmentSpec { spec: SegmentSpec {
endjoints: [prev_joint, joint], endjoints: [prev_joint, joint],
half_width: (width / 2.0) as u64, half_width: (width / 2.0) as u64,
component,
pin, pin,
}, },
endpoints: [prev_pos, pos], endpoints: [prev_pos, pos],
@ -376,6 +393,7 @@ impl Board {
_width: f64, _width: f64,
layer: usize, layer: usize,
net: NetId, net: NetId,
component: Option<ComponentId>,
pin: Option<PinId>, pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
@ -387,6 +405,7 @@ impl Board {
vertices, vertices,
layer, layer,
net, net,
component,
pin, pin,
}); });
} }