feat(topola-egui): Add option to display bend endpoint tangents

This is just to be able to debug navmesh pruning.
This commit is contained in:
Mikolaj Wielgus 2025-11-30 22:25:15 +01:00
parent 62a4d6c413
commit f94733e0f0
5 changed files with 81 additions and 1 deletions

View File

@ -407,6 +407,7 @@ pub struct DebugActions {
pub show_topo_navmesh: Switch,
pub show_bboxes: Switch,
pub show_primitive_indices: Switch,
pub show_endpoint_tangents: Switch,
pub fix_update_timestep: Switch,
}
@ -440,6 +441,10 @@ impl DebugActions {
tr.text("tr-menu-debug-show-primitive-indices"),
)
.into_switch(),
show_endpoint_tangents: Action::new_keyless(
tr.text("tr-menu-debug-show-bend-endpoint-tangents"),
)
.into_switch(),
fix_update_timestep: Action::new_keyless(tr.text("tr-menu-debug-fix-step-rate"))
.into_switch(),
}
@ -465,6 +470,8 @@ impl DebugActions {
self.show_bboxes.checkbox(ui, &mut menu_bar.show_bboxes);
self.show_primitive_indices
.checkbox(ui, &mut menu_bar.show_primitive_indices);
self.show_endpoint_tangents
.checkbox(ui, &mut menu_bar.show_bend_endpoint_tangents);
ui.separator();

View File

@ -18,7 +18,7 @@ use topola::{
head::GetFace,
primitive::MakePrimitiveShape,
},
geometry::{shape::AccessShape, GenericNode},
geometry::{primitive::PrimitiveShape, shape::AccessShape, GenericNode},
graph::{GetIndex, MakeRef},
interactor::{activity::ActivityStepper, interaction::InteractionStepper},
layout::poly::MakePolygon,
@ -78,6 +78,10 @@ impl<'a> Displayer<'a> {
self.display_activity(menu_bar);
if menu_bar.show_bend_endpoint_tangents {
self.display_bend_endpoint_tangents(menu_bar);
}
if menu_bar.show_primitive_indices {
self.display_primitive_indices(menu_bar);
}
@ -606,6 +610,50 @@ impl<'a> Displayer<'a> {
}
}
fn display_bend_endpoint_tangents(&mut self, menu_bar: &MenuBar) {
let board = self.workspace.interactor.invoker().autorouter().board();
for primitive in board
.layout()
.drawing()
.layer_primitive_nodes(menu_bar.multilayer_autoroute_options.planar.principal_layer)
{
let PrimitiveShape::Bend(bend_shape) =
primitive.primitive_ref(board.layout().drawing()).shape()
else {
continue;
};
self.painter.paint_solid_circle(
Circle {
pos: bend_shape.from,
r: 50.0,
},
egui::Color32::from_rgb(0, 0, 255),
);
self.painter.paint_line_segment(
bend_shape.from,
bend_shape.from + bend_shape.from_tangent_ray(),
egui::Stroke::new(3.0, egui::Color32::from_rgb(0, 0, 255)),
);
self.painter.paint_solid_circle(
Circle {
pos: bend_shape.to,
r: 50.0,
},
egui::Color32::from_rgb(0, 0, 255),
);
self.painter.paint_line_segment(
bend_shape.to,
bend_shape.to + bend_shape.to_tangent_ray(),
egui::Stroke::new(3.0, egui::Color32::from_rgb(0, 0, 255)),
);
}
}
fn display_primitive_indices(&mut self, menu_bar: &MenuBar) {
let board = self.workspace.interactor.invoker().autorouter().board();

View File

@ -42,6 +42,7 @@ pub struct MenuBar {
pub show_bboxes: bool,
pub show_origin_destination: bool,
pub show_primitive_indices: bool,
pub show_bend_endpoint_tangents: bool,
pub show_appearance_panel: bool,
pub fix_step_rate: bool,
pub step_rate: f32,
@ -87,6 +88,7 @@ impl MenuBar {
show_bboxes: false,
show_origin_destination: true,
show_primitive_indices: false,
show_bend_endpoint_tangents: false,
show_appearance_panel: true,
fix_step_rate: false,
step_rate: 1.0,

View File

@ -48,6 +48,7 @@ tr-menu-debug-show-pathfinding-scores = Show Pathfinding Scores
tr-menu-debug-show-topo-navmesh = Show Topological Navmesh
tr-menu-debug-show-bboxes = Show BBoxes
tr-menu-debug-show-primitive-indices = Show Primitive Indices
tr-menu-debug-show-bend-endpoint-tangents = Show Bend Endpoint Tangents
tr-menu-debug-fix-step-rate = Fix Step Rate
tr-menu-debug-step-rate = Step Rate
tr-menu-debug-step-rate-unit = steps/s

View File

@ -291,6 +291,28 @@ impl BendShape {
)
}
/// Determines if the provided point lies in the swept region between the rays cast by tangents
/// to the arc endpoints of the bend's outer circle, starting at `from` and `to`.
pub fn between_tangent_rays(&self, point: Point) -> bool {
math::between_vectors(point, self.from_tangent_ray(), self.to_tangent_ray())
}
pub fn from_tangent_ray(&self) -> Point {
// 90-degree CW rotation.
let center = self.inner_circle.pos;
let v_from = self.from - center;
Point::new(v_from.y(), -v_from.x())
}
pub fn to_tangent_ray(&self) -> Point {
// 90-degree CCW rotation.
let center = self.inner_circle.pos;
let v_to = self.to - center;
Point::new(-v_to.y(), v_to.x())
}
pub fn start_angle(&self) -> f64 {
let r = self.from - self.inner_circle.pos;
math::vector_angle(r)