mirror of https://codeberg.org/topola/topola.git
Restore `NavmesherBoard` type, put it inside `Autorouter`
This commit is contained in:
parent
657d33ac6e
commit
9ea602baa4
|
|
@ -3,10 +3,7 @@
|
|||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
use crate::{viewport::Viewport, workspace::Workspace};
|
||||
use topola::{
|
||||
Joint, JointId, PinSelection, Polygon, PolygonId, PrimitiveId, Ratline, Segment, SegmentId,
|
||||
Vector2,
|
||||
};
|
||||
use topola::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2};
|
||||
|
||||
pub struct Display {}
|
||||
|
||||
|
|
@ -40,6 +37,7 @@ impl Display {
|
|||
ui.painter().line(
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.boundary()
|
||||
|
|
@ -52,7 +50,14 @@ impl Display {
|
|||
egui::Stroke::new(5.0 / viewport.scale_factor(), egui::Color32::WHITE),
|
||||
);
|
||||
|
||||
for (joint_index, joint) in workspace.autorouter.board().layout().joints().collection() {
|
||||
for (joint_index, joint) in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.joints()
|
||||
.collection()
|
||||
{
|
||||
if workspace.appearance_panel.visible[joint.layer] {
|
||||
self.paint_joint(
|
||||
ctx,
|
||||
|
|
@ -61,11 +66,19 @@ impl Display {
|
|||
joint,
|
||||
workspace.appearance_panel.layer_color(
|
||||
ctx,
|
||||
workspace.autorouter.board().layer_name(joint.layer),
|
||||
workspace.autorouter.board().pin_selection_contains_joint(
|
||||
&workspace.pin_selection,
|
||||
JointId::new(joint_index),
|
||||
),
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layer_name(joint.layer),
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.pin_selection_contains_joint(
|
||||
&workspace.pin_selection,
|
||||
JointId::new(joint_index),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -73,6 +86,7 @@ impl Display {
|
|||
|
||||
for (segment_index, segment) in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.segments()
|
||||
|
|
@ -86,16 +100,25 @@ impl Display {
|
|||
segment,
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.segment_endpoints(SegmentId::new(segment_index)),
|
||||
workspace.appearance_panel.layer_color(
|
||||
ctx,
|
||||
workspace.autorouter.board().layer_name(segment.layer),
|
||||
workspace.autorouter.board().pin_selection_contains_segment(
|
||||
&workspace.pin_selection,
|
||||
SegmentId::new(segment_index),
|
||||
),
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layer_name(segment.layer),
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.pin_selection_contains_segment(
|
||||
&workspace.pin_selection,
|
||||
SegmentId::new(segment_index),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -105,6 +128,7 @@ impl Display {
|
|||
|
||||
for (polygon_index, polygon) in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.polygons()
|
||||
|
|
@ -118,11 +142,19 @@ impl Display {
|
|||
polygon,
|
||||
workspace.appearance_panel.layer_color(
|
||||
ctx,
|
||||
workspace.autorouter.board().layer_name(polygon.layer),
|
||||
workspace.autorouter.board().pin_selection_contains_polygon(
|
||||
&workspace.pin_selection,
|
||||
PolygonId::new(polygon_index),
|
||||
),
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layer_name(polygon.layer),
|
||||
workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.pin_selection_contains_polygon(
|
||||
&workspace.pin_selection,
|
||||
PolygonId::new(polygon_index),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -190,7 +222,14 @@ impl Display {
|
|||
viewport: &Viewport,
|
||||
workspace: &Workspace,
|
||||
) {
|
||||
for (_, joint) in workspace.autorouter.board().layout().joints().collection() {
|
||||
for (_, joint) in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.joints()
|
||||
.collection()
|
||||
{
|
||||
if workspace.appearance_panel.visible[joint.layer] {
|
||||
ui.painter().rect_stroke(
|
||||
egui::Rect {
|
||||
|
|
@ -212,6 +251,7 @@ impl Display {
|
|||
|
||||
for (i, segment) in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.segments()
|
||||
|
|
@ -220,6 +260,7 @@ impl Display {
|
|||
if workspace.appearance_panel.visible[segment.layer] {
|
||||
let endpoints = workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.segment_endpoints(SegmentId::new(i));
|
||||
|
|
@ -240,6 +281,7 @@ impl Display {
|
|||
|
||||
for (i, polygon) in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.polygons()
|
||||
|
|
@ -268,10 +310,20 @@ impl Display {
|
|||
viewport: &Viewport,
|
||||
workspace: &Workspace,
|
||||
) {
|
||||
for layer in 0..*workspace.autorouter.board().layout().layer_count() {
|
||||
for layer in 0..*workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.layer_count()
|
||||
{
|
||||
if workspace.appearance_panel.visible[layer] {
|
||||
for navmesh in
|
||||
workspace.autorouter.navmesher().layer_navmeshers()[layer].navmeshes()
|
||||
for navmesh in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.navmesher()
|
||||
.layer_navmeshers()[layer]
|
||||
.navmeshes()
|
||||
{
|
||||
for edge_geom in navmesh
|
||||
.triangulation()
|
||||
|
|
@ -309,7 +361,7 @@ impl Display {
|
|||
.appearance_panel
|
||||
.colors(ctx)
|
||||
.layers
|
||||
.color(workspace.navmesher_board.board().layer_name(layer))
|
||||
.color(workspace.autorouter.navmesher_board().board().layer_name(layer))
|
||||
.normal,*/
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -53,8 +53,11 @@ impl Viewport {
|
|||
let pointer_scene_pos = scene_to_viewport.inverse() * pointer_viewport_pos;
|
||||
|
||||
if response.clicked() {
|
||||
if let Some(pin_selector) =
|
||||
workspace.autorouter.board().point_pin_selector(
|
||||
if let Some(pin_selector) = workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.point_pin_selector(
|
||||
0,
|
||||
Vector2::new(
|
||||
pointer_scene_pos.x as i64,
|
||||
|
|
@ -113,14 +116,26 @@ impl Viewport {
|
|||
}
|
||||
|
||||
fn boundary_bounding_box(workspace: &Workspace) -> egui::Rect {
|
||||
let first = workspace.autorouter.board().layout().boundary()[0];
|
||||
let first = workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.boundary()[0];
|
||||
|
||||
let mut min_x = first[0];
|
||||
let mut max_x = first[0];
|
||||
let mut min_y = first[1];
|
||||
let mut max_y = first[1];
|
||||
|
||||
for point in workspace.autorouter.board().layout().boundary()[1..].iter() {
|
||||
for point in workspace
|
||||
.autorouter
|
||||
.navmesher_board()
|
||||
.board()
|
||||
.layout()
|
||||
.boundary()[1..]
|
||||
.iter()
|
||||
{
|
||||
if point[0] < min_x {
|
||||
min_x = point[0];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@ impl Workspace {
|
|||
let appearance_panel = AppearancePanel::new(&board);
|
||||
|
||||
Self {
|
||||
autorouter: Autorouter::with_board(board),
|
||||
autorouter: Autorouter::new(board),
|
||||
appearance_panel,
|
||||
pin_selection: PinSelection::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_appearance_panel(&mut self, ctx: &egui::Context) {
|
||||
self.appearance_panel.update(ctx, &self.autorouter.board());
|
||||
self.appearance_panel
|
||||
.update(ctx, &self.autorouter.navmesher_board().board());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,141 +3,22 @@
|
|||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
use derive_getters::Getters;
|
||||
use undoredo::Recorder;
|
||||
|
||||
use crate::{
|
||||
Board, Joint, JointId, Polygon, PolygonId, Ratsnest, Segment, SegmentId, Vector2, Via, ViaId,
|
||||
navmesher::{MultiObstacleId, Navmesher},
|
||||
};
|
||||
use crate::{Board, Ratsnest, navmesher::NavmesherBoard};
|
||||
|
||||
#[derive(Clone, Debug, Getters)]
|
||||
pub struct Autorouter {
|
||||
navmesher: Navmesher,
|
||||
navmesher_board: NavmesherBoard,
|
||||
ratsnest: Ratsnest,
|
||||
board: Board,
|
||||
|
||||
joint_multiobstacles: Recorder<Vec<MultiObstacleId>>,
|
||||
segment_multiobstacles: Recorder<Vec<MultiObstacleId>>,
|
||||
polygon_multiobstacles: Recorder<Vec<MultiObstacleId>>,
|
||||
}
|
||||
|
||||
impl Autorouter {
|
||||
pub fn with_board(board: Board) -> Self {
|
||||
let mut this = Self {
|
||||
navmesher: Navmesher::new(
|
||||
board
|
||||
.layout()
|
||||
.boundary()
|
||||
.iter()
|
||||
.map(|p| Vector2::new(p[0], p[1])),
|
||||
*board.layout().layer_count(),
|
||||
),
|
||||
ratsnest: Ratsnest::new(&board),
|
||||
board,
|
||||
pub fn new(board: Board) -> Self {
|
||||
let ratsnest = Ratsnest::new(&board);
|
||||
|
||||
joint_multiobstacles: Recorder::new(Vec::new()),
|
||||
segment_multiobstacles: Recorder::new(Vec::new()),
|
||||
polygon_multiobstacles: Recorder::new(Vec::new()),
|
||||
};
|
||||
|
||||
for (i, joint) in this.board.layout().joints().collection() {
|
||||
this.joint_multiobstacles.insert(
|
||||
i,
|
||||
this.navmesher
|
||||
.insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(*joint)),
|
||||
);
|
||||
Self {
|
||||
navmesher_board: NavmesherBoard::new(board),
|
||||
ratsnest,
|
||||
}
|
||||
|
||||
for (i, segment) in this.board.layout().segments().collection() {
|
||||
this.segment_multiobstacles.insert(
|
||||
i,
|
||||
this.navmesher.insert_multiobstacle(
|
||||
segment.layer,
|
||||
this.segment_bounding_rectangle(SegmentId::new(i), *segment),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (i, polygon) in this.board.layout().polygons().collection() {
|
||||
this.polygon_multiobstacles.insert(
|
||||
i,
|
||||
this.navmesher
|
||||
.insert_multiobstacle(polygon.layer, polygon.vertices.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
pub fn insert_joint(&mut self, joint: Joint) -> JointId {
|
||||
let joint_id = self.board.add_joint(joint);
|
||||
self.joint_multiobstacles.insert(
|
||||
joint_id.index(),
|
||||
self.navmesher
|
||||
.insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(joint)),
|
||||
);
|
||||
|
||||
joint_id
|
||||
}
|
||||
|
||||
fn joint_bounding_octagon(joint: Joint) -> [Vector2<i64>; 8] {
|
||||
let cx = joint.position.x;
|
||||
let cy = joint.position.y;
|
||||
let r = joint.radius as i64;
|
||||
|
||||
[
|
||||
Vector2::new(cx + r, cy + r / 2),
|
||||
Vector2::new(cx + r / 2, cy + r),
|
||||
Vector2::new(cx - r / 2, cy + r),
|
||||
Vector2::new(cx - r, cy + r / 2),
|
||||
Vector2::new(cx - r, cy - r / 2),
|
||||
Vector2::new(cx - r / 2, cy - r),
|
||||
Vector2::new(cx + r / 2, cy - r),
|
||||
Vector2::new(cx + r, cy - r / 2),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn insert_segment(&mut self, segment: Segment) -> SegmentId {
|
||||
let segment_id = self.board.add_segment(segment);
|
||||
self.segment_multiobstacles.insert(
|
||||
segment_id.index(),
|
||||
self.navmesher.insert_multiobstacle(
|
||||
segment.layer,
|
||||
self.segment_bounding_rectangle(segment_id, segment),
|
||||
),
|
||||
);
|
||||
|
||||
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_via(&mut self, via: Via) -> ViaId {
|
||||
// TODO: Insert into navmesh.
|
||||
self.board.add_via(via)
|
||||
}
|
||||
|
||||
pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId {
|
||||
let polygon_id = self.board.add_polygon(polygon.clone());
|
||||
self.polygon_multiobstacles.insert(
|
||||
polygon_id.index(),
|
||||
self.navmesher
|
||||
.insert_multiobstacle(polygon.layer, polygon.vertices),
|
||||
);
|
||||
|
||||
polygon_id
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
use derive_more::{
|
||||
Add, AddAssign, Constructor, Div, DivAssign, From, Into, Mul, MulAssign, Sub, SubAssign,
|
||||
};
|
||||
use polygon_unionfind::UnionFind;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(
|
||||
|
|
@ -177,8 +178,7 @@ pub fn kruskal_mst<W: Copy + Ord>(
|
|||
let mut sorted_edges = edges.to_vec();
|
||||
sorted_edges.sort_by_key(|(w, _)| *w);
|
||||
|
||||
let mut unionfind: polygon_unionfind::UnionFind<Vec<usize>, Vec<usize>> =
|
||||
polygon_unionfind::UnionFind::with_len(vertex_count);
|
||||
let mut unionfind: UnionFind = UnionFind::with_len(vertex_count);
|
||||
let mut min_spanning_tree = Vec::new();
|
||||
|
||||
for (_, uv) in sorted_edges {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use dearcut::{RecordingTriangulator, VertexId};
|
|||
use derive_getters::Getters;
|
||||
use derive_more::Constructor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use undoredo::Recorder;
|
||||
|
||||
use crate::Vector2;
|
||||
use crate::{Board, Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Vector2};
|
||||
|
||||
#[derive(
|
||||
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
|
||||
|
|
@ -169,3 +170,128 @@ impl Navmesher {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Getters)]
|
||||
pub struct NavmesherBoard {
|
||||
navmesher: Navmesher,
|
||||
board: Board,
|
||||
|
||||
joint_multiobstacles: Recorder<Vec<MultiObstacleId>>,
|
||||
segment_multiobstacles: Recorder<Vec<MultiObstacleId>>,
|
||||
polygon_multiobstacles: Recorder<Vec<MultiObstacleId>>,
|
||||
}
|
||||
|
||||
impl NavmesherBoard {
|
||||
pub fn new(board: Board) -> Self {
|
||||
let mut this = Self {
|
||||
navmesher: Navmesher::new(
|
||||
board
|
||||
.layout()
|
||||
.boundary()
|
||||
.iter()
|
||||
.map(|p| Vector2::new(p[0], p[1])),
|
||||
*board.layout().layer_count(),
|
||||
),
|
||||
board,
|
||||
|
||||
joint_multiobstacles: Recorder::new(Vec::new()),
|
||||
segment_multiobstacles: Recorder::new(Vec::new()),
|
||||
polygon_multiobstacles: Recorder::new(Vec::new()),
|
||||
};
|
||||
|
||||
for (i, joint) in this.board.layout().joints().collection() {
|
||||
this.joint_multiobstacles.insert(
|
||||
i,
|
||||
this.navmesher
|
||||
.insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(*joint)),
|
||||
);
|
||||
}
|
||||
|
||||
for (i, segment) in this.board.layout().segments().collection() {
|
||||
this.segment_multiobstacles.insert(
|
||||
i,
|
||||
this.navmesher.insert_multiobstacle(
|
||||
segment.layer,
|
||||
this.segment_bounding_rectangle(SegmentId::new(i), *segment),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (i, polygon) in this.board.layout().polygons().collection() {
|
||||
this.polygon_multiobstacles.insert(
|
||||
i,
|
||||
this.navmesher
|
||||
.insert_multiobstacle(polygon.layer, polygon.vertices.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
pub fn insert_joint(&mut self, joint: Joint) -> JointId {
|
||||
let joint_id = self.board.add_joint(joint);
|
||||
self.joint_multiobstacles.insert(
|
||||
joint_id.index(),
|
||||
self.navmesher
|
||||
.insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(joint)),
|
||||
);
|
||||
|
||||
joint_id
|
||||
}
|
||||
|
||||
fn joint_bounding_octagon(joint: Joint) -> [Vector2<i64>; 8] {
|
||||
let cx = joint.position.x;
|
||||
let cy = joint.position.y;
|
||||
let r = joint.radius as i64;
|
||||
|
||||
[
|
||||
Vector2::new(cx + r, cy + r / 2),
|
||||
Vector2::new(cx + r / 2, cy + r),
|
||||
Vector2::new(cx - r / 2, cy + r),
|
||||
Vector2::new(cx - r, cy + r / 2),
|
||||
Vector2::new(cx - r, cy - r / 2),
|
||||
Vector2::new(cx - r / 2, cy - r),
|
||||
Vector2::new(cx + r / 2, cy - r),
|
||||
Vector2::new(cx + r, cy - r / 2),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn insert_segment(&mut self, segment: Segment) -> SegmentId {
|
||||
let segment_id = self.board.add_segment(segment);
|
||||
self.segment_multiobstacles.insert(
|
||||
segment_id.index(),
|
||||
self.navmesher.insert_multiobstacle(
|
||||
segment.layer,
|
||||
self.segment_bounding_rectangle(segment_id, segment),
|
||||
),
|
||||
);
|
||||
|
||||
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 {
|
||||
let polygon_id = self.board.add_polygon(polygon.clone());
|
||||
self.polygon_multiobstacles.insert(
|
||||
polygon_id.index(),
|
||||
self.navmesher
|
||||
.insert_multiobstacle(polygon.layer, polygon.vertices),
|
||||
);
|
||||
|
||||
polygon_id
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue