Design: vertex picking — a click near a corner takes the corner

Completes the precedence Tommaso asked for: vertex, then edge, then face, all
from ONE click, all decided in screen pixels. Verified on :11 by sweeping into
the right corner of a plate — x=1250 and 1290 report "face 5 selected", x=1308,
1318 and 1323 report "vertex selected" — and the cyan marker lands exactly on
the corner in the render.

The vertex tolerance (11 px) is deliberately LARGER than the edge one (8 px). A
corner lies ON its edges, so equal radii would make vertices unreachable: every
click near one would resolve to the edge underneath. Bigger-wins-first is what
makes the smallest entity actually pickable.

Vertices come from the sampled edge polylines' endpoints rather than a separate
topology walk — every corner of a face is the end of one of its edges, so the
data was already in hand.

The highlight is a camera-facing square scaled by 1/zoom, the same trick the
edge ribbon uses, so it reads as a constant dot at any zoom. This is why vertex
picking did not ship with the previous commit: the Edge render path billboards
a ribbon and degenerates on a two-point input, and a selection you cannot see
is not a selection (L5). Better to add the primitive than to fake the feature.

DesignPanel now distinguishes level 4: a picked corner sets neither face nor
edge, because a corner is not its face, and the offer classifies it as
OfferSel::Vertex — where Plane, Axis and Coord Sys already accept it.

snaporca-9xw (rubber band still open — see the issue).
This commit is contained in:
Tommaso Bianchi
2026-07-31 12:48:15 +02:00
parent b003d20e37
commit 33f97d259b
4 changed files with 52 additions and 5 deletions
+5 -1
View File
@@ -119,7 +119,9 @@ public:
// Solid topology selection on the committed bodies: clicking a solid cycles
// whole-solid -> face -> edge (Onshape-style) to target fillet/chamfer/extrude. With
// multiple bodies the pick resolves WHICH body was hit (per-triangle body id).
enum class SolidSel { None, Whole, Face, Edge };
// Appended, never reordered: DesignPanel maps this to a level int (Whole=1, Face=2,
// Edge=3, Vertex=4) and the offer table keys off it.
enum class SolidSel { None, Whole, Face, Edge, Vertex };
// Point the tool at the current bodies + their concatenated tessellation (non-owning;
// pass nullptr to clear). Call after each recompute — selection resets (ids invalidate).
// tri_face = per-triangle face id within its body; tri_body = per-triangle body index.
@@ -903,6 +905,7 @@ private:
int m_sel_face{-1};
int m_sel_edge{-1};
std::vector<Vec3d> m_sel_edge_pts;
Vec3d m_sel_vertex_pt{Vec3d::Zero()}; // world point of a picked vertex
bool handle_solid_click(GLCanvas3D& canvas, const wxMouseEvent& evt); // cycle + notify
void render_solid_highlight();
void render_datum_planes(); // translucent rectangles for datum/reference planes
@@ -913,6 +916,7 @@ private:
std::vector<Vec2d> m_datum_sizes; // per-plane (u,v) full extent; empty -> default
GLModel m_solid_face_model;
GLModel m_solid_edge_model;
GLModel m_solid_vertex_model;
int m_display_pick_region{-1}; // selected closed-region index within that feature (-1 none)
// Visual Extrude gizmo state (C5b). GUI-only; fed by the panel each refresh_preview.