mirror of https://codeberg.org/topola/topola.git
Load layers to primitives
This commit is contained in:
parent
5e6ddac19f
commit
8a50e70a6a
|
|
@ -9,6 +9,7 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bimap = "0.6"
|
||||||
dearcut = { version = "0.1", features = ["undoredo"] }
|
dearcut = { version = "0.1", features = ["undoredo"] }
|
||||||
derive-getters.workspace = true
|
derive-getters.workspace = true
|
||||||
derive_more.workspace = true
|
derive_more.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use bimap::BiBTreeMap;
|
||||||
use derive_getters::{Dissolve, Getters};
|
use derive_getters::{Dissolve, Getters};
|
||||||
use undoredo::{ApplyDelta, Delta, FlushDelta};
|
use undoredo::{ApplyDelta, Delta, FlushDelta};
|
||||||
|
|
||||||
|
|
@ -18,12 +19,30 @@ struct Layer {
|
||||||
#[derive(Clone, Debug, Getters)]
|
#[derive(Clone, Debug, Getters)]
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
|
#[getter(skip)]
|
||||||
|
layer_names: BiBTreeMap<usize, String>,
|
||||||
|
#[getter(skip)]
|
||||||
|
net_names: BiBTreeMap<usize, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
pub fn new(boundary: Vec<[i64; 2]>) -> Self {
|
pub fn new(boundary: Vec<[i64; 2]>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
layout: Layout::new(boundary),
|
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 {
|
pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
|
||||||
self.layout.add_polygon(polygon)
|
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)]
|
#[derive(Clone, Debug, Dissolve)]
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use bimap::BiBTreeMap;
|
||||||
use specctra::{
|
use specctra::{
|
||||||
math::PointWithRotation,
|
math::PointWithRotation,
|
||||||
structure::{DsnFile, Point, Shape},
|
structure::{DsnFile, Layer, Point, Shape},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -16,7 +17,33 @@ use crate::{
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
pub fn from_specctra(dsn: DsnFile) -> Self {
|
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
|
dsn.pcb
|
||||||
.structure
|
.structure
|
||||||
.boundary
|
.boundary
|
||||||
|
|
@ -25,8 +52,29 @@ impl Board {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| [p.x as i64, p.y as i64])
|
.map(|p| [p.x as i64, p.y as i64])
|
||||||
.collect(),
|
.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.
|
// Add pins from components.
|
||||||
for component in &dsn.pcb.placement.components {
|
for component in &dsn.pcb.placement.components {
|
||||||
let image = dsn
|
let image = dsn
|
||||||
|
|
@ -38,54 +86,65 @@ impl Board {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for place in &component.places {
|
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| {
|
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)
|
||||||
};*/
|
};
|
||||||
|
|
||||||
for pin in &image.pins {
|
for pin in &image.pins {
|
||||||
let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap();
|
let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap();
|
||||||
|
|
||||||
for shape in padstack.shapes.iter() {
|
for shape in padstack.shapes.iter() {
|
||||||
match shape {
|
match shape {
|
||||||
Shape::Circle(circle) => Self::place_circle(
|
Shape::Circle(circle) => {
|
||||||
&mut board,
|
let layer = get_layer(&board, &circle.layer);
|
||||||
place.point_with_rotation(),
|
Self::place_circle(
|
||||||
pin.point_with_rotation(),
|
&mut board,
|
||||||
0,
|
place.point_with_rotation(),
|
||||||
(circle.diameter / 2.0) as u64,
|
pin.point_with_rotation(),
|
||||||
false,
|
layer,
|
||||||
),
|
(circle.diameter / 2.0) as u64,
|
||||||
Shape::Rect(rect) => Self::place_rect(
|
false,
|
||||||
&mut board,
|
)
|
||||||
place.point_with_rotation(),
|
}
|
||||||
pin.point_with_rotation(),
|
Shape::Rect(rect) => {
|
||||||
rect.x1,
|
let layer = get_layer(&board, &rect.layer);
|
||||||
rect.y1,
|
Self::place_rect(
|
||||||
rect.x2,
|
&mut board,
|
||||||
rect.y2,
|
place.point_with_rotation(),
|
||||||
0,
|
pin.point_with_rotation(),
|
||||||
false,
|
rect.x1,
|
||||||
),
|
rect.y1,
|
||||||
Shape::Path(path) => Self::place_path(
|
rect.x2,
|
||||||
&mut board,
|
rect.y2,
|
||||||
place.point_with_rotation(),
|
layer,
|
||||||
pin.point_with_rotation(),
|
false,
|
||||||
&path.coords,
|
)
|
||||||
path.width,
|
}
|
||||||
0,
|
Shape::Path(path) => {
|
||||||
false,
|
let layer = get_layer(&board, &path.layer);
|
||||||
),
|
Self::place_path(
|
||||||
Shape::Polygon(polygon) => Self::place_polygon(
|
&mut board,
|
||||||
&mut board,
|
place.point_with_rotation(),
|
||||||
place.point_with_rotation(),
|
pin.point_with_rotation(),
|
||||||
pin.point_with_rotation(),
|
&path.coords,
|
||||||
&polygon.coords,
|
path.width,
|
||||||
polygon.width,
|
layer,
|
||||||
0,
|
false,
|
||||||
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
|
board
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_circle(
|
fn place_circle(
|
||||||
board: &mut Board,
|
board: &mut Board,
|
||||||
place: PointWithRotation,
|
place: PointWithRotation,
|
||||||
pin: PointWithRotation,
|
pin: PointWithRotation,
|
||||||
|
|
@ -110,7 +169,7 @@ impl Board {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_rect(
|
fn place_rect(
|
||||||
board: &mut Board,
|
board: &mut Board,
|
||||||
place: PointWithRotation,
|
place: PointWithRotation,
|
||||||
pin: PointWithRotation,
|
pin: PointWithRotation,
|
||||||
|
|
@ -132,7 +191,7 @@ impl Board {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_path(
|
fn place_path(
|
||||||
board: &mut Board,
|
board: &mut Board,
|
||||||
place: PointWithRotation,
|
place: PointWithRotation,
|
||||||
pin: PointWithRotation,
|
pin: PointWithRotation,
|
||||||
|
|
@ -175,7 +234,7 @@ impl Board {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_polygon(
|
fn place_polygon(
|
||||||
board: &mut Board,
|
board: &mut Board,
|
||||||
place: PointWithRotation,
|
place: PointWithRotation,
|
||||||
pin: PointWithRotation,
|
pin: PointWithRotation,
|
||||||
|
|
@ -191,6 +250,16 @@ impl Board {
|
||||||
board.add_polygon(Polygon { vertices, layer });
|
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(
|
fn pos(
|
||||||
place: PointWithRotation,
|
place: PointWithRotation,
|
||||||
pin: PointWithRotation,
|
pin: PointWithRotation,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue