feat: 完善一级关系编辑 UI 与视图体验

This commit is contained in:
2026-08-06 18:15:14 +08:00
parent 57d75541c3
commit eef9efcc1e
29 changed files with 3907 additions and 178 deletions
+70 -3
View File
@@ -80,14 +80,27 @@ class PolydataMixin:
face_key = _polydata_id_key(face_ids)
part_key = _polydata_id_key(part_ids)
cache_key = ("faces", face_key, part_key, float(deflection))
requested_deflection = max(float(deflection), 1e-9)
local_mesh_face_ids = self._local_fine_mesh_face_ids(face_key, part_key, requested_deflection)
mesh_deflection = self._effective_face_mesh_deflection(
requested_deflection,
local_mesh_face_ids=local_mesh_face_ids,
)
cache_key = (
"faces",
face_key,
part_key,
float(requested_deflection),
float(mesh_deflection),
local_mesh_face_ids,
)
cached = self._polydata_cache_get("_face_polydata_cache", cache_key)
if cached is not None:
return cached
selected_faces = set(face_key) if face_key is not None else None
selected_parts = set(part_key) if part_key is not None else None
self._ensure_mesh(deflection)
self._ensure_mesh(mesh_deflection, face_ids=local_mesh_face_ids)
points = vtk.vtkPoints()
polys = vtk.vtkCellArray()
@@ -137,8 +150,47 @@ class PolydataMixin:
poly.GetCellData().AddArray(solid_arr)
return self._polydata_cache_remember("_face_polydata_cache", cache_key, poly)
def _ensure_mesh(self, deflection: float) -> None:
def _local_fine_mesh_face_ids(
self,
face_key: tuple[int, ...] | None,
part_key: tuple[int, ...] | None,
requested: float,
) -> tuple[int, ...] | None:
if requested > 0.04 or part_key is not None or face_key is None:
return None
valid_face_ids = tuple(face_id for face_id in face_key if 0 <= face_id < len(self.faces))
if 0 < len(valid_face_ids) <= 64:
return valid_face_ids
return None
def _effective_face_mesh_deflection(
self,
requested: float,
*,
local_mesh_face_ids: tuple[int, ...] | None = None,
) -> float:
requested = max(float(requested), 1e-9)
if local_mesh_face_ids:
return requested
face_count = len(getattr(self, "faces", ()) or ())
if requested <= 0.04 and face_count > 600:
# Ultra-fine analytic remeshing can create million-cell VTK meshes
# on large STEP assemblies. Keep the B-Rep edit precision separate
# from the display mesh budget so selection and rotation stay usable.
return 0.1 if face_count > 1500 else 0.06
return requested
def _ensure_mesh(self, deflection: float, face_ids: tuple[int, ...] | None = None) -> None:
requested = max(float(deflection), 1e-9)
if face_ids:
local_deflections = getattr(self, "_face_mesh_deflections", {})
for face_id in face_ids:
if local_deflections.get(face_id) is not None and requested >= float(local_deflections[face_id]) * 0.999:
continue
self._mesh_single_face(face_id, requested)
local_deflections[face_id] = requested
self._face_mesh_deflections = local_deflections
return
if self._mesh_deflection is None or requested < self._mesh_deflection * 0.999:
if requested <= 0.04:
BRepMesh_IncrementalMesh(
@@ -162,6 +214,21 @@ class PolydataMixin:
BRepMesh_IncrementalMesh(self.shape, requested, False, math.radians(angular_degrees), True)
self._mesh_deflection = requested
def _mesh_single_face(self, face_id: int, requested: float) -> None:
if face_id < 0 or face_id >= len(self.faces):
return
try:
face = self.faces[face_id]
surface_type = BRepAdaptor_Surface(face).GetType()
if surface_type in {GeomAbs_Cylinder, GeomAbs_Cone}:
BRepMesh_IncrementalMesh(face, requested, False, math.radians(1.2), True)
elif surface_type in {GeomAbs_Sphere, GeomAbs_Torus}:
BRepMesh_IncrementalMesh(face, max(requested, 0.1), False, math.radians(4.0), True)
else:
BRepMesh_IncrementalMesh(face, requested, False, math.radians(12.0), True)
except Exception:
return
def build_snapshot_polydata(self, snapshot: dict[object, object], deflection: float = 0.8):
shape = _compound_from_shapes(value for value in snapshot.values() if isinstance(value, TopoDS_Shape))
BRepMesh_IncrementalMesh(shape, deflection)