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.
This commit is contained in:
Mikolaj Wielgus 2024-04-11 18:07:08 +00:00
parent 5cef59227a
commit 9feb32955c
19 changed files with 405 additions and 313 deletions

View File

@ -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<String>, Receiver<String>),
#[serde(skip)]
drawing: Option<Drawing<DsnRules>>,
layout: Option<Layout<DsnRules>>,
#[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),
)
}

View File

@ -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<R>),
Layout(&'a Drawing<R>),
Layout(&'a Layout<R>),
}
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);

View File

@ -268,7 +268,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
Some(self.guide().head(prev_dot))
}
fn guide(&self) -> Guide<R> {
fn guide(&self) -> Guide<impl Copy, R> {
Guide::new(self.layout.drawing())
}
}

View File

@ -9,12 +9,12 @@ use super::{
};
#[derive(Debug)]
pub struct Collect<'a, R: RulesTrait> {
drawing: &'a Drawing<R>,
pub struct Collect<'a, GW: Copy, R: RulesTrait> {
drawing: &'a Drawing<GW, R>,
}
impl<'a, R: RulesTrait> Collect<'a, R> {
pub fn new(drawing: &'a Drawing<R>) -> Self {
impl<'a, GW: Copy, R: RulesTrait> Collect<'a, GW, R> {
pub fn new(drawing: &'a Drawing<GW, R>) -> Self {
Self { drawing }
}

View File

@ -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<R: RulesTrait> {
pub struct Drawing<GW: Copy, R: RulesTrait> {
geometry_with_rtree: GeometryWithRtree<
PrimitiveWeight,
DotWeight,
SegWeight,
BendWeight,
ZoneWeight,
GW,
PrimitiveIndex,
DotIndex,
SegIndex,
@ -85,7 +85,7 @@ pub struct Drawing<R: RulesTrait> {
rules: R,
}
impl<R: RulesTrait> Drawing<R> {
impl<GW: Copy, R: RulesTrait> Drawing<GW, R> {
pub fn new(rules: R) -> Self {
Self {
geometry_with_rtree: GeometryWithRtree::new(2),
@ -153,19 +153,7 @@ impl<R: RulesTrait> Drawing<R> {
#[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<FixedDotIndex, Infringement> {
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<FixedDotIndex, Infringement> {
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<R: RulesTrait> Drawing<R> {
fn add_dot_infringably<W: DotWeightTrait<PrimitiveWeight> + GetLayer>(
&mut self,
weight: W,
maybe_zone: Option<ZoneIndex>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
@ -182,11 +169,6 @@ impl<R: RulesTrait> Drawing<R> {
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<R: RulesTrait> Drawing<R> {
to: FixedDotIndex,
weight: FixedSegWeight,
) -> Result<FixedSegIndex, Infringement> {
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<FixedSegIndex, Infringement> {
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<R: RulesTrait> Drawing<R> {
cw: bool,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<Segbend, LayoutException> {
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<R: RulesTrait> Drawing<R> {
to: FixedDotIndex,
weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> {
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<R: RulesTrait> Drawing<R> {
to: LooseDotIndex,
weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> {
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<R: RulesTrait> Drawing<R> {
from: DotIndex,
to: DotIndex,
weight: W,
maybe_zone: Option<ZoneIndex>,
infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
@ -521,11 +488,6 @@ impl<R: RulesTrait> Drawing<R> {
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<R: RulesTrait> Drawing<R> {
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<R: RulesTrait> Drawing<R> {
})
}
pub fn zones(&self) -> impl Iterator<Item = ZoneIndex> + '_ {
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<Item = ZoneIndex> + '_ {
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<Item = PrimitiveIndex> + '_ {
self.geometry()
.grouping_members(GenericIndex::new(zone.node_index()))
}
pub fn node_count(&self) -> usize {
self.geometry_with_rtree.graph().node_count()
}
}
impl<R: RulesTrait> Drawing<R> {
impl<GW: Copy, R: RulesTrait> Drawing<GW, R> {
#[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<R: RulesTrait> Drawing<R> {
}
}
impl<R: RulesTrait> Drawing<R> {
impl<GW: Copy, R: RulesTrait> Drawing<GW, R> {
#[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<R: RulesTrait> Drawing<R> {
DotWeight,
SegWeight,
BendWeight,
ZoneWeight,
GW,
PrimitiveIndex,
DotIndex,
SegIndex,
@ -925,6 +831,12 @@ impl<R: RulesTrait> Drawing<R> {
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<BboxedIndex<Node<PrimitiveIndex, GenericIndex<GW>>>> {
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<R: RulesTrait> Drawing<R> {
#[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<R> {
pub fn guide(&self) -> Guide<GW, R> {
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<R> {
pub fn collect(&self) -> Collect<GW, R> {
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<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, R> {
pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, GW, R> {
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<R> {
pub fn wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable<GW, R> {
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<R> {
pub fn loose(&self, index: LooseIndex) -> Loose<GW, R> {
Loose::new(index, self)
}
}
impl<GW: Copy, R: RulesTrait> GroupingManagerTrait<GW, GenericIndex<GW>> for Drawing<GW, R> {
fn add_grouping(&mut self, weight: GW) -> GenericIndex<GW> {
self.geometry_with_rtree.add_grouping(weight)
}
fn remove_grouping(&mut self, grouping: GenericIndex<GW>) {
self.geometry_with_rtree.remove_grouping(grouping);
}
fn assign_to_grouping<W>(&mut self, primitive: GenericIndex<W>, grouping: GenericIndex<GW>) {
self.geometry_with_rtree
.assign_to_grouping(primitive, grouping);
}
}

View File

@ -32,7 +32,10 @@ pub trait GetMaybeNet {
#[enum_dispatch]
pub trait MakePrimitive {
fn primitive<'a, R: RulesTrait>(&self, drawing: &'a Drawing<R>) -> Primitive<'a, R>;
fn primitive<'a, GW: Copy, R: RulesTrait>(
&self,
drawing: &'a Drawing<GW, R>,
) -> 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<R>) -> Primitive<'a, R> {
fn primitive<'a, GW: Copy, R: RulesTrait>(
&self,
drawing: &'a Drawing<GW, R>,
) -> Primitive<'a, GW, R> {
Primitive::$weight_variant(GenericPrimitive::new(*self, drawing))
}
}

View File

@ -56,12 +56,12 @@ impl HeadTrait for SegbendHead {
}
}
pub struct Guide<'a, R: RulesTrait> {
drawing: &'a Drawing<R>,
pub struct Guide<'a, GW: Copy, R: RulesTrait> {
drawing: &'a Drawing<GW, R>,
}
impl<'a, R: RulesTrait> Guide<'a, R> {
pub fn new(drawing: &'a Drawing<R>) -> Self {
impl<'a, GW: Copy, R: RulesTrait> Guide<'a, GW, R> {
pub fn new(drawing: &'a Drawing<GW, R>) -> Self {
Self { drawing }
}

View File

@ -40,16 +40,16 @@ impl From<LooseIndex> 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<R>) -> Self {
impl<'a, GW: Copy, R: RulesTrait> Loose<'a, GW, R> {
pub fn new(index: LooseIndex, drawing: &'a Drawing<GW, R>) -> 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<LooseIndex>) -> Option<LooseIndex> {
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<LooseIndex>) -> Option<LooseIndex> {
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<LooseIndex>) -> Option<LooseIndex> {
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<LooseIndex>) -> Option<LooseIndex> {
let ends = self.joints();
let Some(prev) = maybe_prev else {

View File

@ -10,6 +10,5 @@ pub mod primitive;
pub mod rules;
pub mod seg;
pub mod segbend;
pub mod zone;
pub use drawing::*;

View File

@ -25,7 +25,7 @@ use crate::{
#[enum_dispatch]
pub trait GetDrawing<'a, R: RulesTrait> {
fn drawing(&self) -> &Drawing<R>;
fn drawing(&self) -> &Drawing<impl Copy, R>;
}
#[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<usize> {
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<W>,
drawing: &'a Drawing<R>,
drawing: &'a Drawing<GW, R>,
}
impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> {
pub fn new(index: GenericIndex<W>, drawing: &'a Drawing<R>) -> Self {
impl<'a, W, GW: Copy, R: RulesTrait> GenericPrimitive<'a, W, GW, R> {
pub fn new(index: GenericIndex<W>, drawing: &'a Drawing<GW, R>) -> Self {
Self { index, drawing }
}
@ -197,41 +199,43 @@ impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> {
}
}
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW, R> {
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW, GW, R> {
GenericPrimitive::new(index, &self.drawing)
}
}
impl<'a, W, R: RulesTrait> GetInterior<PrimitiveIndex> for GenericPrimitive<'a, W, R> {
impl<'a, W, GW: Copy, R: RulesTrait> GetInterior<PrimitiveIndex>
for GenericPrimitive<'a, W, GW, R>
{
fn interior(&self) -> Vec<PrimitiveIndex> {
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<R> {
impl<'a, W, GW: Copy, R: RulesTrait> GetDrawing<'a, R> for GenericPrimitive<'a, W, GW, R> {
fn drawing(&self) -> &Drawing<impl Copy, R> {
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<usize> {
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<W>,
GenericPrimitive<'a, W, GW, R>: GetWeight<W>,
{
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<LooseIndex> {
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<SegIndex> {
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<SeqLooseSegIndex> {
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<SegIndex> {
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<FixedDotIndex, FixedDotIndex> for FixedSeg<'a, R> {
impl<'a, GW: Copy, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> 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<FixedDotIndex, FixedDotIndex> for FixedSeg<'a,
}
}
impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedSeg<'a, R> {}
impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex>
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<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a, R> {
impl<'a, GW: Copy, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex>
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<FixedDotIndex, FixedDotIndex> for LoneLooseSeg
}
}
impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a, R> {}
impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex>
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<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R> {
impl<'a, GW: Copy, R: RulesTrait> GetJoints<DotIndex, LooseDotIndex> 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<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R
}
}
impl<'a, R: RulesTrait> GetOtherJoint<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R> {}
impl<'a, GW: Copy, R: RulesTrait> GetOtherJoint<DotIndex, LooseDotIndex>
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<FixedDotIndex, FixedDotIndex> for FixedBend<'a, R> {
impl<'a, GW: Copy, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> 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<FixedDotIndex, FixedDotIndex> for FixedBend<'a
}
}
impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> 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<FixedDotIndex, FixedDotIndex>
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<LooseBend<'a, R>> for BendIndex {
fn from(bend: LooseBend<'a, R>) -> BendIndex {
impl<'a, GW: Copy, R: RulesTrait> From<LooseBend<'a, GW, R>> 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<LooseDotIndex, LooseDotIndex> for LooseBend<'a, R> {
impl<'a, GW: Copy, R: RulesTrait> GetJoints<LooseDotIndex, LooseDotIndex> 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<LooseDotIndex, LooseDotIndex> for LooseBend<'a
}
}
impl<'a, R: RulesTrait> GetOtherJoint<LooseDotIndex, LooseDotIndex> 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<LooseDotIndex, LooseDotIndex>
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> {}

View File

@ -17,7 +17,7 @@ pub struct Segbend {
}
impl Segbend {
pub fn from_dot(dot: LooseDotIndex, drawing: &Drawing<impl RulesTrait>) -> Self {
pub fn from_dot(dot: LooseDotIndex, drawing: &Drawing<impl Copy, impl RulesTrait>) -> 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();

View File

@ -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<DsnRules> {
pub fn make_layout(&self) -> Layout<DsnRules> {
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::<String, usize>::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<DsnRules>,
layout: &Layout<DsnRules>,
layer_vec: &Vec<Layer>,
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<DsnRules>,
layout: &mut Layout<DsnRules>,
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<DsnRules>,
layout: &mut Layout<DsnRules>,
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<DsnRules>,
layout: &mut Layout<DsnRules>,
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<DsnRules>,
layout: &mut Layout<DsnRules>,
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();

View File

@ -33,7 +33,7 @@ impl RTreeObject for Bbox {
}
}
type BboxedIndex<I> = GeomWithData<Bbox, I>;
pub type BboxedIndex<I> = GeomWithData<Bbox, I>;
#[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<BboxedIndex<Node<PI, GenericIndex<GW>>>> {
&self.rtree
}

View File

@ -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<R: RulesTrait> {
drawing: Drawing<R>, // Shouldn't be public, but is for now because `Draw` needs it.
drawing: Drawing<ZoneWeight, R>, // Shouldn't be public, but is for now because `Draw` needs it.
connectivity: StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>,
}
impl<R: RulesTrait> Layout<R> {
pub fn new(drawing: Drawing<R>) -> Self {
pub fn new(drawing: Drawing<ZoneWeight, R>) -> Self {
Self {
drawing,
connectivity: StableDiGraph::default(),
@ -72,6 +83,51 @@ impl<R: RulesTrait> Layout<R> {
.insert_segbend(from, around, dot_weight, seg_weight, bend_weight, cw)
}
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> {
self.drawing.add_fixed_dot(weight)
}
pub fn add_zone_fixed_dot(
&mut self,
weight: FixedDotWeight,
zone: ZoneIndex,
) -> Result<FixedDotIndex, Infringement> {
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<FixedSegIndex, Infringement> {
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<FixedSegIndex, Infringement> {
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<R: RulesTrait> Layout<R> {
0.0
}
pub fn drawing(&self) -> &Drawing<R> {
&self.drawing
}
pub fn continent(&self, dot: FixedDotIndex) -> ContinentIndex {
// TODO.
ContinentIndex::new(0.into())
}
pub fn zones(&self) -> impl Iterator<Item = ZoneIndex> + '_ {
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<Item = ZoneIndex> + '_ {
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<Item = PrimitiveIndex> + '_ {
self.drawing
.geometry()
.grouping_members(GenericIndex::new(zone.node_index()))
}
pub fn drawing(&self) -> &Drawing<impl Copy, R> {
&self.drawing
}
}
impl<R: RulesTrait> GroupingManagerTrait<ZoneWeight, GenericIndex<ZoneWeight>> for Layout<R> {
fn add_grouping(&mut self, weight: ZoneWeight) -> GenericIndex<ZoneWeight> {
self.drawing.add_grouping(weight)
}
fn remove_grouping(&mut self, grouping: GenericIndex<ZoneWeight>) {
self.drawing.remove_grouping(grouping);
}
fn assign_to_grouping<W>(
&mut self,
primitive: GenericIndex<W>,
grouping: GenericIndex<ZoneWeight>,
) {
self.drawing.assign_to_grouping(primitive, grouping);
}
}

View File

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

View File

@ -17,7 +17,7 @@ use crate::{
#[enum_dispatch]
pub trait MakePolygon {
fn polygon<R: RulesTrait>(&self, drawing: &Drawing<R>) -> Polygon;
fn polygon<R: RulesTrait>(&self, drawing: &Drawing<impl Copy, R>) -> Polygon;
}
#[enum_dispatch(GetNodeIndex, MakePolygon)]
@ -55,12 +55,12 @@ impl<'a> GetMaybeNet for SolidZoneWeight {
pub type SolidZoneIndex = GenericIndex<SolidZoneWeight>;
impl MakePolygon for SolidZoneIndex {
fn polygon<R: RulesTrait>(&self, drawing: &Drawing<R>) -> Polygon {
fn polygon<R: RulesTrait>(&self, drawing: &Drawing<impl Copy, R>) -> Polygon {
Polygon::new(
LineString::from(
drawing
.geometry()
.grouping_members(GenericIndex::<ZoneWeight>::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<PourZoneWeight>;
impl MakePolygon for PourZoneIndex {
fn polygon<R: RulesTrait>(&self, drawing: &Drawing<R>) -> Polygon {
fn polygon<R: RulesTrait>(&self, drawing: &Drawing<impl Copy, R>) -> Polygon {
Polygon::new(
LineString::from(
drawing
.geometry()
.grouping_members(GenericIndex::<ZoneWeight>::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())

View File

@ -83,7 +83,7 @@ pub struct Mesh {
}
impl Mesh {
pub fn new(layout: &Drawing<impl RulesTrait>) -> Self {
pub fn new(layout: &Drawing<impl Copy, impl RulesTrait>) -> 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<impl RulesTrait>) -> Result<(), InsertionError> {
pub fn generate(
&mut self,
drawing: &Drawing<impl Copy, impl RulesTrait>,
) -> Result<(), InsertionError> {
for node in drawing.primitive_nodes() {
let center = node.primitive(drawing).shape().center();

View File

@ -23,14 +23,14 @@ pub struct Triangulation<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I
impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
Triangulation<I, W>
{
pub fn new(layout: &Drawing<impl RulesTrait>) -> Self {
pub fn new(drawing: &Drawing<impl Copy, impl RulesTrait>) -> Self {
let mut this = Self {
triangulation: <DelaunayTriangulation<W> 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
}

View File

@ -45,15 +45,15 @@ impl From<BendIndex> 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<R>) -> Self {
impl<'a, GW: Copy, R: RulesTrait> Wraparoundable<'a, GW, R> {
pub fn new(index: WraparoundableIndex, drawing: &'a Drawing<GW, R>) -> 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<LooseBendIndex> {
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<LooseBendIndex> {
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<LooseBendIndex> {
self.first_rail()
}