layout: move pin information to a new parent object, `Board`

This commit is contained in:
Mikolaj Wielgus 2024-05-31 01:42:48 +02:00
parent b22e3dce1a
commit de17adb01c
11 changed files with 280 additions and 163 deletions

View File

@ -14,6 +14,7 @@ use thiserror::Error;
use crate::{ use crate::{
autorouter::{ autorouter::{
board::Board,
ratsnest::{Ratsnest, RatsnestVertexIndex}, ratsnest::{Ratsnest, RatsnestVertexIndex},
selection::Selection, selection::Selection,
}, },
@ -22,7 +23,7 @@ use crate::{
graph::{GetLayer, GetMaybeNet}, graph::{GetLayer, GetMaybeNet},
rules::RulesTrait, rules::RulesTrait,
}, },
layout::{Layout, NodeIndex}, layout::Layout,
router::{ router::{
navmesh::{Navmesh, NavmeshError}, navmesh::{Navmesh, NavmeshError},
Router, RouterError, RouterObserverTrait, Router, RouterError, RouterObserverTrait,
@ -63,7 +64,7 @@ impl Autoroute {
}; };
let (source, target) = Self::ratline_endpoints(autorouter, cur_ratline); let (source, target) = Self::ratline_endpoints(autorouter, cur_ratline);
let navmesh = Some(Navmesh::new(&autorouter.layout, source, target)?); let navmesh = Some(Navmesh::new(autorouter.board.layout(), source, target)?);
let this = Self { let this = Self {
ratlines_iter, ratlines_iter,
@ -84,7 +85,7 @@ impl Autoroute {
( (
Some( Some(
Navmesh::new(&autorouter.layout, source, target) Navmesh::new(autorouter.board.layout(), source, target)
.ok() .ok()
.unwrap(), .unwrap(),
), ),
@ -95,7 +96,7 @@ impl Autoroute {
}; };
let mut router = Router::new_from_navmesh( let mut router = Router::new_from_navmesh(
&mut autorouter.layout, autorouter.board.layout_mut(),
std::mem::replace(&mut self.navmesh, new_navmesh).unwrap(), std::mem::replace(&mut self.navmesh, new_navmesh).unwrap(),
); );
@ -130,7 +131,7 @@ impl Autoroute {
.vertex_index() .vertex_index()
{ {
RatsnestVertexIndex::FixedDot(dot) => dot, RatsnestVertexIndex::FixedDot(dot) => dot,
RatsnestVertexIndex::Zone(zone) => autorouter.layout.zone_apex(zone), RatsnestVertexIndex::Zone(zone) => autorouter.board.layout_mut().zone_apex(zone),
}; };
let target_dot = match autorouter let target_dot = match autorouter
@ -141,7 +142,7 @@ impl Autoroute {
.vertex_index() .vertex_index()
{ {
RatsnestVertexIndex::FixedDot(dot) => dot, RatsnestVertexIndex::FixedDot(dot) => dot,
RatsnestVertexIndex::Zone(zone) => autorouter.layout.zone_apex(zone), RatsnestVertexIndex::Zone(zone) => autorouter.board.layout_mut().zone_apex(zone),
}; };
(source_dot, target_dot) (source_dot, target_dot)
@ -153,14 +154,14 @@ impl Autoroute {
} }
pub struct Autorouter<R: RulesTrait> { pub struct Autorouter<R: RulesTrait> {
layout: Layout<R>, board: Board<R>,
ratsnest: Ratsnest, ratsnest: Ratsnest,
} }
impl<R: RulesTrait> Autorouter<R> { impl<R: RulesTrait> Autorouter<R> {
pub fn new(layout: Layout<R>) -> Result<Self, InsertionError> { pub fn new(board: Board<R>) -> Result<Self, InsertionError> {
let ratsnest = Ratsnest::new(&layout)?; let ratsnest = Ratsnest::new(board.layout())?;
Ok(Self { layout, ratsnest }) Ok(Self { board, ratsnest })
} }
pub fn autoroute( pub fn autoroute(
@ -195,7 +196,7 @@ impl<R: RulesTrait> Autorouter<R> {
.unwrap() .unwrap()
.band .band
.unwrap(); .unwrap();
self.layout.remove_band(band); self.board.layout_mut().remove_band(band);
} }
} }
@ -219,14 +220,14 @@ impl<R: RulesTrait> Autorouter<R> {
.unwrap() .unwrap()
.vertex_index(); .vertex_index();
selection.contains_node(&self.layout, source_vertex.into()) selection.contains_node(&self.board, source_vertex.into())
&& selection.contains_node(&self.layout, to_vertex.into()) && selection.contains_node(&self.board, to_vertex.into())
}) })
.collect() .collect()
} }
pub fn layout(&self) -> &Layout<R> { pub fn board(&self) -> &Board<R> {
&self.layout &self.board
} }
pub fn ratsnest(&self) -> &Ratsnest { pub fn ratsnest(&self) -> &Ratsnest {

122
src/autorouter/board.rs Normal file
View File

@ -0,0 +1,122 @@
use std::collections::HashMap;
use crate::{
drawing::{
dot::{FixedDotIndex, FixedDotWeight},
graph::PrimitiveIndex,
rules::RulesTrait,
seg::{FixedSegIndex, FixedSegWeight},
Infringement,
},
geometry::GenericNode,
graph::GenericIndex,
layout::{zone::ZoneWeight, Layout},
};
pub type NodeIndex = GenericNode<PrimitiveIndex, GenericIndex<ZoneWeight>>;
#[derive(Debug)]
pub struct Board<R: RulesTrait> {
layout: Layout<R>,
node_to_pin: HashMap<NodeIndex, String>,
}
impl<R: RulesTrait> Board<R> {
pub fn new(layout: Layout<R>) -> Self {
Self {
layout,
node_to_pin: HashMap::new(),
}
}
pub fn add_fixed_dot(
&mut self,
weight: FixedDotWeight,
maybe_pin: Option<String>,
) -> Result<FixedDotIndex, Infringement> {
let dot = self.layout.add_fixed_dot(weight)?;
if let Some(ref pin) = maybe_pin {
self.node_to_pin
.insert(GenericNode::Primitive(dot.into()), pin.clone());
}
Ok(dot)
}
pub fn add_zone_fixed_dot(
&mut self,
weight: FixedDotWeight,
zone: GenericIndex<ZoneWeight>,
) -> Result<FixedDotIndex, Infringement> {
let dot = self.layout.add_zone_fixed_dot(weight, zone)?;
if let Some(pin) = self.node_pin(GenericNode::Compound(zone)) {
self.node_to_pin
.insert(GenericNode::Primitive(dot.into()), pin.to_string());
}
Ok(dot)
}
pub fn add_fixed_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
maybe_pin: Option<String>,
) -> Result<FixedSegIndex, Infringement> {
let seg = self.layout.add_fixed_seg(from, to, weight)?;
if let Some(pin) = maybe_pin {
self.node_to_pin
.insert(GenericNode::Primitive(seg.into()), pin.to_string());
}
Ok(seg)
}
pub fn add_zone_fixed_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
zone: GenericIndex<ZoneWeight>,
) -> Result<FixedSegIndex, Infringement> {
let seg = self.layout.add_zone_fixed_seg(from, to, weight, zone)?;
if let Some(pin) = self.node_pin(GenericNode::Compound(zone)) {
self.node_to_pin
.insert(GenericNode::Primitive(seg.into()), pin.to_string());
}
Ok(seg)
}
pub fn add_zone(
&mut self,
weight: ZoneWeight,
maybe_pin: Option<String>,
) -> GenericIndex<ZoneWeight> {
let zone = self.layout.add_zone(weight);
if let Some(pin) = maybe_pin {
self.node_to_pin
.insert(GenericNode::Compound(zone.into()), pin.to_string());
}
zone
}
pub fn node_pin(&self, node: NodeIndex) -> Option<&String> {
self.node_to_pin.get(&node)
}
pub fn layout(&self) -> &Layout<R> {
&self.layout
}
pub fn layout_mut(&mut self) -> &mut Layout<R> {
&mut self.layout
}
}

View File

@ -1,4 +1,5 @@
mod autorouter; mod autorouter;
pub mod board;
pub mod history; pub mod history;
pub mod invoker; pub mod invoker;
pub mod ratsnest; pub mod ratsnest;

View File

@ -2,9 +2,9 @@ use core::fmt;
use std::collections::HashSet; use std::collections::HashSet;
use crate::{ use crate::{
autorouter::board::{Board, NodeIndex},
drawing::{graph::PrimitiveIndex, rules::RulesTrait}, drawing::{graph::PrimitiveIndex, rules::RulesTrait},
graph::GenericIndex, graph::GenericIndex,
layout::{zone::ZoneWeight, Layout, NodeIndex},
}; };
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@ -19,28 +19,28 @@ impl Selection {
} }
} }
pub fn toggle_at_node(&mut self, layout: &Layout<impl RulesTrait>, node: NodeIndex) { pub fn toggle_at_node(&mut self, board: &Board<impl RulesTrait>, node: NodeIndex) {
let maybe_pin = layout.node_pin(node); let maybe_pin = board.node_pin(node);
if let Some(ref pin) = maybe_pin { if let Some(ref pin) = maybe_pin {
if self.contains_node(layout, node) { if self.contains_node(board, node) {
self.remove_pin(layout, pin); self.remove_pin(board, pin);
} else { } else {
self.add_pin(layout, pin); self.add_pin(board, pin);
} }
} }
} }
fn add_pin(&mut self, layout: &Layout<impl RulesTrait>, pin: &String) { fn add_pin(&mut self, board: &Board<impl RulesTrait>, pin: &String) {
self.pins.insert(pin.clone()); self.pins.insert(pin.clone());
} }
fn remove_pin(&mut self, layout: &Layout<impl RulesTrait>, pin: &String) { fn remove_pin(&mut self, board: &Board<impl RulesTrait>, pin: &String) {
self.pins.remove(pin); self.pins.remove(pin);
} }
pub fn contains_node(&self, layout: &Layout<impl RulesTrait>, node: NodeIndex) -> bool { pub fn contains_node(&self, board: &Board<impl RulesTrait>, node: NodeIndex) -> bool {
if let Some(pin) = layout.node_pin(node) { if let Some(pin) = board.node_pin(node) {
self.pins.contains(pin) self.pins.contains(pin)
} else { } else {
false false

View File

@ -160,19 +160,19 @@ impl eframe::App for App {
if cfg!(target_arch = "wasm32") { if cfg!(target_arch = "wasm32") {
if let Ok(file_contents) = self.text_channel.1.try_recv() { if let Ok(file_contents) = self.text_channel.1.try_recv() {
let design = DsnDesign::load_from_string(file_contents).unwrap(); let design = DsnDesign::load_from_string(file_contents).unwrap();
let layout = design.make_layout(); let board = design.make_board();
self.overlay = Some(Overlay::new(&layout).unwrap()); self.overlay = Some(Overlay::new(&board).unwrap());
self.invoker = Some(Arc::new(Mutex::new(Invoker::new( self.invoker = Some(Arc::new(Mutex::new(Invoker::new(
Autorouter::new(layout).unwrap(), Autorouter::new(board).unwrap(),
)))); ))));
} }
} else { } else {
if let Ok(path) = self.text_channel.1.try_recv() { if let Ok(path) = self.text_channel.1.try_recv() {
let design = DsnDesign::load_from_file(&path).unwrap(); let design = DsnDesign::load_from_file(&path).unwrap();
let layout = design.make_layout(); let board = design.make_board();
self.overlay = Some(Overlay::new(&layout).unwrap()); self.overlay = Some(Overlay::new(&board).unwrap());
self.invoker = Some(Arc::new(Mutex::new(Invoker::new( self.invoker = Some(Arc::new(Mutex::new(Invoker::new(
Autorouter::new(layout).unwrap(), Autorouter::new(board).unwrap(),
)))); ))));
} }
} }
@ -359,22 +359,22 @@ impl eframe::App for App {
self.shared_data.lock().unwrap(), self.shared_data.lock().unwrap(),
&mut self.overlay, &mut self.overlay,
) { ) {
let layout = &invoker.autorouter().layout(); let board = invoker.autorouter().board();
if ctx.input(|i| i.pointer.any_click()) { if ctx.input(|i| i.pointer.any_click()) {
overlay.click( overlay.click(
layout, board,
point! {x: latest_pos.x as f64, y: -latest_pos.y as f64}, point! {x: latest_pos.x as f64, y: -latest_pos.y as f64},
); );
} }
for primitive in layout.drawing().layer_primitive_nodes(1) { for primitive in board.layout().drawing().layer_primitive_nodes(1) {
let shape = primitive.primitive(layout.drawing()).shape(); let shape = primitive.primitive(board.layout().drawing()).shape();
let color = if shared_data.highlighteds.contains(&primitive) let color = if shared_data.highlighteds.contains(&primitive)
|| overlay || overlay
.selection() .selection()
.contains_node(&layout, GenericNode::Primitive(primitive)) .contains_node(board, GenericNode::Primitive(primitive))
{ {
egui::Color32::from_rgb(100, 100, 255) egui::Color32::from_rgb(100, 100, 255)
} else { } else {
@ -383,25 +383,25 @@ impl eframe::App for App {
painter.paint_primitive(&shape, color); painter.paint_primitive(&shape, color);
} }
for zone in layout.layer_zone_nodes(1) { for zone in board.layout().layer_zone_nodes(1) {
let color = if overlay let color = if overlay
.selection() .selection()
.contains_node(&layout, GenericNode::Compound(zone)) .contains_node(board, GenericNode::Compound(zone))
{ {
egui::Color32::from_rgb(100, 100, 255) egui::Color32::from_rgb(100, 100, 255)
} else { } else {
egui::Color32::from_rgb(52, 52, 200) egui::Color32::from_rgb(52, 52, 200)
}; };
painter.paint_polygon(&layout.zone(zone).shape().polygon, color) painter.paint_polygon(&board.layout().zone(zone).shape().polygon, color)
} }
for primitive in layout.drawing().layer_primitive_nodes(0) { for primitive in board.layout().drawing().layer_primitive_nodes(0) {
let shape = primitive.primitive(layout.drawing()).shape(); let shape = primitive.primitive(board.layout().drawing()).shape();
let color = if shared_data.highlighteds.contains(&primitive) let color = if shared_data.highlighteds.contains(&primitive)
|| overlay || overlay
.selection() .selection()
.contains_node(&layout, GenericNode::Primitive(primitive)) .contains_node(board, GenericNode::Primitive(primitive))
{ {
egui::Color32::from_rgb(255, 100, 100) egui::Color32::from_rgb(255, 100, 100)
} else { } else {
@ -410,16 +410,16 @@ impl eframe::App for App {
painter.paint_primitive(&shape, color); painter.paint_primitive(&shape, color);
} }
for zone in layout.layer_zone_nodes(0) { for zone in board.layout().layer_zone_nodes(0) {
let color = if overlay let color = if overlay
.selection() .selection()
.contains_node(&layout, GenericNode::Compound(zone)) .contains_node(board, GenericNode::Compound(zone))
{ {
egui::Color32::from_rgb(255, 100, 100) egui::Color32::from_rgb(255, 100, 100)
} else { } else {
egui::Color32::from_rgb(200, 52, 52) egui::Color32::from_rgb(200, 52, 52)
}; };
painter.paint_polygon(&layout.zone(zone).shape().polygon, color) painter.paint_polygon(&board.layout().zone(zone).shape().polygon, color)
} }
if self.show_ratsnest { if self.show_ratsnest {
@ -447,9 +447,16 @@ impl eframe::App for App {
if let Some(navmesh) = &shared_data.navmesh { if let Some(navmesh) = &shared_data.navmesh {
for edge in navmesh.edge_references() { for edge in navmesh.edge_references() {
let from = let from = edge
edge.source().primitive(layout.drawing()).shape().center(); .source()
let to = edge.target().primitive(layout.drawing()).shape().center(); .primitive(board.layout().drawing())
.shape()
.center();
let to = edge
.target()
.primitive(board.layout().drawing())
.shape()
.center();
let stroke = 'blk: { let stroke = 'blk: {
if let (Some(source_pos), Some(target_pos)) = ( if let (Some(source_pos), Some(target_pos)) = (
@ -486,14 +493,14 @@ impl eframe::App for App {
if let (Some(from), Some(to)) = (shared_data.from, shared_data.to) { if let (Some(from), Some(to)) = (shared_data.from, shared_data.to) {
painter.paint_dot( painter.paint_dot(
Circle { Circle {
pos: layout.drawing().primitive(from).shape().center(), pos: board.layout().drawing().primitive(from).shape().center(),
r: 20.0, r: 20.0,
}, },
egui::Color32::from_rgb(255, 255, 100), egui::Color32::from_rgb(255, 255, 100),
); );
painter.paint_dot( painter.paint_dot(
Circle { Circle {
pos: layout.drawing().primitive(to).shape().center(), pos: board.layout().drawing().primitive(to).shape().center(),
r: 20.0, r: 20.0,
}, },
egui::Color32::from_rgb(255, 255, 100), egui::Color32::from_rgb(255, 255, 100),

View File

@ -5,7 +5,7 @@ use rstar::AABB;
use spade::InsertionError; use spade::InsertionError;
use topola::{ use topola::{
autorouter::{ratsnest::Ratsnest, selection::Selection}, autorouter::{board::Board, ratsnest::Ratsnest, selection::Selection},
drawing::{ drawing::{
graph::{GetLayer, MakePrimitive}, graph::{GetLayer, MakePrimitive},
primitive::MakePrimitiveShape, primitive::MakePrimitiveShape,
@ -25,16 +25,17 @@ pub struct Overlay {
} }
impl Overlay { impl Overlay {
pub fn new(layout: &Layout<impl RulesTrait>) -> Result<Self, InsertionError> { pub fn new(board: &Board<impl RulesTrait>) -> Result<Self, InsertionError> {
Ok(Self { Ok(Self {
ratsnest: Ratsnest::new(layout)?, ratsnest: Ratsnest::new(board.layout())?,
selection: Selection::new(), selection: Selection::new(),
active_layer: 0, active_layer: 0,
}) })
} }
pub fn click(&mut self, layout: &Layout<impl RulesTrait>, at: Point) { pub fn click(&mut self, board: &Board<impl RulesTrait>, at: Point) {
let geoms: Vec<_> = layout let geoms: Vec<_> = board
.layout()
.drawing() .drawing()
.rtree() .rtree()
.locate_in_envelope_intersecting(&AABB::<[f64; 3]>::from_corners( .locate_in_envelope_intersecting(&AABB::<[f64; 3]>::from_corners(
@ -45,17 +46,17 @@ impl Overlay {
if let Some(geom) = geoms.iter().find(|&&geom| match geom.data { if let Some(geom) = geoms.iter().find(|&&geom| match geom.data {
NodeIndex::Primitive(primitive) => { NodeIndex::Primitive(primitive) => {
primitive.primitive(layout.drawing()).layer() == self.active_layer primitive.primitive(board.layout().drawing()).layer() == self.active_layer
} }
NodeIndex::Compound(compound) => false, NodeIndex::Compound(compound) => false,
}) { }) {
if self.toggle_selection_if_contains_point(layout, geom.data, at) { if self.toggle_selection_if_contains_point(board, geom.data, at) {
return; return;
} }
} }
for geom in geoms { for geom in geoms {
if self.toggle_selection_if_contains_point(layout, geom.data, at) { if self.toggle_selection_if_contains_point(board, geom.data, at) {
return; return;
} }
} }
@ -63,17 +64,19 @@ impl Overlay {
fn toggle_selection_if_contains_point( fn toggle_selection_if_contains_point(
&mut self, &mut self,
layout: &Layout<impl RulesTrait>, board: &Board<impl RulesTrait>,
node: NodeIndex, node: NodeIndex,
p: Point, p: Point,
) -> bool { ) -> bool {
let shape: Shape = match node { let shape: Shape = match node {
NodeIndex::Primitive(primitive) => primitive.primitive(layout.drawing()).shape().into(), NodeIndex::Primitive(primitive) => {
NodeIndex::Compound(compound) => layout.zone(compound).shape().into(), primitive.primitive(board.layout().drawing()).shape().into()
}
NodeIndex::Compound(compound) => board.layout().zone(compound).shape().into(),
}; };
if shape.contains_point(p) { if shape.contains_point(p) {
self.selection.toggle_at_node(layout, node); self.selection.toggle_at_node(board, node);
return true; return true;
} }
false false

View File

@ -251,7 +251,7 @@ fn main() -> Result<(), anyhow::Error> {
)?; )?;
//let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?; //let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?;
//dbg!(&design); //dbg!(&design);
let layout = Arc::new(Mutex::new(design.make_layout())); let layout = Arc::new(Mutex::new(design.make_board()));
//let mut router = Router::new(layout); //let mut router = Router::new(layout);
let mut view = View { let mut view = View {

View File

@ -4,6 +4,7 @@ use geo::{point, Point, Rotate, Translate};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
autorouter::board::Board,
drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing}, drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing},
dsn::{ dsn::{
de, de,
@ -43,9 +44,9 @@ impl DsnDesign {
Ok(Self { pcb }) Ok(Self { pcb })
} }
pub fn make_layout(&self) -> Layout<DsnRules> { pub fn make_board(&self) -> Board<DsnRules> {
let rules = DsnRules::from_pcb(&self.pcb); let rules = DsnRules::from_pcb(&self.pcb);
let mut layout = Layout::new(Drawing::new(rules)); let mut board = Board::new(Layout::new(Drawing::new(rules)));
// mapping of pin id -> net id prepared for adding pins // mapping of pin id -> net id prepared for adding pins
let pin_nets = HashMap::<String, usize>::from_iter( let pin_nets = HashMap::<String, usize>::from_iter(
@ -55,7 +56,13 @@ impl DsnDesign {
.iter() .iter()
.map(|net| { .map(|net| {
// resolve the id so we don't work with strings // resolve the id so we don't work with strings
let net_id = layout.drawing().rules().net_ids.get(&net.name).unwrap(); let net_id = board
.layout()
.drawing()
.rules()
.net_ids
.get(&net.name)
.unwrap();
// take the list of pins // take the list of pins
// and for each pin id output (pin id, net id) // and for each pin id output (pin id, net id)
@ -92,13 +99,13 @@ impl DsnDesign {
match shape { match shape {
Shape::Circle(circle) => { Shape::Circle(circle) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&circle.layer, &circle.layer,
place.side == "front", place.side == "front",
); );
Self::add_circle( Self::add_circle(
&mut layout, &mut board,
(place.x as f64, place.y as f64).into(), (place.x as f64, place.y as f64).into(),
place.rotation as f64, place.rotation as f64,
(pin.x as f64, pin.y as f64).into(), (pin.x as f64, pin.y as f64).into(),
@ -111,13 +118,13 @@ impl DsnDesign {
} }
Shape::Rect(rect) => { Shape::Rect(rect) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&rect.layer, &rect.layer,
place.side == "front", place.side == "front",
); );
Self::add_rect( Self::add_rect(
&mut layout, &mut board,
(place.x as f64, place.y as f64).into(), (place.x as f64, place.y as f64).into(),
place.rotation as f64, place.rotation as f64,
(pin.x as f64, pin.y as f64).into(), (pin.x as f64, pin.y as f64).into(),
@ -133,13 +140,13 @@ impl DsnDesign {
} }
Shape::Path(path) => { Shape::Path(path) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&path.layer, &path.layer,
place.side == "front", place.side == "front",
); );
Self::add_path( Self::add_path(
&mut layout, &mut board,
(place.x as f64, place.y as f64).into(), (place.x as f64, place.y as f64).into(),
place.rotation as f64, place.rotation as f64,
(pin.x as f64, pin.y as f64).into(), (pin.x as f64, pin.y as f64).into(),
@ -153,13 +160,13 @@ impl DsnDesign {
} }
Shape::Polygon(polygon) => { Shape::Polygon(polygon) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&polygon.layer, &polygon.layer,
place.side == "front", place.side == "front",
); );
Self::add_polygon( Self::add_polygon(
&mut layout, &mut board,
(place.x as f64, place.y as f64).into(), (place.x as f64, place.y as f64).into(),
place.rotation as f64, place.rotation as f64,
(pin.x as f64, pin.y as f64).into(), (pin.x as f64, pin.y as f64).into(),
@ -178,7 +185,13 @@ impl DsnDesign {
} }
for via in &self.pcb.wiring.via_vec { for via in &self.pcb.wiring.via_vec {
let net_id = *layout.drawing().rules().net_ids.get(&via.net).unwrap(); let net_id = *board
.layout()
.drawing()
.rules()
.net_ids
.get(&via.net)
.unwrap();
// find the padstack referenced by this via placement // find the padstack referenced by this via placement
let padstack = &self let padstack = &self
@ -193,13 +206,13 @@ impl DsnDesign {
match shape { match shape {
Shape::Circle(circle) => { Shape::Circle(circle) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&circle.layer, &circle.layer,
true, true,
); );
Self::add_circle( Self::add_circle(
&mut layout, &mut board,
(0.0, 0.0).into(), (0.0, 0.0).into(),
0.0, 0.0,
(0.0, 0.0).into(), (0.0, 0.0).into(),
@ -212,13 +225,13 @@ impl DsnDesign {
} }
Shape::Rect(rect) => { Shape::Rect(rect) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&rect.layer, &rect.layer,
true, true,
); );
Self::add_rect( Self::add_rect(
&mut layout, &mut board,
(0.0, 0.0).into(), (0.0, 0.0).into(),
0.0, 0.0,
(0.0, 0.0).into(), (0.0, 0.0).into(),
@ -234,13 +247,13 @@ impl DsnDesign {
} }
Shape::Path(path) => { Shape::Path(path) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&path.layer, &path.layer,
true, true,
); );
Self::add_path( Self::add_path(
&mut layout, &mut board,
(0.0, 0.0).into(), (0.0, 0.0).into(),
0.0, 0.0,
(0.0, 0.0).into(), (0.0, 0.0).into(),
@ -254,13 +267,13 @@ impl DsnDesign {
} }
Shape::Polygon(polygon) => { Shape::Polygon(polygon) => {
let layer = Self::layer( let layer = Self::layer(
&mut layout, &mut board,
&self.pcb.structure.layer_vec, &self.pcb.structure.layer_vec,
&polygon.layer, &polygon.layer,
true, true,
); );
Self::add_polygon( Self::add_polygon(
&mut layout, &mut board,
(0.0, 0.0).into(), (0.0, 0.0).into(),
0.0, 0.0,
(0.0, 0.0).into(), (0.0, 0.0).into(),
@ -277,16 +290,23 @@ impl DsnDesign {
} }
for wire in self.pcb.wiring.wire_vec.iter() { for wire in self.pcb.wiring.wire_vec.iter() {
let layer_id = *layout let layer_id = *board
.layout()
.drawing() .drawing()
.rules() .rules()
.layer_ids .layer_ids
.get(&wire.path.layer) .get(&wire.path.layer)
.unwrap(); .unwrap();
let net_id = *layout.drawing().rules().net_ids.get(&wire.net).unwrap(); let net_id = *board
.layout()
.drawing()
.rules()
.net_ids
.get(&wire.net)
.unwrap();
Self::add_path( Self::add_path(
&mut layout, &mut board,
(0.0, 0.0).into(), (0.0, 0.0).into(),
0.0, 0.0,
(0.0, 0.0).into(), (0.0, 0.0).into(),
@ -299,16 +319,22 @@ impl DsnDesign {
); );
} }
layout board
} }
fn layer( fn layer(
layout: &Layout<DsnRules>, board: &Board<DsnRules>,
layer_vec: &Vec<Layer>, layer_vec: &Vec<Layer>,
layer_name: &str, layer_name: &str,
front: bool, front: bool,
) -> usize { ) -> usize {
let image_layer = *layout.drawing().rules().layer_ids.get(layer_name).unwrap(); let image_layer = *board
.layout()
.drawing()
.rules()
.layer_ids
.get(layer_name)
.unwrap();
if front { if front {
image_layer as usize image_layer as usize
@ -318,7 +344,7 @@ impl DsnDesign {
} }
fn add_circle( fn add_circle(
layout: &mut Layout<DsnRules>, board: &mut Board<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -333,7 +359,7 @@ impl DsnDesign {
r, r,
}; };
layout board
.add_fixed_dot( .add_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle, circle,
@ -346,7 +372,7 @@ impl DsnDesign {
} }
fn add_rect( fn add_rect(
layout: &mut Layout<DsnRules>, board: &mut Board<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -359,7 +385,7 @@ impl DsnDesign {
net: usize, net: usize,
maybe_pin: Option<String>, maybe_pin: Option<String>,
) { ) {
let zone = layout.add_zone( let zone = board.add_zone(
SolidZoneWeight { SolidZoneWeight {
layer, layer,
maybe_net: Some(net), maybe_net: Some(net),
@ -369,7 +395,7 @@ impl DsnDesign {
); );
// Corners. // Corners.
let dot_1_1 = layout let dot_1_1 = board
.add_zone_fixed_dot( .add_zone_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -382,7 +408,7 @@ impl DsnDesign {
zone, zone,
) )
.unwrap(); .unwrap();
let dot_2_1 = layout let dot_2_1 = board
.add_zone_fixed_dot( .add_zone_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -395,7 +421,7 @@ impl DsnDesign {
zone, zone,
) )
.unwrap(); .unwrap();
let dot_2_2 = layout let dot_2_2 = board
.add_zone_fixed_dot( .add_zone_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -408,7 +434,7 @@ impl DsnDesign {
zone, zone,
) )
.unwrap(); .unwrap();
let dot_1_2 = layout let dot_1_2 = board
.add_zone_fixed_dot( .add_zone_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -422,7 +448,7 @@ impl DsnDesign {
) )
.unwrap(); .unwrap();
// Sides. // Sides.
layout board
.add_zone_fixed_seg( .add_zone_fixed_seg(
dot_1_1, dot_1_1,
dot_2_1, dot_2_1,
@ -434,7 +460,7 @@ impl DsnDesign {
zone, zone,
) )
.unwrap(); .unwrap();
layout board
.add_zone_fixed_seg( .add_zone_fixed_seg(
dot_2_1, dot_2_1,
dot_2_2, dot_2_2,
@ -446,7 +472,7 @@ impl DsnDesign {
zone, zone,
) )
.unwrap(); .unwrap();
layout board
.add_zone_fixed_seg( .add_zone_fixed_seg(
dot_2_2, dot_2_2,
dot_1_2, dot_1_2,
@ -458,7 +484,7 @@ impl DsnDesign {
zone, zone,
) )
.unwrap(); .unwrap();
layout board
.add_zone_fixed_seg( .add_zone_fixed_seg(
dot_1_2, dot_1_2,
dot_1_1, dot_1_1,
@ -473,7 +499,7 @@ impl DsnDesign {
} }
fn add_path( fn add_path(
layout: &mut Layout<DsnRules>, board: &mut Board<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -493,7 +519,7 @@ impl DsnDesign {
coords[0].x as f64, coords[0].x as f64,
coords[0].y as f64, coords[0].y as f64,
); );
let mut prev_index = layout let mut prev_index = board
.add_fixed_dot( .add_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -522,7 +548,7 @@ impl DsnDesign {
continue; continue;
} }
let index = layout let index = board
.add_fixed_dot( .add_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -537,7 +563,7 @@ impl DsnDesign {
.unwrap(); .unwrap();
// add a seg between the current and previous coords // add a seg between the current and previous coords
let _ = layout let _ = board
.add_fixed_seg( .add_fixed_seg(
prev_index, prev_index,
index, index,
@ -556,7 +582,7 @@ impl DsnDesign {
} }
fn add_polygon( fn add_polygon(
layout: &mut Layout<DsnRules>, board: &mut Board<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -567,7 +593,7 @@ impl DsnDesign {
net: usize, net: usize,
maybe_pin: Option<String>, maybe_pin: Option<String>,
) { ) {
let zone = layout.add_zone( let zone = board.add_zone(
SolidZoneWeight { SolidZoneWeight {
layer, layer,
maybe_net: Some(net), maybe_net: Some(net),
@ -577,7 +603,7 @@ impl DsnDesign {
); );
// add the first coordinate in the wire path as a dot and save its index // add the first coordinate in the wire path as a dot and save its index
let mut prev_index = layout let mut prev_index = board
.add_zone_fixed_dot( .add_zone_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -602,7 +628,7 @@ impl DsnDesign {
// iterate through path coords starting from the second // iterate through path coords starting from the second
for coord in coords.iter().skip(1) { for coord in coords.iter().skip(1) {
let index = layout let index = board
.add_zone_fixed_dot( .add_zone_fixed_dot(
FixedDotWeight { FixedDotWeight {
circle: Circle { circle: Circle {
@ -626,7 +652,7 @@ impl DsnDesign {
.unwrap(); .unwrap();
// add a seg between the current and previous coords // add a seg between the current and previous coords
let _ = layout let _ = board
.add_zone_fixed_seg( .add_zone_fixed_seg(
prev_index, prev_index,
index, index,

View File

@ -33,15 +33,11 @@ pub type NodeIndex = GenericNode<PrimitiveIndex, GenericIndex<ZoneWeight>>;
#[derive(Debug)] #[derive(Debug)]
pub struct Layout<R: RulesTrait> { pub struct Layout<R: RulesTrait> {
drawing: Drawing<ZoneWeight, R>, drawing: Drawing<ZoneWeight, R>,
node_to_pin: HashMap<NodeIndex, String>,
} }
impl<R: RulesTrait> Layout<R> { impl<R: RulesTrait> Layout<R> {
pub fn new(drawing: Drawing<ZoneWeight, R>) -> Self { pub fn new(drawing: Drawing<ZoneWeight, R>) -> Self {
Self { Self { drawing }
drawing,
node_to_pin: HashMap::new(),
}
} }
pub fn remove_band(&mut self, band: BandIndex) { pub fn remove_band(&mut self, band: BandIndex) {
@ -65,19 +61,8 @@ impl<R: RulesTrait> Layout<R> {
.insert_segbend(from, around, dot_weight, seg_weight, bend_weight, cw) .insert_segbend(from, around, dot_weight, seg_weight, bend_weight, cw)
} }
pub fn add_fixed_dot( pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> {
&mut self, self.drawing.add_fixed_dot(weight)
weight: FixedDotWeight,
maybe_pin: Option<String>,
) -> Result<FixedDotIndex, Infringement> {
let dot = self.drawing.add_fixed_dot(weight)?;
if let Some(pin) = maybe_pin {
self.node_to_pin
.insert(GenericNode::Primitive(dot.into()), pin);
}
Ok(dot)
} }
pub fn add_zone_fixed_dot( pub fn add_zone_fixed_dot(
@ -85,7 +70,6 @@ impl<R: RulesTrait> Layout<R> {
weight: FixedDotWeight, weight: FixedDotWeight,
zone: GenericIndex<ZoneWeight>, zone: GenericIndex<ZoneWeight>,
) -> Result<FixedDotIndex, Infringement> { ) -> Result<FixedDotIndex, Infringement> {
let pin = self.node_pin(GenericNode::Compound(zone));
let maybe_dot = self.drawing.add_fixed_dot(weight); let maybe_dot = self.drawing.add_fixed_dot(weight);
if let Ok(dot) = maybe_dot { if let Ok(dot) = maybe_dot {
@ -100,16 +84,8 @@ impl<R: RulesTrait> Layout<R> {
from: FixedDotIndex, from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
weight: FixedSegWeight, weight: FixedSegWeight,
maybe_pin: Option<String>,
) -> Result<FixedSegIndex, Infringement> { ) -> Result<FixedSegIndex, Infringement> {
let seg = self.drawing.add_fixed_seg(from, to, weight)?; self.drawing.add_fixed_seg(from, to, weight)
if let Some(pin) = maybe_pin {
self.node_to_pin
.insert(GenericNode::Primitive(seg.into()), pin);
}
Ok(seg)
} }
pub fn add_zone_fixed_seg( pub fn add_zone_fixed_seg(
@ -119,8 +95,7 @@ impl<R: RulesTrait> Layout<R> {
weight: FixedSegWeight, weight: FixedSegWeight,
zone: GenericIndex<ZoneWeight>, zone: GenericIndex<ZoneWeight>,
) -> Result<FixedSegIndex, Infringement> { ) -> Result<FixedSegIndex, Infringement> {
let pin = self.node_pin(GenericNode::Compound(zone)); let maybe_seg = self.add_fixed_seg(from, to, weight);
let maybe_seg = self.add_fixed_seg(from, to, weight, pin.cloned());
if let Ok(seg) = maybe_seg { if let Ok(seg) = maybe_seg {
self.drawing.add_to_compound(seg, zone); self.drawing.add_to_compound(seg, zone);
@ -151,19 +126,8 @@ impl<R: RulesTrait> Layout<R> {
self.drawing.move_dot(dot, to) self.drawing.move_dot(dot, to)
} }
pub fn add_zone( pub fn add_zone(&mut self, weight: ZoneWeight) -> GenericIndex<ZoneWeight> {
&mut self, self.drawing.add_compound(weight)
weight: ZoneWeight,
maybe_pin: Option<String>,
) -> GenericIndex<ZoneWeight> {
let zone = self.drawing.add_compound(weight);
if let Some(pin) = maybe_pin {
self.node_to_pin
.insert(GenericNode::Compound(zone.into()), pin);
}
zone
} }
pub fn zones<W: 'static>( pub fn zones<W: 'static>(
@ -173,10 +137,6 @@ impl<R: RulesTrait> Layout<R> {
self.drawing.compounds(node) self.drawing.compounds(node)
} }
pub fn node_pin(&self, node: NodeIndex) -> Option<&String> {
self.node_to_pin.get(&node)
}
pub fn band_length(&self, face: DotIndex) -> f64 { pub fn band_length(&self, face: DotIndex) -> f64 {
// TODO. // TODO.
0.0 0.0

View File

@ -171,7 +171,6 @@ impl<'a, R: RulesTrait> Router<'a, R> {
) -> Result<BandIndex, RouterError> { ) -> Result<BandIndex, RouterError> {
let from = self.navmesh.from(); let from = self.navmesh.from();
let to = self.navmesh.to(); let to = self.navmesh.to();
//let mut tracer = self.tracer();
let mut tracer = Tracer::new(self.layout); let mut tracer = Tracer::new(self.layout);
let trace = tracer.start(from, width); let trace = tracer.start(from, width);
@ -201,10 +200,6 @@ impl<'a, R: RulesTrait> Router<'a, R> {
self.route_band(width, observer) self.route_band(width, observer)
}*/ }*/
/*fn tracer(&mut self) -> Tracer<R> {
Tracer::new(self.layout)
}*/
pub fn layout(&mut self) -> &mut Layout<R> { pub fn layout(&mut self) -> &mut Layout<R> {
self.layout self.layout
} }

View File

@ -18,13 +18,14 @@ use topola::{
#[test] #[test]
fn test() { fn test() {
let design = DsnDesign::load_from_file("tests/data/0603_breakout/0603_breakout.dsn").unwrap(); let design = DsnDesign::load_from_file("tests/data/0603_breakout/0603_breakout.dsn").unwrap();
let mut invoker = Invoker::new(Autorouter::new(design.make_layout()).unwrap()); let mut invoker = Invoker::new(Autorouter::new(design.make_board()).unwrap());
let file = File::open("tests/data/0603_breakout/autoroute_all.cmd").unwrap(); let file = File::open("tests/data/0603_breakout/autoroute_all.cmd").unwrap();
invoker.replay(serde_json::from_reader(file).unwrap()); invoker.replay(serde_json::from_reader(file).unwrap());
let mut unionfind = UnionFind::new( let mut unionfind = UnionFind::new(
invoker invoker
.autorouter() .autorouter()
.board()
.layout() .layout()
.drawing() .drawing()
.geometry() .geometry()
@ -34,6 +35,7 @@ fn test() {
for edge in invoker for edge in invoker
.autorouter() .autorouter()
.board()
.layout() .layout()
.drawing() .drawing()
.geometry() .geometry()