layout: implement storage for vias

This commit is contained in:
Mikolaj Wielgus 2024-06-09 17:24:12 +02:00
parent e5829d929a
commit fc1f7e2613
9 changed files with 164 additions and 36 deletions

View File

@ -114,7 +114,7 @@ impl Ratsnest {
} }
for zone in layout.layer_zone_nodes(layer) { for zone in layout.layer_zone_nodes(layer) {
if let Some(net) = layout.drawing().compound_weight(zone).maybe_net() { if let Some(net) = layout.drawing().compound_weight(zone.into()).maybe_net() {
if !triangulations.contains_key(&(layer, net)) { if !triangulations.contains_key(&(layer, net)) {
triangulations.insert( triangulations.insert(
(layer, net), (layer, net),

View File

@ -5,8 +5,9 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
board::{mesadata::MesadataTrait, Board}, board::{mesadata::MesadataTrait, Board},
drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex}, drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex},
graph::GenericIndex, geometry::compound::CompoundManagerTrait,
layout::NodeIndex, graph::{GenericIndex, GetNodeIndex},
layout::{zone::ZoneWeight, CompoundWeight, NodeIndex},
}; };
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
@ -64,7 +65,17 @@ impl Selection {
NodeIndex::Primitive(primitive) => { NodeIndex::Primitive(primitive) => {
primitive.primitive(board.layout().drawing()).layer() primitive.primitive(board.layout().drawing()).layer()
} }
NodeIndex::Compound(compound) => board.layout().zone(compound).layer(), NodeIndex::Compound(compound) => {
if let CompoundWeight::Zone(..) = board.layout().drawing().compound_weight(compound)
{
board
.layout()
.zone(GenericIndex::<ZoneWeight>::new(compound.node_index()))
.layer()
} else {
unreachable!()
}
}
}; };
if let (Some(pinname), Some(layername)) = ( if let (Some(pinname), Some(layername)) = (

View File

@ -386,7 +386,7 @@ impl eframe::App for App {
for zone in board.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(board, GenericNode::Compound(zone)) .contains_node(board, GenericNode::Compound(zone.into()))
{ {
egui::Color32::from_rgb(100, 100, 255) egui::Color32::from_rgb(100, 100, 255)
} else { } else {
@ -413,7 +413,7 @@ impl eframe::App for App {
for zone in board.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(board, GenericNode::Compound(zone)) .contains_node(board, GenericNode::Compound(zone.into()))
{ {
egui::Color32::from_rgb(255, 100, 100) egui::Color32::from_rgb(255, 100, 100)
} else { } else {

View File

@ -15,7 +15,11 @@ use topola::{
compound::CompoundManagerTrait, compound::CompoundManagerTrait,
shape::{Shape, ShapeTrait}, shape::{Shape, ShapeTrait},
}, },
layout::{zone::MakePolyShape, Layout, NodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::{
zone::{MakePolyShape, Zone, ZoneWeight},
CompoundWeight, Layout, NodeIndex,
},
}; };
pub struct Overlay { pub struct Overlay {
@ -72,7 +76,17 @@ impl Overlay {
NodeIndex::Primitive(primitive) => { NodeIndex::Primitive(primitive) => {
primitive.primitive(board.layout().drawing()).shape().into() primitive.primitive(board.layout().drawing()).shape().into()
} }
NodeIndex::Compound(compound) => board.layout().zone(compound).shape().into(), NodeIndex::Compound(compound) => {
match board.layout().drawing().compound_weight(compound) {
CompoundWeight::Zone(zone) => Zone::new(
GenericIndex::<ZoneWeight>::new(compound.node_index()),
board.layout(),
)
.shape()
.into(),
CompoundWeight::Via(via) => unreachable!(),
}
}
}; };
if shape.contains_point(p) { if shape.contains_point(p) {

View File

@ -58,7 +58,7 @@ impl<M: MesadataTrait> Board<M> {
) -> Result<FixedDotIndex, Infringement> { ) -> Result<FixedDotIndex, Infringement> {
let dot = self.layout.add_zone_fixed_dot(weight, zone)?; let dot = self.layout.add_zone_fixed_dot(weight, zone)?;
if let Some(pin) = self.node_pinname(GenericNode::Compound(zone)) { if let Some(pin) = self.node_pinname(GenericNode::Compound(zone.into())) {
self.node_to_pinname self.node_to_pinname
.insert(GenericNode::Primitive(dot.into()), pin.to_string()); .insert(GenericNode::Primitive(dot.into()), pin.to_string());
} }
@ -92,7 +92,7 @@ impl<M: MesadataTrait> Board<M> {
) -> Result<FixedSegIndex, Infringement> { ) -> Result<FixedSegIndex, Infringement> {
let seg = self.layout.add_zone_fixed_seg(from, to, weight, zone)?; let seg = self.layout.add_zone_fixed_seg(from, to, weight, zone)?;
if let Some(pin) = self.node_pinname(GenericNode::Compound(zone)) { if let Some(pin) = self.node_pinname(GenericNode::Compound(zone.into())) {
self.node_to_pinname self.node_to_pinname
.insert(GenericNode::Primitive(seg.into()), pin.to_string()); .insert(GenericNode::Primitive(seg.into()), pin.to_string());
} }

View File

@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use enum_dispatch::enum_dispatch;
use geo::Point; use geo::Point;
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use rstar::AABB; use rstar::AABB;
@ -26,19 +27,29 @@ use crate::{
GetWidth, SegWeightTrait, GetWidth, SegWeightTrait,
}, },
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::zone::{GetMaybeApex, MakePolyShape, PourZoneIndex, SolidZoneIndex, Zone, ZoneWeight}, layout::{
via::ViaWeight,
zone::{GetMaybeApex, MakePolyShape, Zone, ZoneWeight},
},
math::Circle, math::Circle,
}; };
pub type NodeIndex = GenericNode<PrimitiveIndex, GenericIndex<ZoneWeight>>; #[derive(Debug, Clone, Copy)]
#[enum_dispatch(GetMaybeNet)]
pub enum CompoundWeight {
Zone(ZoneWeight),
Via(ViaWeight),
}
pub type NodeIndex = GenericNode<PrimitiveIndex, GenericIndex<CompoundWeight>>;
#[derive(Debug)] #[derive(Debug)]
pub struct Layout<R: RulesTrait> { pub struct Layout<R: RulesTrait> {
drawing: Drawing<ZoneWeight, R>, drawing: Drawing<CompoundWeight, R>,
} }
impl<R: RulesTrait> Layout<R> { impl<R: RulesTrait> Layout<R> {
pub fn new(drawing: Drawing<ZoneWeight, R>) -> Self { pub fn new(drawing: Drawing<CompoundWeight, R>) -> Self {
Self { drawing } Self { drawing }
} }
@ -63,6 +74,21 @@ 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_via(&mut self, weight: ViaWeight) -> Result<GenericIndex<ViaWeight>, Infringement> {
let compound = self.drawing.add_compound(weight.into());
for layer in weight.from_layer..weight.to_layer {
let dot = self.drawing.add_fixed_dot(FixedDotWeight {
circle: weight.circle,
layer,
maybe_net: weight.maybe_net,
})?;
self.drawing.add_to_compound(dot, compound);
}
Ok(GenericIndex::<ViaWeight>::new(compound.node_index()))
}
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> { pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> {
self.drawing.add_fixed_dot(weight) self.drawing.add_fixed_dot(weight)
} }
@ -75,7 +101,7 @@ impl<R: RulesTrait> Layout<R> {
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 {
self.drawing.add_to_compound(dot, zone); self.drawing.add_to_compound(dot, zone.into());
} }
maybe_dot maybe_dot
@ -100,7 +126,7 @@ impl<R: RulesTrait> Layout<R> {
let maybe_seg = self.add_fixed_seg(from, to, weight); let maybe_seg = self.add_fixed_seg(from, to, weight);
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.into());
} }
maybe_seg maybe_seg
@ -129,13 +155,17 @@ impl<R: RulesTrait> Layout<R> {
} }
pub fn add_zone(&mut self, weight: ZoneWeight) -> GenericIndex<ZoneWeight> { pub fn add_zone(&mut self, weight: ZoneWeight) -> GenericIndex<ZoneWeight> {
self.drawing.add_compound(weight) GenericIndex::<ZoneWeight>::new(
self.drawing
.add_compound(CompoundWeight::Zone(weight))
.node_index(),
)
} }
pub fn zones<W: 'static>( pub fn zones<W: 'static>(
&self, &self,
node: GenericIndex<W>, node: GenericIndex<W>,
) -> impl Iterator<Item = GenericIndex<ZoneWeight>> + '_ { ) -> impl Iterator<Item = GenericIndex<CompoundWeight>> + '_ {
self.drawing.compounds(node) self.drawing.compounds(node)
} }
@ -171,11 +201,13 @@ impl<R: RulesTrait> Layout<R> {
pub fn zone_nodes(&self) -> impl Iterator<Item = GenericIndex<ZoneWeight>> + '_ { pub fn zone_nodes(&self) -> impl Iterator<Item = GenericIndex<ZoneWeight>> + '_ {
self.drawing.rtree().iter().filter_map(|wrapper| { self.drawing.rtree().iter().filter_map(|wrapper| {
if let NodeIndex::Compound(zone) = wrapper.data { if let NodeIndex::Compound(compound) = wrapper.data {
Some(zone) if let CompoundWeight::Zone(..) = self.drawing.compound_weight(compound) {
} else { return Some(GenericIndex::<ZoneWeight>::new(compound.node_index()));
None }
} }
None
}) })
} }
@ -190,11 +222,13 @@ impl<R: RulesTrait> Layout<R> {
[f64::INFINITY, f64::INFINITY, layer as f64], [f64::INFINITY, f64::INFINITY, layer as f64],
)) ))
.filter_map(|wrapper| { .filter_map(|wrapper| {
if let NodeIndex::Compound(zone) = wrapper.data { if let NodeIndex::Compound(compound) = wrapper.data {
Some(zone) if let CompoundWeight::Zone(..) = self.drawing.compound_weight(compound) {
} else { return Some(GenericIndex::<ZoneWeight>::new(compound.node_index()));
None }
} }
None
}) })
} }
@ -207,7 +241,7 @@ impl<R: RulesTrait> Layout<R> {
.compound_members(GenericIndex::new(zone.node_index())) .compound_members(GenericIndex::new(zone.node_index()))
} }
pub fn drawing(&self) -> &Drawing<ZoneWeight, R> { pub fn drawing(&self) -> &Drawing<CompoundWeight, R> {
&self.drawing &self.drawing
} }

View File

@ -1,4 +1,5 @@
mod layout; mod layout;
pub mod via;
pub mod zone; pub mod zone;
pub use layout::*; pub use layout::*;

48
src/layout/via.rs Normal file
View File

@ -0,0 +1,48 @@
use crate::{
drawing::{graph::GetMaybeNet, rules::RulesTrait},
geometry::compound::CompoundManagerTrait,
graph::{GenericIndex, GetNodeIndex},
layout::{CompoundWeight, Layout},
math::Circle,
};
#[derive(Debug)]
pub struct Via<'a, R: RulesTrait> {
pub index: GenericIndex<ViaWeight>,
layout: &'a Layout<R>,
}
impl<'a, R: RulesTrait> Via<'a, R> {
pub fn new(index: GenericIndex<ViaWeight>, layout: &'a Layout<R>) -> Self {
Self { index, layout }
}
}
impl<'a, R: RulesTrait> GetMaybeNet for Via<'a, R> {
fn maybe_net(&self) -> Option<usize> {
self.layout
.drawing()
.compound_weight(self.index.into())
.maybe_net()
}
}
#[derive(Debug, Clone, Copy)]
pub struct ViaWeight {
pub from_layer: u64,
pub to_layer: u64,
pub circle: Circle,
pub maybe_net: Option<usize>,
}
impl GetMaybeNet for ViaWeight {
fn maybe_net(&self) -> Option<usize> {
self.maybe_net
}
}
impl From<GenericIndex<ViaWeight>> for GenericIndex<CompoundWeight> {
fn from(via: GenericIndex<ViaWeight>) -> Self {
GenericIndex::<CompoundWeight>::new(via.node_index())
}
}

View File

@ -14,7 +14,7 @@ use crate::{
}, },
geometry::{compound::CompoundManagerTrait, poly::PolyShape, GetPos}, geometry::{compound::CompoundManagerTrait, poly::PolyShape, GetPos},
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::Layout, layout::{CompoundWeight, Layout},
}; };
#[enum_dispatch] #[enum_dispatch]
@ -52,7 +52,13 @@ impl<'a, R: RulesTrait> Zone<'a, R> {
impl<'a, R: RulesTrait> GetLayer for Zone<'a, R> { impl<'a, R: RulesTrait> GetLayer for Zone<'a, R> {
fn layer(&self) -> u64 { fn layer(&self) -> u64 {
self.layout.drawing().compound_weight(self.index).layer() if let CompoundWeight::Zone(weight) =
self.layout.drawing().compound_weight(self.index.into())
{
weight.layer()
} else {
unreachable!();
}
} }
} }
@ -60,7 +66,7 @@ impl<'a, R: RulesTrait> GetMaybeNet for Zone<'a, R> {
fn maybe_net(&self) -> Option<usize> { fn maybe_net(&self) -> Option<usize> {
self.layout self.layout
.drawing() .drawing()
.compound_weight(self.index) .compound_weight(self.index.into())
.maybe_net() .maybe_net()
} }
} }
@ -73,7 +79,7 @@ impl<'a, R: RulesTrait> MakePolyShape for Zone<'a, R> {
self.layout self.layout
.drawing() .drawing()
.geometry() .geometry()
.compound_members(self.index) .compound_members(self.index.into())
.filter_map(|primitive_node| { .filter_map(|primitive_node| {
let PrimitiveIndex::FixedDot(dot) = primitive_node else { let PrimitiveIndex::FixedDot(dot) = primitive_node else {
return None; return None;
@ -104,7 +110,7 @@ impl<'a, R: RulesTrait> GetMaybeApex for Zone<'a, R> {
self.layout self.layout
.drawing() .drawing()
.geometry() .geometry()
.compound_members(self.index) .compound_members(self.index.into())
.find_map(|primitive_node| { .find_map(|primitive_node| {
if let PrimitiveIndex::FixedDot(dot) = primitive_node { if let PrimitiveIndex::FixedDot(dot) = primitive_node {
if self.is_apex(dot) { if self.is_apex(dot) {
@ -124,25 +130,35 @@ pub enum ZoneWeight {
Pour(PourZoneWeight), Pour(PourZoneWeight),
} }
impl From<GenericIndex<ZoneWeight>> for GenericIndex<CompoundWeight> {
fn from(zone: GenericIndex<ZoneWeight>) -> Self {
GenericIndex::<CompoundWeight>::new(zone.node_index())
}
}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct SolidZoneWeight { pub struct SolidZoneWeight {
pub layer: u64, pub layer: u64,
pub maybe_net: Option<usize>, pub maybe_net: Option<usize>,
} }
impl<'a> GetLayer for SolidZoneWeight { impl GetLayer for SolidZoneWeight {
fn layer(&self) -> u64 { fn layer(&self) -> u64 {
self.layer self.layer
} }
} }
impl<'a> GetMaybeNet for SolidZoneWeight { impl GetMaybeNet for SolidZoneWeight {
fn maybe_net(&self) -> Option<usize> { fn maybe_net(&self) -> Option<usize> {
self.maybe_net self.maybe_net
} }
} }
pub type SolidZoneIndex = GenericIndex<SolidZoneWeight>; impl From<GenericIndex<SolidZoneWeight>> for GenericIndex<CompoundWeight> {
fn from(zone: GenericIndex<SolidZoneWeight>) -> Self {
GenericIndex::<CompoundWeight>::new(zone.node_index())
}
}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct PourZoneWeight { pub struct PourZoneWeight {
@ -162,4 +178,8 @@ impl<'a> GetMaybeNet for PourZoneWeight {
} }
} }
pub type PourZoneIndex = GenericIndex<PourZoneWeight>; impl From<GenericIndex<PourZoneWeight>> for GenericIndex<CompoundWeight> {
fn from(zone: GenericIndex<PourZoneWeight>) -> Self {
GenericIndex::<CompoundWeight>::new(zone.node_index())
}
}