mirror of https://codeberg.org/topola/topola.git
Split `Segment` into full `Segment` and input `SegmentSpec`
This commit is contained in:
parent
36004b155b
commit
67f3426586
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
use crate::{viewport::Viewport, workspace::Workspace};
|
use crate::{viewport::Viewport, workspace::Workspace};
|
||||||
use topola::{Joint, Polygon, Segment, Vector2};
|
use topola::{Joint, Polygon, Segment};
|
||||||
|
|
||||||
pub struct Display {}
|
pub struct Display {}
|
||||||
|
|
||||||
|
|
@ -65,7 +65,6 @@ impl Display {
|
||||||
ui,
|
ui,
|
||||||
viewport,
|
viewport,
|
||||||
segment,
|
segment,
|
||||||
layout.segment_endpoints(segment_id),
|
|
||||||
workspace.appearance_panel.layer_color(
|
workspace.appearance_panel.layer_color(
|
||||||
ctx,
|
ctx,
|
||||||
board.layer_name(segment.layer),
|
board.layer_name(segment.layer),
|
||||||
|
|
@ -126,15 +125,14 @@ impl Display {
|
||||||
ui: &egui::Ui,
|
ui: &egui::Ui,
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
segment: &Segment,
|
segment: &Segment,
|
||||||
endpoints: [Vector2<i64>; 2],
|
|
||||||
color: egui::Color32,
|
color: egui::Color32,
|
||||||
) {
|
) {
|
||||||
ui.painter().line_segment(
|
ui.painter().line_segment(
|
||||||
[
|
[
|
||||||
egui::pos2(endpoints[0].x as f32, endpoints[0].y as f32),
|
egui::pos2(segment.endpoints[0].x as f32, segment.endpoints[0].y as f32),
|
||||||
egui::pos2(endpoints[1].x as f32, endpoints[1].y as f32),
|
egui::pos2(segment.endpoints[1].x as f32, segment.endpoints[1].y as f32),
|
||||||
],
|
],
|
||||||
egui::Stroke::new(segment.half_width as f32 * 2.0, color),
|
egui::Stroke::new(segment.spec.half_width as f32 * 2.0, color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,7 +192,7 @@ impl Display {
|
||||||
}
|
}
|
||||||
|
|
||||||
for segment_id in layout.layer_segments(layer) {
|
for segment_id in layout.layer_segments(layer) {
|
||||||
let endpoints = layout.segment_endpoints(segment_id);
|
let endpoints = layout.segment(segment_id).endpoints;
|
||||||
|
|
||||||
ui.painter().rect_stroke(
|
ui.painter().rect_stroke(
|
||||||
egui::Rect::from_two_pos(
|
egui::Rect::from_two_pos(
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@ use undoredo::{ApplyDelta, Delta, FlushDelta};
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::{Layout, LayoutHalfDelta, NetId, PinId},
|
layout::{Layout, LayoutHalfDelta, NetId, PinId},
|
||||||
math::Vector2,
|
math::Vector2,
|
||||||
primitives::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId},
|
primitives::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId},
|
||||||
selection::PinSelection,
|
selection::{PinSelection, PinSelector},
|
||||||
selection::PinSelector,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Getters)]
|
#[derive(Clone, Debug, Getters)]
|
||||||
|
|
@ -64,8 +63,12 @@ impl Board {
|
||||||
self.layout.add_joint(joint)
|
self.layout.add_joint(joint)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_segment(&mut self, segment: Segment) -> SegmentId {
|
pub fn add_segment(&mut self, spec: SegmentSpec) -> SegmentId {
|
||||||
self.layout.add_segment(segment)
|
self.layout.add_segment(spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_segment_raw(&mut self, segment: Segment) -> SegmentId {
|
||||||
|
self.layout.add_segment_raw(segment)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_via(&mut self, via: Via) -> ViaId {
|
pub fn add_via(&mut self, via: Via) -> ViaId {
|
||||||
|
|
@ -89,7 +92,7 @@ impl Board {
|
||||||
let segment = self.layout.segment(segment_id);
|
let segment = self.layout.segment(segment_id);
|
||||||
|
|
||||||
Some(PinSelector {
|
Some(PinSelector {
|
||||||
pin: self.pin_name(segment.pin?)?.to_string(),
|
pin: self.pin_name(segment.spec.pin?)?.to_string(),
|
||||||
layer: self.layer_name(segment.layer)?.to_string(),
|
layer: self.layer_name(segment.layer)?.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ use serde::{Deserialize, Serialize};
|
||||||
use stable_vec::StableVec;
|
use stable_vec::StableVec;
|
||||||
use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
|
use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
|
||||||
|
|
||||||
use crate::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2, Via, ViaId};
|
use crate::{
|
||||||
|
Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2, Via, ViaId,
|
||||||
|
primitives::SegmentSpec,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
|
|
@ -24,7 +27,7 @@ pub struct PinId(usize);
|
||||||
impl PinId {
|
impl PinId {
|
||||||
/// Returns the underlying index.
|
/// Returns the underlying index.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id(self) -> usize {
|
pub fn index(self) -> usize {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +59,7 @@ pub struct NetId(usize);
|
||||||
impl NetId {
|
impl NetId {
|
||||||
/// Returns the underlying index.
|
/// Returns the underlying index.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id(self) -> usize {
|
pub fn index(self) -> usize {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,22 +117,34 @@ impl Layout {
|
||||||
.insert(GeomWithData::new(bbox, joint_id), ());
|
.insert(GeomWithData::new(bbox, joint_id), ());
|
||||||
|
|
||||||
if let Some(pin_id) = pin_id {
|
if let Some(pin_id) = pin_id {
|
||||||
self.pins[pin_id.id()].joints.push(joint_id);
|
self.pins[pin_id.index()].joints.push(joint_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
joint_id
|
joint_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_segment(&mut self, segment: Segment) -> SegmentId {
|
pub fn add_segment(&mut self, segment: SegmentSpec) -> SegmentId {
|
||||||
let pin_id = segment.pin;
|
self.add_segment_raw(Segment {
|
||||||
|
spec: segment,
|
||||||
|
endpoints: [
|
||||||
|
self.joint(segment.endjoints[0]).position,
|
||||||
|
self.joint(segment.endjoints[1]).position,
|
||||||
|
],
|
||||||
|
layer: self.joint(segment.endjoints[0]).layer,
|
||||||
|
net: self.joint(segment.endjoints[0]).net,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_segment_raw(&mut self, segment: Segment) -> SegmentId {
|
||||||
|
let pin_id = segment.spec.pin;
|
||||||
|
let bbox = segment.rtree_bbox();
|
||||||
let segment_id = SegmentId::new(self.segments.push(segment));
|
let segment_id = SegmentId::new(self.segments.push(segment));
|
||||||
let bbox = self.segment_bbox(segment_id);
|
|
||||||
|
|
||||||
self.segments_rtree
|
self.segments_rtree
|
||||||
.insert(GeomWithData::new(bbox, segment_id), ());
|
.insert(GeomWithData::new(bbox, segment_id), ());
|
||||||
|
|
||||||
if let Some(pin_id) = pin_id {
|
if let Some(pin_id) = pin_id {
|
||||||
self.pins[pin_id.id()].segments.push(segment_id);
|
self.pins[pin_id.index()].segments.push(segment_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
segment_id
|
segment_id
|
||||||
|
|
@ -143,7 +158,7 @@ impl Layout {
|
||||||
//self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ());
|
//self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ());
|
||||||
|
|
||||||
if let Some(pin_id) = pin_id {
|
if let Some(pin_id) = pin_id {
|
||||||
self.pins[pin_id.id()].vias.push(via_id);
|
self.pins[pin_id.index()].vias.push(via_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
via_id
|
via_id
|
||||||
|
|
@ -158,52 +173,12 @@ impl Layout {
|
||||||
.insert(GeomWithData::new(bbox, polygon_id), ());
|
.insert(GeomWithData::new(bbox, polygon_id), ());
|
||||||
|
|
||||||
if let Some(pin_id) = pin_id {
|
if let Some(pin_id) = pin_id {
|
||||||
self.pins[pin_id.id()].polygons.push(polygon_id);
|
self.pins[pin_id.index()].polygons.push(polygon_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
polygon_id
|
polygon_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn segment_center(&self, segment_id: SegmentId) -> Vector2<i64> {
|
|
||||||
let endpoints = self.segment_endpoints(segment_id);
|
|
||||||
|
|
||||||
(endpoints[0] + endpoints[1]) / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn segment_endpoints(&self, segment_id: SegmentId) -> [Vector2<i64>; 2] {
|
|
||||||
let endjoints = self.segments.get(&segment_id.index()).unwrap().endjoints;
|
|
||||||
[
|
|
||||||
self.joints.get(&endjoints[0].index()).unwrap().position,
|
|
||||||
self.joints.get(&endjoints[1].index()).unwrap().position,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn segment_contains_point(&self, segment_id: SegmentId, point: Vector2<i64>) -> bool {
|
|
||||||
let endpoints = self.segment_endpoints(segment_id);
|
|
||||||
let segment = self.segments.get(&segment_id.index()).unwrap();
|
|
||||||
let vertices = crate::math::inflated_segment(
|
|
||||||
endpoints[0].x,
|
|
||||||
endpoints[0].y,
|
|
||||||
endpoints[1].x,
|
|
||||||
endpoints[1].y,
|
|
||||||
segment.half_width,
|
|
||||||
);
|
|
||||||
point.inside_polygon(&vertices)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn segment_bbox(&self, segment_id: SegmentId) -> Rectangle<[i64; 3]> {
|
|
||||||
let endpoints = self.segment_endpoints(segment_id);
|
|
||||||
let layer = self.segments.get(&segment_id.index()).unwrap().layer as i64;
|
|
||||||
let half_width = self.segments.get(&segment_id.index()).unwrap().half_width as i64;
|
|
||||||
|
|
||||||
let min_x = std::cmp::min(endpoints[0].x, endpoints[1].x) - half_width;
|
|
||||||
let min_y = std::cmp::min(endpoints[0].y, endpoints[1].y) - half_width;
|
|
||||||
let max_x = std::cmp::max(endpoints[0].x, endpoints[1].x) + half_width;
|
|
||||||
let max_y = std::cmp::max(endpoints[0].y, endpoints[1].y) + half_width;
|
|
||||||
|
|
||||||
Rectangle::from_corners([min_x, min_y, layer], [max_x, max_y, layer])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn locate_joints_at_point(
|
pub fn locate_joints_at_point(
|
||||||
&self,
|
&self,
|
||||||
layer: usize,
|
layer: usize,
|
||||||
|
|
@ -230,7 +205,7 @@ impl Layout {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.locate_all_at_point(&[point.x, point.y, layer as i64])
|
.locate_all_at_point(&[point.x, point.y, layer as i64])
|
||||||
.map(|geom_with_data| geom_with_data.data)
|
.map(|geom_with_data| geom_with_data.data)
|
||||||
.filter(move |segment_id| self.segment_contains_point(*segment_id, point))
|
.filter(move |&segment_id| self.segment(segment_id).contains_point(point))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: vias.
|
// TODO: vias.
|
||||||
|
|
@ -299,7 +274,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pin(&self, pin_id: PinId) -> &Pin {
|
pub fn pin(&self, pin_id: PinId) -> &Pin {
|
||||||
&self.pins[pin_id.id()]
|
&self.pins[pin_id.index()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,8 @@ impl_inside_polygon!(f64);
|
||||||
impl_inside_polygon!(i32);
|
impl_inside_polygon!(i32);
|
||||||
impl_inside_polygon!(i64);
|
impl_inside_polygon!(i64);
|
||||||
|
|
||||||
/// Returns the four vertices of a segment inflated by `half_width`, forming a convex
|
/// Returns the four vertices of a segment inflated by `half_width`, forming a
|
||||||
/// quadrilateral. The segment goes from (x1, y1) to (x2, y2).
|
/// convex quadrilateral. The segment goes from (x1, y1) to (x2, y2).
|
||||||
pub fn inflated_segment(x1: i64, y1: i64, x2: i64, y2: i64, half_width: u64) -> [Vector2<i64>; 4] {
|
pub fn inflated_segment(x1: i64, y1: i64, x2: i64, y2: i64, half_width: u64) -> [Vector2<i64>; 4] {
|
||||||
let dx = x2 - x1;
|
let dx = x2 - x1;
|
||||||
let dy = y2 - y1;
|
let dy = y2 - y1;
|
||||||
|
|
|
||||||
|
|
@ -210,10 +210,8 @@ impl NavmesherBoard {
|
||||||
for (i, segment) in this.board.layout().segments().collection() {
|
for (i, segment) in this.board.layout().segments().collection() {
|
||||||
this.segment_multiobstacles.insert(
|
this.segment_multiobstacles.insert(
|
||||||
i,
|
i,
|
||||||
this.navmesher.insert_multiobstacle(
|
this.navmesher
|
||||||
segment.layer,
|
.insert_multiobstacle(segment.layer, segment.bbox()),
|
||||||
this.segment_bounding_rectangle(SegmentId::new(i), *segment),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -256,34 +254,18 @@ impl NavmesherBoard {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_segment(&mut self, segment: Segment) -> SegmentId {
|
pub fn insert_segment_with_cache(&mut self, segment: Segment) -> SegmentId {
|
||||||
let segment_id = self.board.add_segment(segment);
|
let layer = segment.layer;
|
||||||
|
let obstacle = segment.bbox();
|
||||||
|
let segment_id = self.board.add_segment_raw(segment);
|
||||||
self.segment_multiobstacles.insert(
|
self.segment_multiobstacles.insert(
|
||||||
segment_id.index(),
|
segment_id.index(),
|
||||||
self.navmesher.insert_multiobstacle(
|
self.navmesher.insert_multiobstacle(layer, obstacle),
|
||||||
segment.layer,
|
|
||||||
self.segment_bounding_rectangle(segment_id, segment),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
segment_id
|
segment_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn segment_bounding_rectangle(
|
|
||||||
&self,
|
|
||||||
segment_id: SegmentId,
|
|
||||||
segment: Segment,
|
|
||||||
) -> [Vector2<i64>; 4] {
|
|
||||||
let endpoints = self.board.layout().segment_endpoints(segment_id);
|
|
||||||
crate::math::inflated_segment(
|
|
||||||
endpoints[0].x,
|
|
||||||
endpoints[0].y,
|
|
||||||
endpoints[1].x,
|
|
||||||
endpoints[1].y,
|
|
||||||
segment.half_width,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId {
|
pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId {
|
||||||
let polygon_id = self.board.add_polygon(polygon.clone());
|
let polygon_id = self.board.add_polygon(polygon.clone());
|
||||||
self.polygon_multiobstacles.insert(
|
self.polygon_multiobstacles.insert(
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,60 @@ impl SegmentId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Segment {
|
pub struct SegmentSpec {
|
||||||
pub endjoints: [JointId; 2],
|
pub endjoints: [JointId; 2],
|
||||||
pub layer: usize,
|
|
||||||
pub half_width: u64,
|
pub half_width: u64,
|
||||||
pub net: NetId,
|
|
||||||
pub pin: Option<PinId>,
|
pub pin: Option<PinId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Segment {
|
||||||
|
pub spec: SegmentSpec,
|
||||||
|
pub endpoints: [Vector2<i64>; 2],
|
||||||
|
pub layer: usize,
|
||||||
|
pub net: NetId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Segment {
|
||||||
|
pub fn center(&self) -> Vector2<i64> {
|
||||||
|
(self.endpoints[0] + self.endpoints[1]) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains_point(&self, point: Vector2<i64>) -> bool {
|
||||||
|
let vertices = crate::math::inflated_segment(
|
||||||
|
self.endpoints[0].x,
|
||||||
|
self.endpoints[0].y,
|
||||||
|
self.endpoints[1].x,
|
||||||
|
self.endpoints[1].y,
|
||||||
|
self.spec.half_width,
|
||||||
|
);
|
||||||
|
point.inside_polygon(&vertices)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bbox(&self) -> [Vector2<i64>; 4] {
|
||||||
|
crate::math::inflated_segment(
|
||||||
|
self.endpoints[0].x,
|
||||||
|
self.endpoints[0].y,
|
||||||
|
self.endpoints[1].x,
|
||||||
|
self.endpoints[1].y,
|
||||||
|
self.spec.half_width,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rtree_bbox(&self) -> Rectangle<[i64; 3]> {
|
||||||
|
let endpoints = self.endpoints;
|
||||||
|
let layer = self.layer as i64;
|
||||||
|
let half_width = self.spec.half_width as i64;
|
||||||
|
|
||||||
|
let min_x = std::cmp::min(endpoints[0].x, endpoints[1].x) - half_width;
|
||||||
|
let min_y = std::cmp::min(endpoints[0].y, endpoints[1].y) - half_width;
|
||||||
|
let max_x = std::cmp::max(endpoints[0].x, endpoints[1].x) + half_width;
|
||||||
|
let max_y = std::cmp::max(endpoints[0].y, endpoints[1].y) + half_width;
|
||||||
|
|
||||||
|
Rectangle::from_corners([min_x, min_y, layer], [max_x, max_y, layer])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
||||||
)]
|
)]
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ impl Ratsnest {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, segment) in board.layout().segments().collection() {
|
for (i, segment) in board.layout().segments().collection() {
|
||||||
let segment_center = board.layout().segment_center(SegmentId::new(i));
|
let segment_center = segment.center();
|
||||||
let _ = triangulations
|
let _ = triangulations
|
||||||
.entry((segment.net, segment.layer))
|
.entry((segment.net, segment.layer))
|
||||||
.or_insert_with(DelaunayTriangulation::new)
|
.or_insert_with(DelaunayTriangulation::new)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
Segment, Vector2,
|
Segment, Vector2,
|
||||||
board::Board,
|
board::Board,
|
||||||
layout::{NetId, PinId},
|
layout::{NetId, PinId},
|
||||||
primitives::{Joint, Polygon},
|
primitives::{Joint, Polygon, SegmentSpec},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
|
|
@ -351,12 +351,15 @@ impl Board {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a seg between the current and previous coords.
|
// Add a seg between the current and previous coords.
|
||||||
let _ = board.add_segment(Segment {
|
let _ = board.add_segment_raw(Segment {
|
||||||
endjoints: [prev_joint, joint],
|
spec: SegmentSpec {
|
||||||
|
endjoints: [prev_joint, joint],
|
||||||
|
half_width: (width / 2.0) as u64,
|
||||||
|
pin,
|
||||||
|
},
|
||||||
|
endpoints: [prev_pos, pos],
|
||||||
layer,
|
layer,
|
||||||
half_width: (width / 2.0) as u64,
|
|
||||||
net,
|
net,
|
||||||
pin,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
prev_pos = pos;
|
prev_pos = pos;
|
||||||
|
|
@ -369,7 +372,7 @@ impl Board {
|
||||||
place: PointWithRotation,
|
place: PointWithRotation,
|
||||||
pin_pos: PointWithRotation,
|
pin_pos: PointWithRotation,
|
||||||
coords: &[Point],
|
coords: &[Point],
|
||||||
width: f64,
|
_width: f64,
|
||||||
layer: usize,
|
layer: usize,
|
||||||
net: NetId,
|
net: NetId,
|
||||||
pin: Option<PinId>,
|
pin: Option<PinId>,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue