feat: 完善一级关系参数化建模与参数导出

This commit is contained in:
2026-08-11 18:28:16 +08:00
parent 6cb99a1273
commit 19364d81b5
20 changed files with 917 additions and 167 deletions
+36 -6
View File
@@ -288,6 +288,19 @@ class FeatureMixin:
max_scan_edges: int | None = None,
progress_callback: Callable[[], None] | None = None,
) -> list[dict[str, object]]:
limit = max(1, int(limit))
normalized_max_faces = None if max_scan_faces is None else max(0, int(max_scan_faces))
normalized_max_edges = None if max_scan_edges is None else max(0, int(max_scan_edges))
cache_key = (
"editable",
limit,
bool(detailed),
normalized_max_faces,
normalized_max_edges,
)
cache = getattr(self, "_editable_feature_candidates_cache", None)
if isinstance(cache, dict) and cache_key in cache:
return [dict(item) for item in cache[cache_key]]
per_type_limit = max(1, limit // 5)
candidates: list[dict[str, object]] = []
@@ -315,7 +328,7 @@ class FeatureMixin:
for item in self.cylindrical_feature_candidates(
limit=cylinder_scan_limit,
include_end_info=True,
max_scan_faces=max_scan_faces,
max_scan_faces=normalized_max_faces,
progress_callback=progress_callback,
):
feature_guess = str(item["feature_guess"])
@@ -680,7 +693,7 @@ class FeatureMixin:
shell_thickness_limit = max(2, min(per_type_limit, limit // 10))
shell_candidate_rows: list[dict[str, object]] = []
shell_scan_pool_limit = max(shell_thickness_limit * 4, 12)
face_scan_limit = len(self.faces) if max_scan_faces is None else min(len(self.faces), max(0, int(max_scan_faces)))
face_scan_limit = len(self.faces) if normalized_max_faces is None else min(len(self.faces), normalized_max_faces)
for face_id, face in enumerate(self.faces[:face_scan_limit]):
if progress_callback is not None and face_id % 30 == 0:
progress_callback()
@@ -832,7 +845,7 @@ class FeatureMixin:
ellipse_edge_major_radius_count = 0
ellipse_edge_minor_radius_count = 0
edge_type_limit = max(1, per_type_limit // 3)
edge_scan_limit = len(self.edges) if max_scan_edges is None else min(len(self.edges), max(0, int(max_scan_edges)))
edge_scan_limit = len(self.edges) if normalized_max_edges is None else min(len(self.edges), normalized_max_edges)
for edge_id, edge in enumerate(self.edges[:edge_scan_limit]):
if progress_callback is not None and edge_id % 80 == 0:
progress_callback()
@@ -995,7 +1008,10 @@ class FeatureMixin:
for candidate in candidates:
candidate["recognition_user_priority"] = feature_recognition_sort_key(candidate)[0]
candidates.sort(key=feature_recognition_sort_key)
return candidates[:limit]
result = [dict(item) for item in candidates[:limit]]
if isinstance(cache, dict):
cache[cache_key] = [dict(item) for item in result]
return [dict(item) for item in result]
def cylindrical_feature_candidates(
self,
@@ -1004,8 +1020,19 @@ class FeatureMixin:
max_scan_faces: int | None = None,
progress_callback: Callable[[], None] | None = None,
) -> list[dict[str, object]]:
limit = max(1, int(limit))
normalized_max_faces = None if max_scan_faces is None else max(0, int(max_scan_faces))
cache_key = (
"cylinder",
limit,
bool(include_end_info),
normalized_max_faces,
)
cache = getattr(self, "_cylindrical_feature_candidates_cache", None)
if isinstance(cache, dict) and cache_key in cache:
return [dict(item) for item in cache[cache_key]]
candidates: list[dict[str, object]] = []
face_scan_limit = len(self.faces) if max_scan_faces is None else min(len(self.faces), max(0, int(max_scan_faces)))
face_scan_limit = len(self.faces) if normalized_max_faces is None else min(len(self.faces), normalized_max_faces)
for face_id, face in enumerate(self.faces[:face_scan_limit]):
if progress_callback is not None and face_id % 30 == 0:
progress_callback()
@@ -1075,7 +1102,10 @@ class FeatureMixin:
candidates.append(candidate)
if len(candidates) >= limit:
break
return candidates
result = [dict(item) for item in candidates]
if isinstance(cache, dict):
cache[cache_key] = [dict(item) for item in result]
return [dict(item) for item in result]
def cylindrical_resize_plan(self, face_id: int, new_diameter: float) -> dict[str, object]:
if face_id < 0 or face_id >= len(self.faces):