From d0e40cdcbc4ac6cf8cfb6773e1a0ee7e6af4e357 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 29 May 2026 14:32:42 -0300 Subject: [PATCH] Show real edges on featured boards (fix flat/edgeless look) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Featured (tessellated) boards were drawn with show_edges off to avoid triangle noise, which left them looking flat and edgeless. Now overlay only the true geometric edges via pyvista extract_feature_edges (corners, hole rims, chamfer bevels, mortise walls) — crisp like plain boards, no mesh noise. Selected boards get yellow edges. Applied in both the standalone viewer and the GUI viewport. Verified by render: hole, mortise, tenon, and chamfer all read clearly. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/woodshop/gui/viewport.py | 7 +++++-- src/woodshop/viewer.py | 21 +++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/woodshop/gui/viewport.py b/src/woodshop/gui/viewport.py index ed3904a..5c6a518 100644 --- a/src/woodshop/gui/viewport.py +++ b/src/woodshop/gui/viewport.py @@ -7,7 +7,7 @@ from PySide6.QtWidgets import (QApplication, QHBoxLayout, QPushButton, QVBoxLayout, QWidget) from ..scene import Scene -from ..viewer import _PALETTE, _part_mesh, _quiet_vtk +from ..viewer import _PALETTE, _add_feature_edges, _part_mesh, _quiet_vtk class Viewport(QWidget): @@ -64,13 +64,16 @@ class Viewport(QWidget): labels, pts = [], [] for i, part in enumerate(scene.parts): selected = part.id in selected_ids + mesh = _part_mesh(part) actor = self.plotter.add_mesh( - _part_mesh(part), + mesh, color="#f5d76e" if selected else _PALETTE[i % len(_PALETTE)], show_edges=not part.features, line_width=3 if selected else 1, edge_color="black", reset_camera=False, pickable=True, ) self._actor_to_pid[actor] = part.id + if part.features: + _add_feature_edges(self.plotter, mesh, selected) mid = [part.position_in[j] + part.axis_unit()[j] * part.length_in / 2 for j in range(3)] labels.append(part.name or part.id) pts.append(mid) diff --git a/src/woodshop/viewer.py b/src/woodshop/viewer.py index 1549959..08018c1 100644 --- a/src/woodshop/viewer.py +++ b/src/woodshop/viewer.py @@ -54,6 +54,20 @@ def _part_mesh(part: Part): return cube +def _add_feature_edges(plotter, mesh, selected: bool) -> None: + """Overlay a tessellated solid's real edges (corners/holes/chamfers) so it + reads as crisply as a plain board, without the triangle-mesh noise.""" + try: + edges = mesh.extract_feature_edges( + feature_angle=20, boundary_edges=True, feature_edges=True, + manifold_edges=False, non_manifold_edges=False) + if edges.n_points: + plotter.add_mesh(edges, color="yellow" if selected else "black", + line_width=3 if selected else 2, reset_camera=False) + except Exception: + pass + + def _quiet_vtk() -> None: """Stop VTK from spamming warnings (esp. headless) through Python logging.""" try: @@ -71,14 +85,17 @@ def _render(plotter, scene: Scene) -> None: labels, label_pts = [], [] for i, part in enumerate(scene.parts): edge = part.id == scene.selection + mesh = _part_mesh(part) plotter.add_mesh( - _part_mesh(part), + mesh, color="#f5d76e" if edge else _PALETTE[i % len(_PALETTE)], - show_edges=not part.features, # triangle mesh would look noisy with edges + show_edges=not part.features, # plain boxes: real quad edges line_width=3 if edge else 1, edge_color="black", smooth_shading=False, ) + if part.features: # tessellated: overlay only the true edges + _add_feature_edges(plotter, mesh, edge) mid = [part.position_in[j] + part.axis_unit()[j] * part.length_in / 2 for j in range(3)] labels.append(part.name or part.id) label_pts.append(mid)