Load layers to primitives

This commit is contained in:
Mikolaj Wielgus 2026-03-10 22:18:15 +01:00
parent 5e6ddac19f
commit 8a50e70a6a
3 changed files with 151 additions and 46 deletions

View File

@ -9,6 +9,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
bimap = "0.6"
dearcut = { version = "0.1", features = ["undoredo"] }
derive-getters.workspace = true
derive_more.workspace = true

View File

@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: MIT
use bimap::BiBTreeMap;
use derive_getters::{Dissolve, Getters};
use undoredo::{ApplyDelta, Delta, FlushDelta};
@ -18,12 +19,30 @@ struct Layer {
#[derive(Clone, Debug, Getters)]
pub struct Board {
layout: Layout,
#[getter(skip)]
layer_names: BiBTreeMap<usize, String>,
#[getter(skip)]
net_names: BiBTreeMap<usize, String>,
}
impl Board {
pub fn new(boundary: Vec<[i64; 2]>) -> Self {
Self {
layout: Layout::new(boundary),
layer_names: BiBTreeMap::new(),
net_names: BiBTreeMap::new(),
}
}
pub fn with_names(
boundary: Vec<[i64; 2]>,
layer_names: BiBTreeMap<usize, String>,
net_names: BiBTreeMap<usize, String>,
) -> Self {
Self {
layout: Layout::new(boundary),
layer_names,
net_names,
}
}
@ -46,6 +65,22 @@ impl Board {
pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
self.layout.add_polygon(polygon)
}
pub fn layer_name(&self, layer: usize) -> &str {
&self.layer_names.get_by_left(&layer).unwrap()
}
pub fn layer_id(&self, name: &str) -> usize {
*self.layer_names.get_by_right(name).unwrap()
}
pub fn net_name(&self, net: usize) -> &str {
&self.net_names.get_by_left(&net).unwrap()
}
pub fn net_id(&self, name: &str) -> usize {
*self.net_names.get_by_right(name).unwrap()
}
}
#[derive(Clone, Debug, Dissolve)]

View File

@ -2,9 +2,10 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use bimap::BiBTreeMap;
use specctra::{
math::PointWithRotation,
structure::{DsnFile, Point, Shape},
structure::{DsnFile, Layer, Point, Shape},
};
use crate::{
@ -16,7 +17,33 @@ use crate::{
impl Board {
pub fn from_specctra(dsn: DsnFile) -> Self {
let mut board = Board::new(
let layer_names = BiBTreeMap::from_iter(
dsn.pcb
.structure
.layers
.iter()
.enumerate()
.map(|(index, layer)| (index, layer.name.clone())),
);
// assign IDs to all nets named in pcb.network
let net_names = {
let mut tmp: Vec<_> = dsn
.pcb
.network
.classes
.iter()
.flat_map(|class| &class.nets)
.chain(dsn.pcb.network.nets.iter().map(|net| &net.name))
.collect();
// deduplicate net names
tmp.sort_unstable();
tmp.dedup();
BiBTreeMap::from_iter(tmp.into_iter().cloned().enumerate())
};
let mut board = Board::with_names(
dsn.pcb
.structure
.boundary
@ -25,8 +52,29 @@ impl Board {
.into_iter()
.map(|p| [p.x as i64, p.y as i64])
.collect(),
layer_names,
net_names,
);
// Mapping of pin -> net prepared for adding pins.
let pin_nets = dsn
.pcb
.network
.nets
.iter()
.filter_map(|net_pin_assignments| {
// Resolve the id so we don't work with strings.
let net = board.net_id(&net_pin_assignments.name);
net_pin_assignments.pins.as_ref().map(|pins| {
// Take the list of pins
// and for each pin output (pin name, net id).
pins.names.iter().map(move |pinname| (pinname.clone(), net))
})
})
// Flatten the nested iters into a single stream of tuples.
.flatten();
// Add pins from components.
for component in &dsn.pcb.placement.components {
let image = dsn
@ -38,54 +86,65 @@ impl Board {
.unwrap();
for place in &component.places {
/*let place_side_is_front = place.side == "front";
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)
};*/
};
for pin in &image.pins {
let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap();
for shape in padstack.shapes.iter() {
match shape {
Shape::Circle(circle) => Self::place_circle(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
0,
(circle.diameter / 2.0) as u64,
false,
),
Shape::Rect(rect) => Self::place_rect(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
rect.x1,
rect.y1,
rect.x2,
rect.y2,
0,
false,
),
Shape::Path(path) => Self::place_path(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
&path.coords,
path.width,
0,
false,
),
Shape::Polygon(polygon) => Self::place_polygon(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
&polygon.coords,
polygon.width,
0,
false,
),
_ => (),
Shape::Circle(circle) => {
let layer = get_layer(&board, &circle.layer);
Self::place_circle(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
layer,
(circle.diameter / 2.0) as u64,
false,
)
}
Shape::Rect(rect) => {
let layer = get_layer(&board, &rect.layer);
Self::place_rect(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
rect.x1,
rect.y1,
rect.x2,
rect.y2,
layer,
false,
)
}
Shape::Path(path) => {
let layer = get_layer(&board, &path.layer);
Self::place_path(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
&path.coords,
path.width,
layer,
false,
)
}
Shape::Polygon(polygon) => {
let layer = get_layer(&board, &polygon.layer);
Self::place_polygon(
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
&polygon.coords,
polygon.width,
layer,
false,
)
}
}
}
}
@ -95,7 +154,7 @@ impl Board {
board
}
pub fn place_circle(
fn place_circle(
board: &mut Board,
place: PointWithRotation,
pin: PointWithRotation,
@ -110,7 +169,7 @@ impl Board {
});
}
pub fn place_rect(
fn place_rect(
board: &mut Board,
place: PointWithRotation,
pin: PointWithRotation,
@ -132,7 +191,7 @@ impl Board {
});
}
pub fn place_path(
fn place_path(
board: &mut Board,
place: PointWithRotation,
pin: PointWithRotation,
@ -175,7 +234,7 @@ impl Board {
}
}
pub fn place_polygon(
fn place_polygon(
board: &mut Board,
place: PointWithRotation,
pin: PointWithRotation,
@ -191,6 +250,16 @@ impl Board {
board.add_polygon(Polygon { vertices, layer });
}
fn layer(board: &Board, layers: &[Layer], name: &str, front: bool) -> usize {
let image_layer = board.layer_id(name);
if front {
image_layer
} else {
layers.len() - image_layer - 1
}
}
fn pos(
place: PointWithRotation,
pin: PointWithRotation,