mirror of https://codeberg.org/topola/topola.git
Compare commits
5 Commits
4afd0d7e3d
...
68eafc1059
| Author | SHA1 | Date |
|---|---|---|
|
|
68eafc1059 | |
|
|
95694ac931 | |
|
|
7b5bffada8 | |
|
|
ce5634ee6a | |
|
|
965080b8db |
|
|
@ -5,9 +5,9 @@
|
|||
use crate::{viewport::Viewport, workspace::Workspace};
|
||||
use topola::{Joint, Polygon, Segment, SegmentId};
|
||||
|
||||
pub struct Displayer {}
|
||||
pub struct Display {}
|
||||
|
||||
impl Displayer {
|
||||
impl Display {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ impl Displayer {
|
|||
workspace: &Workspace,
|
||||
) {
|
||||
self.display_layout(ctx, ui, /*menu_bar,*/ viewport, workspace);
|
||||
self.display_bboxes(ctx, ui, viewport, workspace);
|
||||
self.display_navmeshes(ctx, ui, viewport, workspace);
|
||||
}
|
||||
|
||||
|
|
@ -176,6 +177,90 @@ impl Displayer {
|
|||
));
|
||||
}
|
||||
|
||||
fn display_bboxes(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &egui::Ui,
|
||||
viewport: &Viewport,
|
||||
workspace: &Workspace,
|
||||
) {
|
||||
for (_, joint) in workspace
|
||||
.navmesher_board
|
||||
.board()
|
||||
.layout()
|
||||
.joints()
|
||||
.collection()
|
||||
{
|
||||
if workspace.appearance_panel.visible[joint.layer] {
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(
|
||||
joint.bbox().lower()[0] as f32,
|
||||
joint.bbox().lower()[1] as f32,
|
||||
),
|
||||
max: egui::pos2(
|
||||
joint.bbox().upper()[0] as f32,
|
||||
joint.bbox().upper()[1] as f32,
|
||||
),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (i, segment) in workspace
|
||||
.navmesher_board
|
||||
.board()
|
||||
.layout()
|
||||
.segments()
|
||||
.collection()
|
||||
{
|
||||
if workspace.appearance_panel.visible[segment.layer] {
|
||||
let endpoints = workspace
|
||||
.navmesher_board
|
||||
.board()
|
||||
.layout()
|
||||
.segment_endpoints(SegmentId::new(i));
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect::from_two_pos(
|
||||
egui::pos2(endpoints[0][0] as f32, endpoints[0][1] as f32),
|
||||
egui::pos2(endpoints[1][0] as f32, endpoints[1][1] as f32),
|
||||
),
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: vias.
|
||||
|
||||
for (i, polygon) in workspace
|
||||
.navmesher_board
|
||||
.board()
|
||||
.layout()
|
||||
.polygons()
|
||||
.collection()
|
||||
{
|
||||
if workspace.appearance_panel.visible[polygon.layer] {
|
||||
let bbox = polygon.bbox();
|
||||
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
min: egui::pos2(bbox.lower()[0] as f32, bbox.lower()[1] as f32),
|
||||
max: egui::pos2(bbox.upper()[0] as f32, bbox.upper()[1] as f32),
|
||||
},
|
||||
egui::CornerRadius::ZERO,
|
||||
egui::Stroke::new(5.0, egui::Color32::GRAY),
|
||||
egui::StrokeKind::Middle,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn display_navmeshes(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
|
|
@ -8,7 +8,7 @@ mod action;
|
|||
mod actions;
|
||||
mod app;
|
||||
mod appearance_panel;
|
||||
mod displayer;
|
||||
mod display;
|
||||
mod menu_bar;
|
||||
mod translator;
|
||||
mod viewport;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use egui::Pos2;
|
||||
|
||||
use crate::{displayer::Displayer, workspace::Workspace};
|
||||
use crate::{display::Display, workspace::Workspace};
|
||||
|
||||
pub struct Viewport {
|
||||
pub scene_rect: egui::Rect,
|
||||
|
|
@ -29,8 +29,8 @@ impl Viewport {
|
|||
.zoom_range(0.00001..=10000.0)
|
||||
.show(ui, &mut scene_rect, |ui| {
|
||||
if let Some(ref workspace) = workspace {
|
||||
let mut displayer = Displayer::new();
|
||||
displayer.update(ctx, ui, &self, workspace);
|
||||
let mut display = Display::new();
|
||||
display.update(ctx, ui, &self, workspace);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ bimap = "0.6"
|
|||
dearcut = { version = "0.1", features = ["undoredo"] }
|
||||
derive-getters.workspace = true
|
||||
derive_more.workspace = true
|
||||
rstar = "0.12"
|
||||
serde.workspace = true
|
||||
specctra = { path = "../specctra" }
|
||||
stable-vec = "0.4"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ use std::collections::BTreeMap;
|
|||
|
||||
use derive_getters::{Dissolve, Getters};
|
||||
use derive_more::Constructor;
|
||||
use rstar::{
|
||||
RTree,
|
||||
primitives::{GeomWithData, Rectangle},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stable_vec::StableVec;
|
||||
use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
|
||||
|
|
@ -64,10 +68,16 @@ pub struct Layout {
|
|||
layer_count: usize,
|
||||
|
||||
pins: StableVec<Pin>,
|
||||
|
||||
joints: Recorder<StableVec<Joint>>,
|
||||
segments: Recorder<StableVec<Segment>>,
|
||||
vias: Recorder<StableVec<Via>>,
|
||||
polygons: Recorder<StableVec<Polygon>>,
|
||||
|
||||
joints_rtree: Recorder<RTree<GeomWithData<Rectangle<[i64; 3]>, JointId>>>,
|
||||
segments_rtree: Recorder<RTree<GeomWithData<Rectangle<[i64; 3]>, SegmentId>>>,
|
||||
vias_rtree: Recorder<RTree<GeomWithData<Rectangle<[i64; 3]>, ViaId>>>,
|
||||
polygons_rtree: Recorder<RTree<GeomWithData<Rectangle<[i64; 3]>, PolygonId>>>,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
|
|
@ -78,10 +88,16 @@ impl Layout {
|
|||
layer_count,
|
||||
|
||||
pins: StableVec::new(),
|
||||
|
||||
joints: Recorder::new(StableVec::new()),
|
||||
segments: Recorder::new(StableVec::new()),
|
||||
vias: Recorder::new(StableVec::new()),
|
||||
polygons: Recorder::new(StableVec::new()),
|
||||
|
||||
joints_rtree: Recorder::new(RTree::new()),
|
||||
segments_rtree: Recorder::new(RTree::new()),
|
||||
vias_rtree: Recorder::new(RTree::new()),
|
||||
polygons_rtree: Recorder::new(RTree::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,9 +106,13 @@ impl Layout {
|
|||
}
|
||||
|
||||
pub fn add_joint(&mut self, joint: Joint) -> JointId {
|
||||
let bbox = joint.bbox();
|
||||
let pin_id = joint.pin;
|
||||
let joint_id = JointId::new(self.joints.push(joint));
|
||||
|
||||
self.joints_rtree
|
||||
.insert(GeomWithData::new(bbox, joint_id), ());
|
||||
|
||||
if let Some(pin_id) = pin_id {
|
||||
self.pins[pin_id.id()].joints.push(joint_id);
|
||||
}
|
||||
|
|
@ -103,6 +123,10 @@ impl Layout {
|
|||
pub fn add_segment(&mut self, segment: Segment) -> SegmentId {
|
||||
let pin_id = segment.pin;
|
||||
let segment_id = SegmentId::new(self.segments.push(segment));
|
||||
let bbox = self.segment_bbox(segment_id);
|
||||
|
||||
self.segments_rtree
|
||||
.insert(GeomWithData::new(bbox, segment_id), ());
|
||||
|
||||
if let Some(pin_id) = pin_id {
|
||||
self.pins[pin_id.id()].segments.push(segment_id);
|
||||
|
|
@ -112,9 +136,12 @@ impl Layout {
|
|||
}
|
||||
|
||||
pub fn add_via(&mut self, via: Via) -> ViaId {
|
||||
//let bbox = via.bbox();
|
||||
let pin_id = via.pin;
|
||||
let via_id = ViaId::new(self.vias.push(via));
|
||||
|
||||
//self.vias_rtree.insert(GeomWithData::new(bbox, via_id), ());
|
||||
|
||||
if let Some(pin_id) = pin_id {
|
||||
self.pins[pin_id.id()].vias.push(via_id);
|
||||
}
|
||||
|
|
@ -123,9 +150,13 @@ impl Layout {
|
|||
}
|
||||
|
||||
pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
|
||||
let bbox = polygon.bbox();
|
||||
let pin_id = polygon.pin;
|
||||
let polygon_id = PolygonId::new(self.polygons.push(polygon));
|
||||
|
||||
self.polygons_rtree
|
||||
.insert(GeomWithData::new(bbox, polygon_id), ());
|
||||
|
||||
if let Some(pin_id) = pin_id {
|
||||
self.pins[pin_id.id()].polygons.push(polygon_id);
|
||||
}
|
||||
|
|
@ -133,14 +164,62 @@ impl Layout {
|
|||
polygon_id
|
||||
}
|
||||
|
||||
pub fn segment_endpoints(&self, segment: SegmentId) -> [[i64; 2]; 2] {
|
||||
let endjoints = self.segments.get(&segment.id()).unwrap().endjoints;
|
||||
pub fn segment_endpoints(&self, segment_id: SegmentId) -> [[i64; 2]; 2] {
|
||||
let endjoints = self.segments.get(&segment_id.id()).unwrap().endjoints;
|
||||
[
|
||||
self.joints.get(&endjoints[0].id()).unwrap().position,
|
||||
self.joints.get(&endjoints[1].id()).unwrap().position,
|
||||
]
|
||||
}
|
||||
|
||||
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.id()).unwrap().layer as i64;
|
||||
let half_width = self.segments.get(&segment_id.id()).unwrap().half_width as i64;
|
||||
|
||||
let min_x = std::cmp::min(endpoints[0][0], endpoints[1][0]) - half_width;
|
||||
let min_y = std::cmp::min(endpoints[0][1], endpoints[1][1]) - half_width;
|
||||
let max_x = std::cmp::max(endpoints[0][0], endpoints[1][0]) + half_width;
|
||||
let max_y = std::cmp::max(endpoints[0][1], endpoints[1][1]) + half_width;
|
||||
|
||||
Rectangle::from_corners([min_x, min_y, layer], [max_x, max_y, layer])
|
||||
}
|
||||
|
||||
pub fn locate_joints_at_point(
|
||||
&self,
|
||||
layer: usize,
|
||||
point: [i64; 2],
|
||||
) -> impl Iterator<Item = JointId> {
|
||||
self.joints_rtree
|
||||
.as_ref()
|
||||
.locate_all_at_point(&[point[0], point[1], layer as i64])
|
||||
.map(|geom_with_data| geom_with_data.data)
|
||||
}
|
||||
|
||||
pub fn locate_segments_at_point(
|
||||
&self,
|
||||
layer: usize,
|
||||
point: [i64; 2],
|
||||
) -> impl Iterator<Item = SegmentId> {
|
||||
self.segments_rtree
|
||||
.as_ref()
|
||||
.locate_all_at_point(&[point[0], point[1], layer as i64])
|
||||
.map(|geom_with_data| geom_with_data.data)
|
||||
}
|
||||
|
||||
// TODO: vias.
|
||||
|
||||
pub fn locate_polygons_at_point(
|
||||
&self,
|
||||
layer: usize,
|
||||
point: [i64; 2],
|
||||
) -> impl Iterator<Item = PolygonId> {
|
||||
self.polygons_rtree
|
||||
.as_ref()
|
||||
.locate_all_at_point(&[point[0], point[1], layer as i64])
|
||||
.map(|geom_with_data| geom_with_data.data)
|
||||
}
|
||||
|
||||
pub fn pin(&self, pin: PinId) -> &Pin {
|
||||
&self.pins[pin.id()]
|
||||
}
|
||||
|
|
@ -169,6 +248,8 @@ impl ApplyDelta<LayoutHalfDelta> for Layout {
|
|||
|
||||
let polygons_delta = Delta::with_removed_inserted(removed.polygons, inserted.polygons);
|
||||
self.polygons.apply_delta(&polygons_delta);
|
||||
|
||||
// TODO R-trees.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,6 +260,8 @@ impl FlushDelta<LayoutHalfDelta> for Layout {
|
|||
let (removed_vias, inserted_vias) = self.vias.flush_delta().dissolve();
|
||||
let (removed_polygons, inserted_polygons) = self.polygons.flush_delta().dissolve();
|
||||
|
||||
// TODO R-trees.
|
||||
|
||||
Delta::with_removed_inserted(
|
||||
LayoutHalfDelta {
|
||||
joints: removed_joints,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
use derive_more::{Constructor, From};
|
||||
use derive_more::Constructor;
|
||||
use rstar::{AABB, Envelope, primitives::Rectangle};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -10,14 +11,6 @@ use crate::{
|
|||
selection::PinSelector,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, From, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum PrimitiveId {
|
||||
Joint(JointId),
|
||||
Segment(SegmentId),
|
||||
Via(ViaId),
|
||||
Polygon(PolygonId),
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
||||
)]
|
||||
|
|
@ -41,6 +34,21 @@ pub struct Joint {
|
|||
}
|
||||
|
||||
impl Joint {
|
||||
pub fn bbox(&self) -> Rectangle<[i64; 3]> {
|
||||
Rectangle::from_aabb(AABB::from_corners(
|
||||
[
|
||||
self.position[0] - self.radius as i64,
|
||||
self.position[1] - self.radius as i64,
|
||||
self.layer as i64,
|
||||
],
|
||||
[
|
||||
self.position[0] + self.radius as i64,
|
||||
self.position[1] + self.radius as i64,
|
||||
self.layer as i64,
|
||||
],
|
||||
))
|
||||
}
|
||||
|
||||
pub fn pin_selector(&self) -> Option<PinSelector> {
|
||||
Some(PinSelector {
|
||||
pin: self.pin?,
|
||||
|
|
@ -95,7 +103,7 @@ impl ViaId {
|
|||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Via {
|
||||
pub endpoints: [JointId; 2],
|
||||
pub endjoints: [JointId; 2],
|
||||
pub layer: usize, // ??? This should be a range.
|
||||
pub radius: u64,
|
||||
pub net: NetId,
|
||||
|
|
@ -103,6 +111,10 @@ pub struct Via {
|
|||
}
|
||||
|
||||
impl Via {
|
||||
/*pub fn bbox(&self) -> Rectangle<[i64; 3]> {
|
||||
//
|
||||
}*/
|
||||
|
||||
pub fn pin_selector(&self) -> Option<PinSelector> {
|
||||
Some(PinSelector {
|
||||
pin: self.pin?,
|
||||
|
|
@ -133,6 +145,15 @@ pub struct Polygon {
|
|||
}
|
||||
|
||||
impl Polygon {
|
||||
pub fn bbox(&self) -> Rectangle<[i64; 3]> {
|
||||
Rectangle::from_aabb(self.vertices.clone().into_iter().fold(
|
||||
AABB::new_empty(),
|
||||
|aabb, vertex| {
|
||||
aabb.merged(&AABB::from_point([vertex[0], vertex[1], self.layer as i64]))
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn pin_selector(&self) -> Option<PinSelector> {
|
||||
Some(PinSelector {
|
||||
pin: self.pin?,
|
||||
|
|
|
|||
Loading…
Reference in New Issue