Show real edges on featured boards (fix flat/edgeless look)
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) <noreply@anthropic.com>
This commit is contained in:
parent
9cbff4ec78
commit
d0e40cdcbc
|
|
@ -7,7 +7,7 @@ from PySide6.QtWidgets import (QApplication, QHBoxLayout, QPushButton,
|
||||||
QVBoxLayout, QWidget)
|
QVBoxLayout, QWidget)
|
||||||
|
|
||||||
from ..scene import Scene
|
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):
|
class Viewport(QWidget):
|
||||||
|
|
@ -64,13 +64,16 @@ class Viewport(QWidget):
|
||||||
labels, pts = [], []
|
labels, pts = [], []
|
||||||
for i, part in enumerate(scene.parts):
|
for i, part in enumerate(scene.parts):
|
||||||
selected = part.id in selected_ids
|
selected = part.id in selected_ids
|
||||||
|
mesh = _part_mesh(part)
|
||||||
actor = self.plotter.add_mesh(
|
actor = self.plotter.add_mesh(
|
||||||
_part_mesh(part),
|
mesh,
|
||||||
color="#f5d76e" if selected else _PALETTE[i % len(_PALETTE)],
|
color="#f5d76e" if selected else _PALETTE[i % len(_PALETTE)],
|
||||||
show_edges=not part.features, line_width=3 if selected else 1,
|
show_edges=not part.features, line_width=3 if selected else 1,
|
||||||
edge_color="black", reset_camera=False, pickable=True,
|
edge_color="black", reset_camera=False, pickable=True,
|
||||||
)
|
)
|
||||||
self._actor_to_pid[actor] = part.id
|
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)]
|
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)
|
labels.append(part.name or part.id)
|
||||||
pts.append(mid)
|
pts.append(mid)
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,20 @@ def _part_mesh(part: Part):
|
||||||
return cube
|
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:
|
def _quiet_vtk() -> None:
|
||||||
"""Stop VTK from spamming warnings (esp. headless) through Python logging."""
|
"""Stop VTK from spamming warnings (esp. headless) through Python logging."""
|
||||||
try:
|
try:
|
||||||
|
|
@ -71,14 +85,17 @@ def _render(plotter, scene: Scene) -> None:
|
||||||
labels, label_pts = [], []
|
labels, label_pts = [], []
|
||||||
for i, part in enumerate(scene.parts):
|
for i, part in enumerate(scene.parts):
|
||||||
edge = part.id == scene.selection
|
edge = part.id == scene.selection
|
||||||
|
mesh = _part_mesh(part)
|
||||||
plotter.add_mesh(
|
plotter.add_mesh(
|
||||||
_part_mesh(part),
|
mesh,
|
||||||
color="#f5d76e" if edge else _PALETTE[i % len(_PALETTE)],
|
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,
|
line_width=3 if edge else 1,
|
||||||
edge_color="black",
|
edge_color="black",
|
||||||
smooth_shading=False,
|
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)]
|
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)
|
labels.append(part.name or part.id)
|
||||||
label_pts.append(mid)
|
label_pts.append(mid)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue