From 9feb32955c8816b2a255efd00bccfcabb22899e7 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Thu, 11 Apr 2024 18:07:08 +0000 Subject: [PATCH] drawing,layout: move zones upwards, from drawing to layout This generally largely drawings from groupings. We need this because it will be easier to handle all groupings on the level of layout as continents and bands, which are groupings too, are to be tracked there. There's a lot of rough edges when it comes to typing and contracts. --- src/bin/topola-egui/app.rs | 29 +++--- src/bin/topola-sdl2-demo/main.rs | 6 +- src/draw.rs | 2 +- src/drawing/collect.rs | 8 +- src/drawing/drawing.rs | 157 ++++++++---------------------- src/drawing/graph.rs | 10 +- src/drawing/guide.rs | 8 +- src/drawing/loose.rs | 24 ++--- src/drawing/mod.rs | 1 - src/drawing/primitive.rs | 161 +++++++++++++++++-------------- src/drawing/segbend.rs | 2 +- src/dsn/design.rs | 121 +++++++++++++---------- src/geometry/with_rtree.rs | 3 +- src/layout/layout.rs | 144 ++++++++++++++++++++++++--- src/layout/mod.rs | 1 + src/{drawing => layout}/zone.rs | 10 +- src/mesh.rs | 7 +- src/triangulation.rs | 4 +- src/wraparoundable.rs | 20 ++-- 19 files changed, 405 insertions(+), 313 deletions(-) rename src/{drawing => layout}/zone.rs (87%) diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 0686116..8c1aaf8 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -5,9 +5,10 @@ use std::{ }; use topola::{ - drawing::{graph::MakePrimitive, primitive::MakeShape, zone::MakePolygon, Drawing}, + drawing::{graph::MakePrimitive, primitive::MakeShape, Drawing}, dsn::{design::DsnDesign, rules::DsnRules}, geometry::primitive::{BendShape, DotShape, PrimitiveShape, SegShape}, + layout::{zone::MakePolygon, Layout}, math::Circle, }; @@ -24,7 +25,7 @@ pub struct App { text_channel: (Sender, Receiver), #[serde(skip)] - drawing: Option>, + layout: Option>, #[serde(skip)] from_rect: egui::emath::Rect, @@ -36,7 +37,7 @@ impl Default for App { // Example stuff: label: "Hello World!".to_owned(), text_channel: channel(), - drawing: None, + layout: None, from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0), } } @@ -65,12 +66,12 @@ impl eframe::App for App { if cfg!(target_arch = "wasm32") { if let Ok(file_contents) = self.text_channel.1.try_recv() { let design = DsnDesign::load_from_string(file_contents).unwrap(); - self.drawing = Some(design.make_drawing()); + self.layout = Some(design.make_layout()); } } else { if let Ok(path) = self.text_channel.1.try_recv() { let design = DsnDesign::load_from_file(&path).unwrap(); - self.drawing = Some(design.make_drawing()); + self.layout = Some(design.make_layout()); } } @@ -138,27 +139,27 @@ impl eframe::App for App { let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect); let mut painter = Painter::new(ui, transform); - if let Some(drawing) = &self.drawing { - for node in drawing.layer_primitive_nodes(1) { - let shape = node.primitive(drawing).shape(); + if let Some(layout) = &self.layout { + for node in layout.drawing().layer_primitive_nodes(1) { + let shape = node.primitive(layout.drawing()).shape(); painter.paint_shape(&shape, egui::Color32::from_rgb(52, 52, 200)); } - for zone in drawing.layer_zones(1) { + for zone in layout.layer_zones(1) { painter.paint_polygon( - &zone.polygon(&drawing), + &zone.polygon(&layout.drawing()), egui::Color32::from_rgb(52, 52, 200), ) } - for node in drawing.layer_primitive_nodes(0) { - let shape = node.primitive(drawing).shape(); + for node in layout.drawing().layer_primitive_nodes(0) { + let shape = node.primitive(layout.drawing()).shape(); painter.paint_shape(&shape, egui::Color32::from_rgb(200, 52, 52)); } - for zone in drawing.layer_zones(0) { + for zone in layout.layer_zones(0) { painter.paint_polygon( - &zone.polygon(&drawing), + &zone.polygon(&layout.drawing()), egui::Color32::from_rgb(200, 52, 52), ) } diff --git a/src/bin/topola-sdl2-demo/main.rs b/src/bin/topola-sdl2-demo/main.rs index 567c91f..27c9027 100644 --- a/src/bin/topola-sdl2-demo/main.rs +++ b/src/bin/topola-sdl2-demo/main.rs @@ -19,7 +19,7 @@ use topola::drawing::primitive::MakeShape; use topola::drawing::rules::{Conditions, RulesTrait}; use topola::drawing::seg::FixedSegWeight; use topola::drawing::zone::MakePolygon; -use topola::drawing::{Drawing, Infringement, LayoutException}; +use topola::drawing::{Infringement, Layout, LayoutException}; use topola::dsn::design::DsnDesign; use topola::geometry::primitive::{PrimitiveShape, PrimitiveShapeTrait}; use topola::layout::connectivity::BandIndex; @@ -80,7 +80,7 @@ impl RulesTrait for SimpleRules { // Clunky enum to work around borrow checker. enum RouterOrDrawing<'a, R: RulesTrait> { Router(&'a mut Router), - Layout(&'a Drawing), + Layout(&'a Layout), } struct EmptyRouterObserver; @@ -260,7 +260,7 @@ fn main() -> Result<(), anyhow::Error> { )?; //let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?; //dbg!(&design); - let drawing = design.make_drawing(); + let drawing = design.make_layout(); let layout = Layout::new(drawing); let mut router = Router::new(layout); diff --git a/src/draw.rs b/src/draw.rs index 25b0a2b..93d50d9 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -268,7 +268,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> { Some(self.guide().head(prev_dot)) } - fn guide(&self) -> Guide { + fn guide(&self) -> Guide { Guide::new(self.layout.drawing()) } } diff --git a/src/drawing/collect.rs b/src/drawing/collect.rs index 451031a..8f24f6f 100644 --- a/src/drawing/collect.rs +++ b/src/drawing/collect.rs @@ -9,12 +9,12 @@ use super::{ }; #[derive(Debug)] -pub struct Collect<'a, R: RulesTrait> { - drawing: &'a Drawing, +pub struct Collect<'a, GW: Copy, R: RulesTrait> { + drawing: &'a Drawing, } -impl<'a, R: RulesTrait> Collect<'a, R> { - pub fn new(drawing: &'a Drawing) -> Self { +impl<'a, GW: Copy, R: RulesTrait> Collect<'a, GW, R> { + pub fn new(drawing: &'a Drawing) -> Self { Self { drawing } } diff --git a/src/drawing/drawing.rs b/src/drawing/drawing.rs index 78fe9ce..adc513e 100644 --- a/src/drawing/drawing.rs +++ b/src/drawing/drawing.rs @@ -2,14 +2,13 @@ use contracts::debug_ensures; use enum_dispatch::enum_dispatch; use geo::Point; -use rstar::{RTreeObject, AABB}; +use rstar::{RTree, RTreeObject, AABB}; use thiserror::Error; use super::graph::GetLayer; use super::loose::{GetNextLoose, Loose, LooseIndex}; use super::rules::RulesTrait; use super::segbend::Segbend; -use super::zone::SolidZoneWeight; use crate::drawing::bend::BendIndex; use crate::drawing::collect::Collect; use crate::drawing::dot::DotWeight; @@ -26,9 +25,9 @@ use crate::drawing::{ FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex, SeqLooseSegWeight, }, - zone::{PourZoneIndex, SolidZoneIndex, ZoneIndex, ZoneWeight}, }; use crate::geometry::grouping::GroupingManagerTrait; +use crate::geometry::with_rtree::BboxedIndex; use crate::geometry::Node; use crate::geometry::{ primitive::{PrimitiveShape, PrimitiveShapeTrait}, @@ -37,6 +36,7 @@ use crate::geometry::{ SegWeightTrait, }; use crate::graph::{GenericIndex, GetNodeIndex}; +use crate::layout::zone::{ZoneIndex, ZoneWeight}; use crate::math::NoTangents; use crate::wraparoundable::{GetWraparound, Wraparoundable, WraparoundableIndex}; @@ -70,13 +70,13 @@ pub struct Collision(pub PrimitiveShape, pub PrimitiveIndex); pub struct AlreadyConnected(pub usize, pub PrimitiveIndex); #[derive(Debug)] -pub struct Drawing { +pub struct Drawing { geometry_with_rtree: GeometryWithRtree< PrimitiveWeight, DotWeight, SegWeight, BendWeight, - ZoneWeight, + GW, PrimitiveIndex, DotIndex, SegIndex, @@ -85,7 +85,7 @@ pub struct Drawing { rules: R, } -impl Drawing { +impl Drawing { pub fn new(rules: R) -> Self { Self { geometry_with_rtree: GeometryWithRtree::new(2), @@ -153,19 +153,7 @@ impl Drawing { #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result { - self.add_dot_infringably(weight, None, None) - } - - #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 1))] - #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn add_zone_fixed_dot( - &mut self, - weight: FixedDotWeight, - zone: ZoneIndex, - ) -> Result { - self.add_dot_infringably(weight, Some(zone), None) + self.add_dot_infringably(weight, None) } #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] @@ -173,7 +161,6 @@ impl Drawing { fn add_dot_infringably + GetLayer>( &mut self, weight: W, - maybe_zone: Option, infringables: Option<&[PrimitiveIndex]>, ) -> Result, Infringement> where @@ -182,11 +169,6 @@ impl Drawing { let dot = self.geometry_with_rtree.add_dot(weight); self.fail_and_remove_if_infringes_except(dot.into(), infringables)?; - if let Some(zone) = maybe_zone { - self.geometry_with_rtree - .assign_to_grouping(dot, GenericIndex::new(zone.node_index())); - } - Ok(dot) } @@ -200,21 +182,7 @@ impl Drawing { to: FixedDotIndex, weight: FixedSegWeight, ) -> Result { - self.add_seg_infringably(from.into(), to.into(), weight, None, None) - } - - #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 3))] - #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn add_zone_fixed_seg( - &mut self, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - zone: ZoneIndex, - ) -> Result { - self.add_seg_infringably(from.into(), to.into(), weight, Some(zone), None) + self.add_seg_infringably(from.into(), to.into(), weight, None) } #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))] @@ -418,16 +386,16 @@ impl Drawing { cw: bool, infringables: Option<&[PrimitiveIndex]>, ) -> Result { - let seg_to = self.add_dot_infringably(dot_weight, None, infringables)?; + let seg_to = self.add_dot_infringably(dot_weight, infringables)?; let seg = self - .add_seg_infringably(from, seg_to.into(), seg_weight, None, infringables) + .add_seg_infringably(from, seg_to.into(), seg_weight, infringables) .map_err(|err| { self.geometry_with_rtree.remove_dot(seg_to.into()); err })?; let to = self - .add_dot_infringably(dot_weight, None, infringables) + .add_dot_infringably(dot_weight, infringables) .map_err(|err| { self.geometry_with_rtree.remove_seg(seg.into()); self.geometry_with_rtree.remove_dot(seg_to.into()); @@ -485,7 +453,7 @@ impl Drawing { to: FixedDotIndex, weight: LoneLooseSegWeight, ) -> Result { - let seg = self.add_seg_infringably(from.into(), to.into(), weight, None, Some(&[]))?; + let seg = self.add_seg_infringably(from.into(), to.into(), weight, Some(&[]))?; Ok(seg) } @@ -499,7 +467,7 @@ impl Drawing { to: LooseDotIndex, weight: SeqLooseSegWeight, ) -> Result { - let seg = self.add_seg_infringably(from, to.into(), weight, None, Some(&[]))?; + let seg = self.add_seg_infringably(from, to.into(), weight, Some(&[]))?; Ok(seg) } @@ -512,7 +480,6 @@ impl Drawing { from: DotIndex, to: DotIndex, weight: W, - maybe_zone: Option, infringables: Option<&[PrimitiveIndex]>, ) -> Result, Infringement> where @@ -521,11 +488,6 @@ impl Drawing { let seg = self.geometry_with_rtree.add_seg(from, to, weight); self.fail_and_remove_if_infringes_except(seg.into(), infringables)?; - if let Some(zone) = maybe_zone { - self.geometry_with_rtree - .assign_to_grouping(seg, GenericIndex::new(zone.node_index())); - } - Ok(seg) } @@ -647,14 +609,6 @@ impl Drawing { self.geometry_with_rtree.flip_bend(bend.into()); } - pub fn add_solid_zone(&mut self, weight: SolidZoneWeight) -> SolidZoneIndex { - GenericIndex::new( - self.geometry_with_rtree - .add_grouping(weight.into()) - .node_index(), - ) - } - pub fn segbend(&self, dot: LooseDotIndex) -> Segbend { Segbend::from_dot(dot, self) } @@ -709,60 +663,12 @@ impl Drawing { }) } - pub fn zones(&self) -> impl Iterator + '_ { - self.geometry_with_rtree - .rtree() - .iter() - .filter_map(|wrapper| { - if let Node::Grouping(zone) = wrapper.data { - Some(match self.geometry().grouping_weight(zone) { - ZoneWeight::Solid(..) => { - ZoneIndex::Solid(SolidZoneIndex::new(zone.node_index())) - } - ZoneWeight::Pour(..) => { - ZoneIndex::Pour(PourZoneIndex::new(zone.node_index())) - } - }) - } else { - None - } - }) - } - - pub fn layer_zones(&self, layer: u64) -> impl Iterator + '_ { - self.geometry_with_rtree - .rtree() - .locate_in_envelope_intersecting(&AABB::from_corners( - [-f64::INFINITY, -f64::INFINITY, layer as f64], - [f64::INFINITY, f64::INFINITY, layer as f64], - )) - .filter_map(|wrapper| { - if let Node::Grouping(zone) = wrapper.data { - Some(match self.geometry().grouping_weight(zone) { - ZoneWeight::Solid(..) => { - ZoneIndex::Solid(SolidZoneIndex::new(zone.node_index())) - } - ZoneWeight::Pour(..) => { - ZoneIndex::Pour(PourZoneIndex::new(zone.node_index())) - } - }) - } else { - None - } - }) - } - - pub fn zone_members(&self, zone: ZoneIndex) -> impl Iterator + '_ { - self.geometry() - .grouping_members(GenericIndex::new(zone.node_index())) - } - pub fn node_count(&self) -> usize { self.geometry_with_rtree.graph().node_count() } } -impl Drawing { +impl Drawing { #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> { @@ -906,7 +812,7 @@ impl Drawing { } } -impl Drawing { +impl Drawing { #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] pub fn geometry( @@ -916,7 +822,7 @@ impl Drawing { DotWeight, SegWeight, BendWeight, - ZoneWeight, + GW, PrimitiveIndex, DotIndex, SegIndex, @@ -925,6 +831,12 @@ impl Drawing { self.geometry_with_rtree.geometry() } + #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] + #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] + pub fn rtree(&self) -> &RTree>>> { + self.geometry_with_rtree.rtree() + } + #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] pub fn rules(&self) -> &R { @@ -933,31 +845,46 @@ impl Drawing { #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn guide(&self) -> Guide { + pub fn guide(&self) -> Guide { Guide::new(self) } #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn collect(&self) -> Collect { + pub fn collect(&self) -> Collect { Collect::new(self) } #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn primitive(&self, index: GenericIndex) -> GenericPrimitive { + pub fn primitive(&self, index: GenericIndex) -> GenericPrimitive { GenericPrimitive::new(index, self) } #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable { + pub fn wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable { Wraparoundable::new(index, self) } #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] - pub fn loose(&self, index: LooseIndex) -> Loose { + pub fn loose(&self, index: LooseIndex) -> Loose { Loose::new(index, self) } } + +impl GroupingManagerTrait> for Drawing { + fn add_grouping(&mut self, weight: GW) -> GenericIndex { + self.geometry_with_rtree.add_grouping(weight) + } + + fn remove_grouping(&mut self, grouping: GenericIndex) { + self.geometry_with_rtree.remove_grouping(grouping); + } + + fn assign_to_grouping(&mut self, primitive: GenericIndex, grouping: GenericIndex) { + self.geometry_with_rtree + .assign_to_grouping(primitive, grouping); + } +} diff --git a/src/drawing/graph.rs b/src/drawing/graph.rs index 589e42e..83e8b58 100644 --- a/src/drawing/graph.rs +++ b/src/drawing/graph.rs @@ -32,7 +32,10 @@ pub trait GetMaybeNet { #[enum_dispatch] pub trait MakePrimitive { - fn primitive<'a, R: RulesTrait>(&self, drawing: &'a Drawing) -> Primitive<'a, R>; + fn primitive<'a, GW: Copy, R: RulesTrait>( + &self, + drawing: &'a Drawing, + ) -> Primitive<'a, GW, R>; } macro_rules! impl_weight { @@ -58,7 +61,10 @@ macro_rules! impl_weight { pub type $index_struct = GenericIndex<$weight_struct>; impl MakePrimitive for $index_struct { - fn primitive<'a, R: RulesTrait>(&self, drawing: &'a Drawing) -> Primitive<'a, R> { + fn primitive<'a, GW: Copy, R: RulesTrait>( + &self, + drawing: &'a Drawing, + ) -> Primitive<'a, GW, R> { Primitive::$weight_variant(GenericPrimitive::new(*self, drawing)) } } diff --git a/src/drawing/guide.rs b/src/drawing/guide.rs index 79e75a8..44570b8 100644 --- a/src/drawing/guide.rs +++ b/src/drawing/guide.rs @@ -56,12 +56,12 @@ impl HeadTrait for SegbendHead { } } -pub struct Guide<'a, R: RulesTrait> { - drawing: &'a Drawing, +pub struct Guide<'a, GW: Copy, R: RulesTrait> { + drawing: &'a Drawing, } -impl<'a, R: RulesTrait> Guide<'a, R> { - pub fn new(drawing: &'a Drawing) -> Self { +impl<'a, GW: Copy, R: RulesTrait> Guide<'a, GW, R> { + pub fn new(drawing: &'a Drawing) -> Self { Self { drawing } } diff --git a/src/drawing/loose.rs b/src/drawing/loose.rs index 42f1061..7f824c8 100644 --- a/src/drawing/loose.rs +++ b/src/drawing/loose.rs @@ -40,16 +40,16 @@ impl From for PrimitiveIndex { } } -#[enum_dispatch(GetNextLoose, GetLayout, GetNodeIndex)] -pub enum Loose<'a, R: RulesTrait> { - Dot(LooseDot<'a, R>), - LoneSeg(LoneLooseSeg<'a, R>), - SeqSeg(SeqLooseSeg<'a, R>), - Bend(LooseBend<'a, R>), +#[enum_dispatch(GetNextLoose, GetDrawing, GetNodeIndex)] +pub enum Loose<'a, GW: Copy, R: RulesTrait> { + Dot(LooseDot<'a, GW, R>), + LoneSeg(LoneLooseSeg<'a, GW, R>), + SeqSeg(SeqLooseSeg<'a, GW, R>), + Bend(LooseBend<'a, GW, R>), } -impl<'a, R: RulesTrait> Loose<'a, R> { - pub fn new(index: LooseIndex, drawing: &'a Drawing) -> Self { +impl<'a, GW: Copy, R: RulesTrait> Loose<'a, GW, R> { + pub fn new(index: LooseIndex, drawing: &'a Drawing) -> Self { match index { LooseIndex::Dot(dot) => drawing.primitive(dot).into(), LooseIndex::LoneSeg(seg) => drawing.primitive(seg).into(), @@ -59,7 +59,7 @@ impl<'a, R: RulesTrait> Loose<'a, R> { } } -impl<'a, R: RulesTrait> GetNextLoose for LooseDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetNextLoose for LooseDot<'a, GW, R> { fn next_loose(&self, maybe_prev: Option) -> Option { let bend = self.bend(); let Some(prev) = maybe_prev else { @@ -74,13 +74,13 @@ impl<'a, R: RulesTrait> GetNextLoose for LooseDot<'a, R> { } } -impl<'a, R: RulesTrait> GetNextLoose for LoneLooseSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetNextLoose for LoneLooseSeg<'a, GW, R> { fn next_loose(&self, _maybe_prev: Option) -> Option { None } } -impl<'a, R: RulesTrait> GetNextLoose for SeqLooseSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetNextLoose for SeqLooseSeg<'a, GW, R> { fn next_loose(&self, maybe_prev: Option) -> Option { let ends = self.joints(); let Some(prev) = maybe_prev else { @@ -98,7 +98,7 @@ impl<'a, R: RulesTrait> GetNextLoose for SeqLooseSeg<'a, R> { } } -impl<'a, R: RulesTrait> GetNextLoose for LooseBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetNextLoose for LooseBend<'a, GW, R> { fn next_loose(&self, maybe_prev: Option) -> Option { let ends = self.joints(); let Some(prev) = maybe_prev else { diff --git a/src/drawing/mod.rs b/src/drawing/mod.rs index 1e59f5c..ddd431b 100644 --- a/src/drawing/mod.rs +++ b/src/drawing/mod.rs @@ -10,6 +10,5 @@ pub mod primitive; pub mod rules; pub mod seg; pub mod segbend; -pub mod zone; pub use drawing::*; diff --git a/src/drawing/primitive.rs b/src/drawing/primitive.rs index b4c0d81..938ac08 100644 --- a/src/drawing/primitive.rs +++ b/src/drawing/primitive.rs @@ -25,7 +25,7 @@ use crate::{ #[enum_dispatch] pub trait GetDrawing<'a, R: RulesTrait> { - fn drawing(&self) -> &Drawing; + fn drawing(&self) -> &Drawing; } #[enum_dispatch] @@ -117,7 +117,9 @@ pub trait GetInnerOuter<'a, R: RulesTrait>: GetDrawing<'a, R> + GetBendIndex { macro_rules! impl_primitive { ($primitive_struct:ident, $weight_struct:ident) => { - impl<'a, R: RulesTrait> GetWeight<$weight_struct> for $primitive_struct<'a, R> { + impl<'a, GW: Copy, R: RulesTrait> GetWeight<$weight_struct> + for $primitive_struct<'a, GW, R> + { fn weight(&self) -> $weight_struct { if let PrimitiveWeight::$primitive_struct(weight) = self.tagged_weight() { weight @@ -127,13 +129,13 @@ macro_rules! impl_primitive { } } - impl<'a, R: RulesTrait> GetLayer for $primitive_struct<'a, R> { + impl<'a, GW: Copy, R: RulesTrait> GetLayer for $primitive_struct<'a, GW, R> { fn layer(&self) -> u64 { self.weight().layer() } } - impl<'a, R: RulesTrait> GetMaybeNet for $primitive_struct<'a, R> { + impl<'a, GW: Copy, R: RulesTrait> GetMaybeNet for $primitive_struct<'a, GW, R> { fn maybe_net(&self) -> Option { self.weight().maybe_net() } @@ -157,29 +159,29 @@ macro_rules! impl_loose_primitive { GetLayer, GetMaybeNet, GetWidth, - GetLayout, + GetDrawing, MakeShape, GetLimbs, GetConditions )] -pub enum Primitive<'a, R: RulesTrait> { - FixedDot(FixedDot<'a, R>), - LooseDot(LooseDot<'a, R>), - FixedSeg(FixedSeg<'a, R>), - LoneLooseSeg(LoneLooseSeg<'a, R>), - SeqLooseSeg(SeqLooseSeg<'a, R>), - FixedBend(FixedBend<'a, R>), - LooseBend(LooseBend<'a, R>), +pub enum Primitive<'a, GW: Copy, R: RulesTrait> { + FixedDot(FixedDot<'a, GW, R>), + LooseDot(LooseDot<'a, GW, R>), + FixedSeg(FixedSeg<'a, GW, R>), + LoneLooseSeg(LoneLooseSeg<'a, GW, R>), + SeqLooseSeg(SeqLooseSeg<'a, GW, R>), + FixedBend(FixedBend<'a, GW, R>), + LooseBend(LooseBend<'a, GW, R>), } #[derive(Debug)] -pub struct GenericPrimitive<'a, W, R: RulesTrait> { +pub struct GenericPrimitive<'a, W, GW: Copy, R: RulesTrait> { pub index: GenericIndex, - drawing: &'a Drawing, + drawing: &'a Drawing, } -impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> { - pub fn new(index: GenericIndex, drawing: &'a Drawing) -> Self { +impl<'a, W, GW: Copy, R: RulesTrait> GenericPrimitive<'a, W, GW, R> { + pub fn new(index: GenericIndex, drawing: &'a Drawing) -> Self { Self { index, drawing } } @@ -197,41 +199,43 @@ impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> { } } - fn primitive(&self, index: GenericIndex) -> GenericPrimitive { + fn primitive(&self, index: GenericIndex) -> GenericPrimitive { GenericPrimitive::new(index, &self.drawing) } } -impl<'a, W, R: RulesTrait> GetInterior for GenericPrimitive<'a, W, R> { +impl<'a, W, GW: Copy, R: RulesTrait> GetInterior + for GenericPrimitive<'a, W, GW, R> +{ fn interior(&self) -> Vec { vec![self.tagged_weight().retag(self.index.node_index())] } } -impl<'a, W, R: RulesTrait> GetDrawing<'a, R> for GenericPrimitive<'a, W, R> { - fn drawing(&self) -> &Drawing { +impl<'a, W, GW: Copy, R: RulesTrait> GetDrawing<'a, R> for GenericPrimitive<'a, W, GW, R> { + fn drawing(&self) -> &Drawing { self.drawing } } -impl<'a, W, R: RulesTrait> GetNodeIndex for GenericPrimitive<'a, W, R> { +impl<'a, W, GW: Copy, R: RulesTrait> GetNodeIndex for GenericPrimitive<'a, W, GW, R> { fn node_index(&self) -> NodeIndex { self.index.node_index() } } -impl<'a, W: GetWidth, R: RulesTrait> GetWidth for GenericPrimitive<'a, W, R> +impl<'a, W: GetWidth, GW: Copy, R: RulesTrait> GetWidth for GenericPrimitive<'a, W, GW, R> where - GenericPrimitive<'a, W, R>: GetWeight, + GenericPrimitive<'a, W, GW, R>: GetWeight, { fn width(&self) -> f64 { self.weight().width() } } -impl<'a, W, R: RulesTrait> GetConditions for GenericPrimitive<'a, W, R> +impl<'a, W, GW: Copy, R: RulesTrait> GetConditions for GenericPrimitive<'a, W, GW, R> where - GenericPrimitive<'a, W, R>: GetMaybeNet, + GenericPrimitive<'a, W, GW, R>: GetMaybeNet, { fn conditions(&self) -> Conditions { Conditions { @@ -242,10 +246,10 @@ where } } -pub type FixedDot<'a, R> = GenericPrimitive<'a, FixedDotWeight, R>; +pub type FixedDot<'a, GW, R> = GenericPrimitive<'a, FixedDotWeight, GW, R>; impl_fixed_primitive!(FixedDot, FixedDotWeight); -impl<'a, R: RulesTrait> FixedDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> FixedDot<'a, GW, R> { pub fn first_loose(&self, _band: BandIndex) -> Option { self.drawing .geometry() @@ -269,13 +273,13 @@ impl<'a, R: RulesTrait> FixedDot<'a, R> { } } -impl<'a, R: RulesTrait> MakeShape for FixedDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for FixedDot<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().dot_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for FixedDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for FixedDot<'a, GW, R> { fn segs(&self) -> Vec { self.drawing .geometry() @@ -291,12 +295,12 @@ impl<'a, R: RulesTrait> GetLimbs for FixedDot<'a, R> { } } -impl<'a, R: RulesTrait> GetFirstRail<'a, R> for FixedDot<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetFirstRail<'a, R> for FixedDot<'a, GW, R> {} -pub type LooseDot<'a, R> = GenericPrimitive<'a, LooseDotWeight, R>; +pub type LooseDot<'a, GW, R> = GenericPrimitive<'a, LooseDotWeight, GW, R>; impl_loose_primitive!(LooseDot, LooseDotWeight); -impl<'a, R: RulesTrait> LooseDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> LooseDot<'a, GW, R> { pub fn seg(&self) -> Option { self.drawing .geometry() @@ -315,13 +319,13 @@ impl<'a, R: RulesTrait> LooseDot<'a, R> { } } -impl<'a, R: RulesTrait> MakeShape for LooseDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for LooseDot<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().dot_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for LooseDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for LooseDot<'a, GW, R> { fn segs(&self) -> Vec { if let Some(seg) = self.seg() { vec![seg.into()] @@ -335,18 +339,18 @@ impl<'a, R: RulesTrait> GetLimbs for LooseDot<'a, R> { } } -pub type FixedSeg<'a, R> = GenericPrimitive<'a, FixedSegWeight, R>; +pub type FixedSeg<'a, GW, R> = GenericPrimitive<'a, FixedSegWeight, GW, R>; impl_fixed_primitive!(FixedSeg, FixedSegWeight); -impl<'a, R: RulesTrait> MakeShape for FixedSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for FixedSeg<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().seg_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for FixedSeg<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for FixedSeg<'a, GW, R> {} -impl<'a, R: RulesTrait> GetJoints for FixedSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetJoints for FixedSeg<'a, GW, R> { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { let (from, to) = self.drawing.geometry().seg_joints(self.index.into()); ( @@ -356,20 +360,25 @@ impl<'a, R: RulesTrait> GetJoints for FixedSeg<'a, } } -impl<'a, R: RulesTrait> GetOtherJoint for FixedSeg<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint + for FixedSeg<'a, GW, R> +{ +} -pub type LoneLooseSeg<'a, R> = GenericPrimitive<'a, LoneLooseSegWeight, R>; +pub type LoneLooseSeg<'a, GW, R> = GenericPrimitive<'a, LoneLooseSegWeight, GW, R>; impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight); -impl<'a, R: RulesTrait> MakeShape for LoneLooseSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for LoneLooseSeg<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().seg_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for LoneLooseSeg<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for LoneLooseSeg<'a, GW, R> {} -impl<'a, R: RulesTrait> GetJoints for LoneLooseSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetJoints + for LoneLooseSeg<'a, GW, R> +{ fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { let (from, to) = self.drawing.geometry().seg_joints(self.index.into()); ( @@ -379,20 +388,23 @@ impl<'a, R: RulesTrait> GetJoints for LoneLooseSeg } } -impl<'a, R: RulesTrait> GetOtherJoint for LoneLooseSeg<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint + for LoneLooseSeg<'a, GW, R> +{ +} -pub type SeqLooseSeg<'a, R> = GenericPrimitive<'a, SeqLooseSegWeight, R>; +pub type SeqLooseSeg<'a, GW, R> = GenericPrimitive<'a, SeqLooseSegWeight, GW, R>; impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight); -impl<'a, R: RulesTrait> MakeShape for SeqLooseSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for SeqLooseSeg<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().seg_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for SeqLooseSeg<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for SeqLooseSeg<'a, GW, R> {} -impl<'a, R: RulesTrait> GetJoints for SeqLooseSeg<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetJoints for SeqLooseSeg<'a, GW, R> { fn joints(&self) -> (DotIndex, LooseDotIndex) { let joints = self.drawing.geometry().seg_joints(self.index.into()); if let DotWeight::Fixed(..) = self.drawing.geometry().dot_weight(joints.0) { @@ -414,26 +426,29 @@ impl<'a, R: RulesTrait> GetJoints for SeqLooseSeg<'a, R } } -impl<'a, R: RulesTrait> GetOtherJoint for SeqLooseSeg<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint + for SeqLooseSeg<'a, GW, R> +{ +} -pub type FixedBend<'a, R> = GenericPrimitive<'a, FixedBendWeight, R>; +pub type FixedBend<'a, GW, R> = GenericPrimitive<'a, FixedBendWeight, GW, R>; impl_fixed_primitive!(FixedBend, FixedBendWeight); -impl<'a, R: RulesTrait> GetBendIndex for FixedBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetBendIndex for FixedBend<'a, GW, R> { fn bend_index(&self) -> BendIndex { self.index.into() } } -impl<'a, R: RulesTrait> MakeShape for FixedBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for FixedBend<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().bend_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for FixedBend<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for FixedBend<'a, GW, R> {} -impl<'a, R: RulesTrait> GetJoints for FixedBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetJoints for FixedBend<'a, GW, R> { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { let (from, to) = self.drawing.geometry().bend_joints(self.index.into()); ( @@ -443,41 +458,44 @@ impl<'a, R: RulesTrait> GetJoints for FixedBend<'a } } -impl<'a, R: RulesTrait> GetOtherJoint for FixedBend<'a, R> {} -impl<'a, R: RulesTrait> GetFirstRail<'a, R> for FixedBend<'a, R> {} -impl<'a, R: RulesTrait> GetCore<'a, R> for FixedBend<'a, R> {} // TODO: Fixed bends don't have cores actually. - //impl<'a, R: QueryRules> GetInnerOuter for FixedBend<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint + for FixedBend<'a, GW, R> +{ +} +impl<'a, GW: Copy, R: RulesTrait> GetFirstRail<'a, R> for FixedBend<'a, GW, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetCore<'a, R> for FixedBend<'a, GW, R> {} // TODO: Fixed bends don't have cores actually. + //impl<'a, R: QueryRules> GetInnerOuter for FixedBend<'a, GW, R> {} -pub type LooseBend<'a, R> = GenericPrimitive<'a, LooseBendWeight, R>; +pub type LooseBend<'a, GW, R> = GenericPrimitive<'a, LooseBendWeight, GW, R>; impl_loose_primitive!(LooseBend, LooseBendWeight); -impl<'a, R: RulesTrait> GetBendIndex for LooseBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetBendIndex for LooseBend<'a, GW, R> { fn bend_index(&self) -> BendIndex { self.index.into() } } -impl<'a, R: RulesTrait> From> for BendIndex { - fn from(bend: LooseBend<'a, R>) -> BendIndex { +impl<'a, GW: Copy, R: RulesTrait> From> for BendIndex { + fn from(bend: LooseBend<'a, GW, R>) -> BendIndex { bend.index.into() } } -impl<'a, R: RulesTrait> MakeShape for LooseBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> MakeShape for LooseBend<'a, GW, R> { fn shape(&self) -> PrimitiveShape { self.drawing.geometry().bend_shape(self.index.into()) } } -impl<'a, R: RulesTrait> GetLimbs for LooseBend<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetLimbs for LooseBend<'a, GW, R> {} -impl<'a, R: RulesTrait> GetOffset for LooseBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetOffset for LooseBend<'a, GW, R> { fn offset(&self) -> f64 { self.weight().offset } } -impl<'a, R: RulesTrait> GetJoints for LooseBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetJoints for LooseBend<'a, GW, R> { fn joints(&self) -> (LooseDotIndex, LooseDotIndex) { let (from, to) = self.drawing.geometry().bend_joints(self.index.into()); ( @@ -487,6 +505,9 @@ impl<'a, R: RulesTrait> GetJoints for LooseBend<'a } } -impl<'a, R: RulesTrait> GetOtherJoint for LooseBend<'a, R> {} -impl<'a, R: RulesTrait> GetCore<'a, R> for LooseBend<'a, R> {} -impl<'a, R: RulesTrait> GetInnerOuter<'a, R> for LooseBend<'a, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint + for LooseBend<'a, GW, R> +{ +} +impl<'a, GW: Copy, R: RulesTrait> GetCore<'a, R> for LooseBend<'a, GW, R> {} +impl<'a, GW: Copy, R: RulesTrait> GetInnerOuter<'a, R> for LooseBend<'a, GW, R> {} diff --git a/src/drawing/segbend.rs b/src/drawing/segbend.rs index 39e6b89..7f3c804 100644 --- a/src/drawing/segbend.rs +++ b/src/drawing/segbend.rs @@ -17,7 +17,7 @@ pub struct Segbend { } impl Segbend { - pub fn from_dot(dot: LooseDotIndex, drawing: &Drawing) -> Self { + pub fn from_dot(dot: LooseDotIndex, drawing: &Drawing) -> Self { let bend = LooseDot::new(dot, drawing).bend(); let dot = LooseBend::new(bend, drawing).other_joint(dot); let seg = LooseDot::new(dot, drawing).seg().unwrap(); diff --git a/src/dsn/design.rs b/src/dsn/design.rs index b66fb4f..79f66ef 100644 --- a/src/dsn/design.rs +++ b/src/dsn/design.rs @@ -4,17 +4,18 @@ use geo::{point, Point, Rotate, Translate}; use thiserror::Error; use crate::{ - drawing::{ - dot::FixedDotWeight, - seg::FixedSegWeight, - zone::{SolidZoneWeight, ZoneIndex}, - Drawing, - }, + drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing}, dsn::{ de, rules::DsnRules, structure::{self, DsnFile, Layer, Pcb, Shape}, }, + geometry::grouping::GroupingManagerTrait, + graph::{GenericIndex, GetNodeIndex}, + layout::{ + zone::{SolidZoneWeight, ZoneIndex}, + Layout, + }, math::Circle, }; @@ -45,9 +46,9 @@ impl DsnDesign { Ok(Self { pcb }) } - pub fn make_drawing(&self) -> Drawing { + pub fn make_layout(&self) -> Layout { let rules = DsnRules::from_pcb(&self.pcb); - let mut layout = Drawing::new(rules); + let mut layout = Layout::new(Drawing::new(rules)); // mapping of pin id -> net id prepared for adding pins let pin_nets = HashMap::::from_iter( @@ -57,7 +58,7 @@ impl DsnDesign { .iter() .map(|net| { // resolve the id so we don't work with strings - let net_id = layout.rules().net_ids.get(&net.name).unwrap(); + let net_id = layout.drawing().rules().net_ids.get(&net.name).unwrap(); // take the list of pins // and for each pin id output (pin id, net id) @@ -176,7 +177,7 @@ impl DsnDesign { } for via in &self.pcb.wiring.via_vec { - let net_id = *layout.rules().net_ids.get(&via.net).unwrap(); + let net_id = *layout.drawing().rules().net_ids.get(&via.net).unwrap(); // find the padstack referenced by this via placement let padstack = &self @@ -271,8 +272,13 @@ impl DsnDesign { } for wire in self.pcb.wiring.wire_vec.iter() { - let layer_id = *layout.rules().layer_ids.get(&wire.path.layer).unwrap(); - let net_id = *layout.rules().net_ids.get(&wire.net).unwrap(); + let layer_id = *layout + .drawing() + .rules() + .layer_ids + .get(&wire.path.layer) + .unwrap(); + let net_id = *layout.drawing().rules().net_ids.get(&wire.net).unwrap(); Self::add_path( &mut layout, @@ -291,12 +297,12 @@ impl DsnDesign { } fn layer( - drawing: &Drawing, + layout: &Layout, layer_vec: &Vec, layer_name: &str, front: bool, ) -> usize { - let image_layer = *drawing.rules().layer_ids.get(layer_name).unwrap(); + let image_layer = *layout.drawing().rules().layer_ids.get(layer_name).unwrap(); if front { image_layer as usize @@ -306,7 +312,7 @@ impl DsnDesign { } fn add_circle( - drawing: &mut Drawing, + layout: &mut Layout, place_pos: Point, place_rot: f64, pin_pos: Point, @@ -320,7 +326,7 @@ impl DsnDesign { r, }; - drawing + layout .add_fixed_dot(FixedDotWeight { circle, layer, @@ -330,7 +336,7 @@ impl DsnDesign { } fn add_rect( - drawing: &mut Drawing, + layout: &mut Layout, place_pos: Point, place_rot: f64, pin_pos: Point, @@ -342,13 +348,16 @@ impl DsnDesign { layer: u64, net: usize, ) { - let zone = drawing.add_solid_zone(SolidZoneWeight { - layer, - maybe_net: Some(net), - }); + let zone = layout.add_grouping( + SolidZoneWeight { + layer, + maybe_net: Some(net), + } + .into(), + ); // Corners. - let dot_1_1 = drawing + let dot_1_1 = layout .add_zone_fixed_dot( FixedDotWeight { circle: Circle { @@ -358,11 +367,10 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); - - let dot_2_1 = drawing + let dot_2_1 = layout .add_zone_fixed_dot( FixedDotWeight { circle: Circle { @@ -372,10 +380,10 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); - let dot_2_2 = drawing + let dot_2_2 = layout .add_zone_fixed_dot( FixedDotWeight { circle: Circle { @@ -385,10 +393,10 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); - let dot_1_2 = drawing + let dot_1_2 = layout .add_zone_fixed_dot( FixedDotWeight { circle: Circle { @@ -398,11 +406,11 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); // Sides. - drawing + layout .add_zone_fixed_seg( dot_1_1, dot_2_1, @@ -411,10 +419,10 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); - drawing + layout .add_zone_fixed_seg( dot_2_1, dot_2_2, @@ -423,10 +431,10 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); - drawing + layout .add_zone_fixed_seg( dot_2_2, dot_1_2, @@ -435,10 +443,10 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); - drawing + layout .add_zone_fixed_seg( dot_1_2, dot_1_1, @@ -447,13 +455,13 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); } fn add_path( - drawing: &mut Drawing, + layout: &mut Layout, place_pos: Point, place_rot: f64, pin_pos: Point, @@ -464,7 +472,7 @@ impl DsnDesign { net: usize, ) { // add the first coordinate in the wire path as a dot and save its index - let mut prev_index = drawing + let mut prev_index = layout .add_fixed_dot(FixedDotWeight { circle: Circle { pos: Self::pos( @@ -484,7 +492,7 @@ impl DsnDesign { // iterate through path coords starting from the second for coord in coords.iter().skip(1) { - let index = drawing + let index = layout .add_fixed_dot(FixedDotWeight { circle: Circle { pos: Self::pos( @@ -504,7 +512,7 @@ impl DsnDesign { .unwrap(); // add a seg between the current and previous coords - let _ = drawing + let _ = layout .add_fixed_seg( prev_index, index, @@ -521,7 +529,7 @@ impl DsnDesign { } fn add_polygon( - drawing: &mut Drawing, + layout: &mut Layout, place_pos: Point, place_rot: f64, pin_pos: Point, @@ -531,13 +539,16 @@ impl DsnDesign { layer: u64, net: usize, ) { - let zone = drawing.add_solid_zone(SolidZoneWeight { - layer, - maybe_net: Some(net), - }); + let zone = layout.add_grouping( + SolidZoneWeight { + layer, + maybe_net: Some(net), + } + .into(), + ); // add the first coordinate in the wire path as a dot and save its index - let mut prev_index = drawing + let mut prev_index = layout .add_zone_fixed_dot( FixedDotWeight { circle: Circle { @@ -554,13 +565,15 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + // TODO: This manual retagging shouldn't be necessary, `.into()` should suffice. + //GenericIndex::new(zone.node_index()).into(), + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); // iterate through path coords starting from the second for coord in coords.iter().skip(1) { - let index = drawing + let index = layout .add_zone_fixed_dot( FixedDotWeight { circle: Circle { @@ -578,12 +591,13 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + // TODO: This manual retagging shouldn't be necessary, `.into()` should suffice. + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); // add a seg between the current and previous coords - let _ = drawing + let _ = layout .add_zone_fixed_seg( prev_index, index, @@ -592,7 +606,8 @@ impl DsnDesign { layer, maybe_net: Some(net), }, - zone.into(), + // TODO: This manual retagging shouldn't be necessary, `.into()` should suffice. + ZoneIndex::Solid(GenericIndex::new(zone.node_index())), ) .unwrap(); diff --git a/src/geometry/with_rtree.rs b/src/geometry/with_rtree.rs index 851ebc1..39a810d 100644 --- a/src/geometry/with_rtree.rs +++ b/src/geometry/with_rtree.rs @@ -33,7 +33,7 @@ impl RTreeObject for Bbox { } } -type BboxedIndex = GeomWithData; +pub type BboxedIndex = GeomWithData; #[derive(Debug)] pub struct GeometryWithRtree< @@ -354,6 +354,7 @@ impl< &self.geometry } + // XXX: The type appears wrong? I don't think it should contain GW? pub fn rtree(&self) -> &RTree>>> { &self.rtree } diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 1220600..1c9b185 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -1,30 +1,41 @@ use geo::Point; use petgraph::stable_graph::StableDiGraph; +use rstar::AABB; use crate::{ drawing::{ bend::LooseBendWeight, - dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight}, + dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, + graph::{PrimitiveIndex, Retag}, rules::RulesTrait, - seg::{LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex, SeqLooseSegWeight}, + seg::{ + FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex, + SeqLooseSegWeight, + }, segbend::Segbend, Drawing, Infringement, LayoutException, }, - graph::GetNodeIndex, + geometry::{ + grouping::GroupingManagerTrait, BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, + GetWidth, Node, SegWeightTrait, + }, + graph::{GenericIndex, GetNodeIndex}, + layout::{ + connectivity::{ + BandIndex, BandWeight, ConnectivityLabel, ConnectivityWeight, ContinentIndex, + }, + zone::{PourZoneIndex, SolidZoneIndex, ZoneIndex, ZoneWeight}, + }, wraparoundable::WraparoundableIndex, }; -use super::connectivity::{ - BandIndex, BandWeight, ConnectivityLabel, ConnectivityWeight, ContinentIndex, -}; - pub struct Layout { - drawing: Drawing, // Shouldn't be public, but is for now because `Draw` needs it. + drawing: Drawing, // Shouldn't be public, but is for now because `Draw` needs it. connectivity: StableDiGraph, } impl Layout { - pub fn new(drawing: Drawing) -> Self { + pub fn new(drawing: Drawing) -> Self { Self { drawing, connectivity: StableDiGraph::default(), @@ -72,6 +83,51 @@ impl Layout { .insert_segbend(from, around, dot_weight, seg_weight, bend_weight, cw) } + pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result { + self.drawing.add_fixed_dot(weight) + } + + pub fn add_zone_fixed_dot( + &mut self, + weight: FixedDotWeight, + zone: ZoneIndex, + ) -> Result { + let maybe_dot = self.drawing.add_fixed_dot(weight); + + if let Ok(dot) = maybe_dot { + self.drawing + .assign_to_grouping(dot, GenericIndex::new(zone.node_index())); + } + + maybe_dot + } + + pub fn add_fixed_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + ) -> Result { + self.drawing.add_fixed_seg(from, to, weight) + } + + pub fn add_zone_fixed_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + zone: ZoneIndex, + ) -> Result { + let maybe_seg = self.add_fixed_seg(from, to, weight); + + if let Ok(seg) = maybe_seg { + self.drawing + .assign_to_grouping(seg, GenericIndex::new(zone.node_index())); + } + + maybe_seg + } + pub fn add_lone_loose_seg( &mut self, from: FixedDotIndex, @@ -107,12 +163,74 @@ impl Layout { 0.0 } - pub fn drawing(&self) -> &Drawing { - &self.drawing - } - pub fn continent(&self, dot: FixedDotIndex) -> ContinentIndex { // TODO. ContinentIndex::new(0.into()) } + + pub fn zones(&self) -> impl Iterator + '_ { + self.drawing.rtree().iter().filter_map(|wrapper| { + if let Node::Grouping(zone) = wrapper.data { + Some(match self.drawing.geometry().grouping_weight(zone) { + ZoneWeight::Solid(..) => { + ZoneIndex::Solid(SolidZoneIndex::new(zone.node_index())) + } + ZoneWeight::Pour(..) => ZoneIndex::Pour(PourZoneIndex::new(zone.node_index())), + }) + } else { + None + } + }) + } + + pub fn layer_zones(&self, layer: u64) -> impl Iterator + '_ { + self.drawing + .rtree() + .locate_in_envelope_intersecting(&AABB::from_corners( + [-f64::INFINITY, -f64::INFINITY, layer as f64], + [f64::INFINITY, f64::INFINITY, layer as f64], + )) + .filter_map(|wrapper| { + if let Node::Grouping(zone) = wrapper.data { + Some(match self.drawing.geometry().grouping_weight(zone) { + ZoneWeight::Solid(..) => { + ZoneIndex::Solid(SolidZoneIndex::new(zone.node_index())) + } + ZoneWeight::Pour(..) => { + ZoneIndex::Pour(PourZoneIndex::new(zone.node_index())) + } + }) + } else { + None + } + }) + } + + pub fn zone_members(&self, zone: ZoneIndex) -> impl Iterator + '_ { + self.drawing + .geometry() + .grouping_members(GenericIndex::new(zone.node_index())) + } + + pub fn drawing(&self) -> &Drawing { + &self.drawing + } +} + +impl GroupingManagerTrait> for Layout { + fn add_grouping(&mut self, weight: ZoneWeight) -> GenericIndex { + self.drawing.add_grouping(weight) + } + + fn remove_grouping(&mut self, grouping: GenericIndex) { + self.drawing.remove_grouping(grouping); + } + + fn assign_to_grouping( + &mut self, + primitive: GenericIndex, + grouping: GenericIndex, + ) { + self.drawing.assign_to_grouping(primitive, grouping); + } } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index fb19bf4..a415a3a 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,4 +1,5 @@ pub mod connectivity; mod layout; +pub mod zone; pub use layout::*; diff --git a/src/drawing/zone.rs b/src/layout/zone.rs similarity index 87% rename from src/drawing/zone.rs rename to src/layout/zone.rs index 5ca8e89..14e3eed 100644 --- a/src/drawing/zone.rs +++ b/src/layout/zone.rs @@ -17,7 +17,7 @@ use crate::{ #[enum_dispatch] pub trait MakePolygon { - fn polygon(&self, drawing: &Drawing) -> Polygon; + fn polygon(&self, drawing: &Drawing) -> Polygon; } #[enum_dispatch(GetNodeIndex, MakePolygon)] @@ -55,12 +55,12 @@ impl<'a> GetMaybeNet for SolidZoneWeight { pub type SolidZoneIndex = GenericIndex; impl MakePolygon for SolidZoneIndex { - fn polygon(&self, drawing: &Drawing) -> Polygon { + fn polygon(&self, drawing: &Drawing) -> Polygon { Polygon::new( LineString::from( drawing .geometry() - .grouping_members(GenericIndex::::new(self.node_index())) + .grouping_members(GenericIndex::new(self.node_index())) .filter_map(|primitive_node| { if let Ok(dot) = DotIndex::try_from(primitive_node) { Some(drawing.geometry().dot_weight(dot).pos()) @@ -96,12 +96,12 @@ impl<'a> GetMaybeNet for PourZoneWeight { pub type PourZoneIndex = GenericIndex; impl MakePolygon for PourZoneIndex { - fn polygon(&self, drawing: &Drawing) -> Polygon { + fn polygon(&self, drawing: &Drawing) -> Polygon { Polygon::new( LineString::from( drawing .geometry() - .grouping_members(GenericIndex::::new(self.node_index())) + .grouping_members(GenericIndex::new(self.node_index())) .filter_map(|primitive_node| { if let Ok(dot) = DotIndex::try_from(primitive_node) { Some(drawing.geometry().dot_weight(dot).pos()) diff --git a/src/mesh.rs b/src/mesh.rs index c864c3e..5487ef8 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -83,7 +83,7 @@ pub struct Mesh { } impl Mesh { - pub fn new(layout: &Drawing) -> Self { + pub fn new(layout: &Drawing) -> Self { let mut this = Self { triangulation: Triangulation::new(layout), vertex_to_triangulation_vertex: Vec::new(), @@ -93,7 +93,10 @@ impl Mesh { this } - pub fn generate(&mut self, drawing: &Drawing) -> Result<(), InsertionError> { + pub fn generate( + &mut self, + drawing: &Drawing, + ) -> Result<(), InsertionError> { for node in drawing.primitive_nodes() { let center = node.primitive(drawing).shape().center(); diff --git a/src/triangulation.rs b/src/triangulation.rs index 8586537..a19f2ad 100644 --- a/src/triangulation.rs +++ b/src/triangulation.rs @@ -23,14 +23,14 @@ pub struct Triangulation + HasPosition> Triangulation { - pub fn new(layout: &Drawing) -> Self { + pub fn new(drawing: &Drawing) -> Self { let mut this = Self { triangulation: as spade::Triangulation>::new(), vertex_to_handle: Vec::new(), index_marker: PhantomData, }; this.vertex_to_handle - .resize(layout.geometry().graph().node_bound(), None); + .resize(drawing.geometry().graph().node_bound(), None); this } diff --git a/src/wraparoundable.rs b/src/wraparoundable.rs index 3cebd7f..bde3a75 100644 --- a/src/wraparoundable.rs +++ b/src/wraparoundable.rs @@ -45,15 +45,15 @@ impl From for WraparoundableIndex { } } -#[enum_dispatch(GetWraparound, GetLayout, GetNodeIndex)] -pub enum Wraparoundable<'a, R: RulesTrait> { - FixedDot(FixedDot<'a, R>), - FixedBend(FixedBend<'a, R>), - LooseBend(LooseBend<'a, R>), +#[enum_dispatch(GetWraparound, GetDrawing, GetNodeIndex)] +pub enum Wraparoundable<'a, GW: Copy, R: RulesTrait> { + FixedDot(FixedDot<'a, GW, R>), + FixedBend(FixedBend<'a, GW, R>), + LooseBend(LooseBend<'a, GW, R>), } -impl<'a, R: RulesTrait> Wraparoundable<'a, R> { - pub fn new(index: WraparoundableIndex, drawing: &'a Drawing) -> Self { +impl<'a, GW: Copy, R: RulesTrait> Wraparoundable<'a, GW, R> { + pub fn new(index: WraparoundableIndex, drawing: &'a Drawing) -> Self { match index { WraparoundableIndex::FixedDot(dot) => drawing.primitive(dot).into(), WraparoundableIndex::FixedBend(bend) => drawing.primitive(bend).into(), @@ -62,19 +62,19 @@ impl<'a, R: RulesTrait> Wraparoundable<'a, R> { } } -impl<'a, R: RulesTrait> GetWraparound for FixedDot<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetWraparound for FixedDot<'a, GW, R> { fn wraparound(&self) -> Option { self.first_rail() } } -impl<'a, R: RulesTrait> GetWraparound for LooseBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetWraparound for LooseBend<'a, GW, R> { fn wraparound(&self) -> Option { self.outer() } } -impl<'a, R: RulesTrait> GetWraparound for FixedBend<'a, R> { +impl<'a, GW: Copy, R: RulesTrait> GetWraparound for FixedBend<'a, GW, R> { fn wraparound(&self) -> Option { self.first_rail() }