diff --git a/topola-egui/src/display.rs b/topola-egui/src/display.rs index b217182..7dc4183 100644 --- a/topola-egui/src/display.rs +++ b/topola-egui/src/display.rs @@ -52,7 +52,7 @@ impl Display { joint, workspace.appearance_panel.layer_color( ctx, - board.layer_name(joint.layer), + board.layer_name(joint.spec.layer), board.pin_selection_contains_joint(&workspace.pin_selection, joint_id), ), ); @@ -113,8 +113,8 @@ impl Display { color: egui::Color32, ) { ui.painter().circle_filled( - egui::pos2(joint.position.x as f32, joint.position.y as f32), - joint.radius as f32, + egui::pos2(joint.spec.position.x as f32, joint.spec.position.y as f32), + joint.spec.radius as f32, color, ); } diff --git a/topola/src/board.rs b/topola/src/board.rs index 6c05fcf..d5bbfd8 100644 --- a/topola/src/board.rs +++ b/topola/src/board.rs @@ -10,7 +10,8 @@ use crate::{ layout::{Layout, LayoutHalfDelta, NetId, PinId}, math::Vector2, primitives::{ - Joint, JointId, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId, ViaSpec, + JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId, + ViaSpec, }, selection::{PinSelection, PinSelector}, }; @@ -61,8 +62,8 @@ impl Board { pin_id } - pub fn add_joint(&mut self, joint: Joint) -> JointId { - self.layout.add_joint(joint) + pub fn add_joint(&mut self, spec: JointSpec) -> JointId { + self.layout.add_joint(spec) } pub fn add_segment(&mut self, spec: SegmentSpec) -> SegmentId { @@ -89,8 +90,8 @@ impl Board { let joint = self.layout.joint(joint_id); Some(PinSelector { - pin: self.pin_name(joint.pin?)?.to_string(), - layer: self.layer_name(joint.layer)?.to_string(), + pin: self.pin_name(joint.spec.pin?)?.to_string(), + layer: self.layer_name(joint.spec.layer)?.to_string(), }) } diff --git a/topola/src/layout.rs b/topola/src/layout.rs index 09e04c0..26e9a23 100644 --- a/topola/src/layout.rs +++ b/topola/src/layout.rs @@ -15,7 +15,7 @@ use undoredo::{Delta, Recorder}; use crate::{ Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2, Via, ViaId, - primitives::{SegmentSpec, ViaSpec}, + primitives::{JointSpec, SegmentSpec, ViaSpec}, }; #[derive( @@ -123,9 +123,14 @@ impl Layout { PinId::new(self.pins.push(Pin::new())) } - pub fn add_joint(&mut self, joint: Joint) -> JointId { + pub fn add_joint(&mut self, spec: JointSpec) -> JointId { + let joint = Joint { + spec, + segments: Vec::new(), + vias: Vec::new(), + }; let bbox = joint.bbox(); - let pin_id = joint.pin; + let pin_id = joint.spec.pin; let joint_id = JointId::new(self.joints.push(joint)); self.joints_rtree @@ -142,11 +147,11 @@ impl Layout { self.add_segment_raw(Segment { spec, endpoints: [ - self.joint(spec.endjoints[0]).position, - self.joint(spec.endjoints[1]).position, + self.joint(spec.endjoints[0]).spec.position, + self.joint(spec.endjoints[1]).spec.position, ], - layer: self.joint(spec.endjoints[0]).layer, - net: self.joint(spec.endjoints[0]).net, + layer: self.joint(spec.endjoints[0]).spec.layer, + net: self.joint(spec.endjoints[0]).spec.net, }) } @@ -155,6 +160,15 @@ impl Layout { let bbox = segment.bbox(); let segment_id = SegmentId::new(self.segments.push(segment)); + self.joints + .modify(segment.spec.endjoints[0].index(), |joint| { + joint.segments.push(segment_id) + }); + self.joints + .modify(segment.spec.endjoints[1].index(), |joint| { + joint.segments.push(segment_id) + }); + self.segments_rtree .insert(GeomWithData::new(bbox, segment_id), ()); @@ -171,10 +185,10 @@ impl Layout { self.add_via_raw(Via { spec, - min_layer: std::cmp::min(joint0.layer, joint1.layer), - max_layer: std::cmp::max(joint0.layer, joint1.layer), - net: joint0.net, - position: (joint0.position + joint1.position) / 2, + min_layer: std::cmp::min(joint0.spec.layer, joint1.spec.layer), + max_layer: std::cmp::max(joint0.spec.layer, joint1.spec.layer), + net: joint0.spec.net, + position: (joint0.spec.position + joint1.spec.position) / 2, }) } @@ -183,6 +197,13 @@ impl Layout { let pin_id = via.spec.pin; let via_id = ViaId::new(self.vias.push(via)); + self.joints.modify(via.spec.endjoints[0].index(), |joint| { + joint.vias.push(via_id) + }); + self.joints.modify(via.spec.endjoints[1].index(), |joint| { + joint.vias.push(via_id) + }); + self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ()); if let Some(pin_id) = pin_id { @@ -261,7 +282,7 @@ impl Layout { .as_ref() .locate_in_envelope_intersecting(&envelope) .map(|geom_with_data| geom_with_data.data) - .filter(move |&id| self.joint(id).layer == layer) + .filter(move |&id| self.joint(id).spec.layer == layer) } pub fn layer_segments(&self, layer: usize) -> impl Iterator + '_ { diff --git a/topola/src/navmesher.rs b/topola/src/navmesher.rs index e22e4e7..ee8598d 100644 --- a/topola/src/navmesher.rs +++ b/topola/src/navmesher.rs @@ -9,7 +9,9 @@ use serde::{Deserialize, Serialize}; use stable_vec::StableVec; use undoredo::Recorder; -use crate::{Board, Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2}; +use crate::{ + Board, Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2, primitives::JointSpec, +}; #[derive( Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, @@ -204,7 +206,7 @@ impl NavmesherBoard { this.joint_multiobstacles.insert( i, this.navmesher - .insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(*joint)), + .insert_multiobstacle(joint.spec.layer, Self::joint_bounding_octagon(joint)), ); } @@ -227,21 +229,26 @@ impl NavmesherBoard { this } - pub fn insert_joint(&mut self, joint: Joint) -> JointId { - let joint_id = self.board.add_joint(joint); + pub fn insert_joint(&mut self, spec: JointSpec) -> JointId { + let layer = spec.layer; + let obstacle = Self::joint_bounding_octagon(&Joint { + spec, + segments: Vec::new(), + vias: Vec::new(), + }); + let joint_id = self.board.add_joint(spec); self.joint_multiobstacles.insert( joint_id.index(), - self.navmesher - .insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(joint)), + self.navmesher.insert_multiobstacle(layer, obstacle), ); joint_id } - fn joint_bounding_octagon(joint: Joint) -> [Vector2; 8] { - let cx = joint.position.x; - let cy = joint.position.y; - let r = joint.radius as i64; + fn joint_bounding_octagon(joint: &Joint) -> [Vector2; 8] { + let cx = joint.spec.position.x; + let cy = joint.spec.position.y; + let r = joint.spec.radius as i64; [ Vector2::new(cx + r, cy + r / 2), diff --git a/topola/src/primitives/joint.rs b/topola/src/primitives/joint.rs index 1b022fb..0965dbe 100644 --- a/topola/src/primitives/joint.rs +++ b/topola/src/primitives/joint.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::layout::{NetId, PinId}; use crate::math::Vector2; +use crate::primitives::{SegmentId, ViaId}; #[derive( Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, @@ -23,7 +24,7 @@ impl JointId { } #[derive(Clone, Copy, Debug)] -pub struct Joint { +pub struct JointSpec { pub position: Vector2, pub layer: usize, pub radius: u64, @@ -31,28 +32,36 @@ pub struct Joint { pub pin: Option, } +#[derive(Clone, Debug)] +pub struct Joint { + pub spec: JointSpec, + pub segments: Vec, + pub vias: Vec, +} + impl Joint { + pub fn center(&self) -> Vector2 { + self.spec.position + } + pub fn bbox(&self) -> Rectangle<[i64; 3]> { Rectangle::from_aabb(AABB::from_corners( [ - self.position.x - self.radius as i64, - self.position.y - self.radius as i64, - self.layer as i64, + self.spec.position.x - self.spec.radius as i64, + self.spec.position.y - self.spec.radius as i64, + self.spec.layer as i64, ], [ - self.position.x + self.radius as i64, - self.position.y + self.radius as i64, - self.layer as i64, + self.spec.position.x + self.spec.radius as i64, + self.spec.position.y + self.spec.radius as i64, + self.spec.layer as i64, ], )) } - pub fn center(&self) -> Vector2 { - self.position - } - pub fn contains_point(&self, point: Vector2) -> bool { - (point.x - self.position.x).pow(2) as u64 + (point.y - self.position.y).pow(2) as u64 - <= self.radius.pow(2) + (point.x - self.spec.position.x).pow(2) as u64 + + (point.y - self.spec.position.y).pow(2) as u64 + <= self.spec.radius.pow(2) } } diff --git a/topola/src/primitives/mod.rs b/topola/src/primitives/mod.rs index 5d56de0..4e02afb 100644 --- a/topola/src/primitives/mod.rs +++ b/topola/src/primitives/mod.rs @@ -9,7 +9,7 @@ mod polygon; mod segment; mod via; -pub use joint::{Joint, JointId}; +pub use joint::{Joint, JointId, JointSpec}; pub use polygon::{Polygon, PolygonId}; pub use segment::{Segment, SegmentId, SegmentSpec}; pub use via::{Via, ViaId, ViaSpec}; diff --git a/topola/src/ratsnest.rs b/topola/src/ratsnest.rs index 9ea08b3..91ee7af 100644 --- a/topola/src/ratsnest.rs +++ b/topola/src/ratsnest.rs @@ -48,10 +48,10 @@ impl Ratsnest { for (i, joint) in board.layout().joints().container().iter() { let _ = triangulations - .entry((joint.net, joint.layer)) + .entry((joint.spec.net, joint.spec.layer)) .or_insert_with(DelaunayTriangulation::new) .insert(DelaunayVertex { - layer: joint.layer, + layer: joint.spec.layer, center: joint.center(), position: spade::Point2::new(joint.center().x as f64, joint.center().y as f64), primitive_id: PrimitiveId::Joint(JointId::new(i)), diff --git a/topola/src/specctra.rs b/topola/src/specctra.rs index 9dc32ac..59ebc86 100644 --- a/topola/src/specctra.rs +++ b/topola/src/specctra.rs @@ -14,7 +14,7 @@ use crate::{ Segment, Vector2, board::Board, layout::{NetId, PinId}, - primitives::{Joint, Polygon, SegmentSpec}, + primitives::{JointSpec, Polygon, SegmentSpec}, }; impl Board { @@ -278,7 +278,7 @@ impl Board { pin: Option, flip: bool, ) { - board.add_joint(Joint { + board.add_joint(JointSpec { position: Self::pos(place, pin_pos, 0.0, 0.0, flip), layer, net, @@ -326,7 +326,7 @@ impl Board { ) { // Add the first coordinate in the wire path as a dot and save its index. let mut prev_pos: Vector2 = Self::pos(place, pin_pos, coords[0].x, coords[0].y, flip); - let mut prev_joint = board.add_joint(Joint { + let mut prev_joint = board.add_joint(JointSpec { position: prev_pos, layer, radius: (width / 2.0) as u64, @@ -342,7 +342,7 @@ impl Board { continue; } - let joint = board.add_joint(Joint { + let joint = board.add_joint(JointSpec { position: pos, layer, radius: (width / 2.0) as u64,