feat: 接入 SCDM 优先编辑闭环并支持阵列局部间距
接入 SCDM probe/edit/cache/校验链路,增强孔组、阵列、关系式和参数表交互。 支持阵列相邻段间距、移动意图切换、结果回滚校验,并补充对应回归脚本。
This commit is contained in:
+86
-16
@@ -21,9 +21,9 @@ from PySide6.QtWidgets import (
|
||||
from .model import StepModel
|
||||
from .asitus_bridge import run_asitus_hole_recognition
|
||||
from .records import OperationRecord
|
||||
from .scdm_feature_mapper import attach_local_face_ids_to_scdm_cache, map_scdm_raw_features
|
||||
from .scdm_feature_mapper import SCDM_FEATURE_CACHE_REVISION, attach_local_face_ids_to_scdm_cache, map_scdm_raw_features
|
||||
from .scdm_probe import run_scdm_probe
|
||||
from .scdm_schema import write_json
|
||||
from .scdm_schema import default_scdm_work_dir, file_fingerprint, read_json, write_json
|
||||
from .ui_helpers import * # noqa: F403
|
||||
from .workers import EditWorker, LoadWorker, ScanWorker
|
||||
|
||||
@@ -1308,11 +1308,13 @@ class WindowCoreMixin:
|
||||
f"Loaded {self.step_path.name}; 大模型已跳过全量边线补绘,旋转会更流畅,切到 Edge 选择时再按需生成。"
|
||||
)
|
||||
pending_scdm_reload = isinstance(getattr(self, "pending_scdm_edit_reload", None), dict)
|
||||
if large_interaction_model and not pending_scdm_reload:
|
||||
scdm_cache_restored = False if pending_scdm_reload else self._restore_scdm_feature_cache_from_disk()
|
||||
if large_interaction_model and not pending_scdm_reload and not scdm_cache_restored:
|
||||
self._defer_large_model_recognition_preloads()
|
||||
else:
|
||||
QTimer.singleShot(160, self._start_asitus_hole_recognition_preload)
|
||||
QTimer.singleShot(240, lambda: self._start_scdm_probe_preload(force=pending_scdm_reload))
|
||||
if pending_scdm_reload or not scdm_cache_restored:
|
||||
QTimer.singleShot(240, lambda: self._start_scdm_probe_preload(force=pending_scdm_reload))
|
||||
|
||||
def _large_model_interaction_mode(self, stats: object | None = None) -> bool:
|
||||
if stats is not None:
|
||||
@@ -1354,9 +1356,84 @@ class WindowCoreMixin:
|
||||
if hasattr(self, "_update_current_capability_panel"):
|
||||
self._update_current_capability_panel()
|
||||
|
||||
def _install_scdm_feature_cache(self, cache: dict[str, object], *, cache_path: str = "", message: str = "") -> None:
|
||||
self.scdm_feature_cache = dict(cache)
|
||||
self.scdm_feature_cache_state = "ready"
|
||||
self.scdm_feature_cache_message = message or "SCDM 可修改参数识别完成。"
|
||||
self.scdm_feature_cache_path = str(cache_path or "")
|
||||
if self.model is not None:
|
||||
try:
|
||||
self.model.scdm_feature_cache = dict(cache)
|
||||
except Exception:
|
||||
pass
|
||||
if hasattr(self, "_update_current_capability_panel"):
|
||||
self._update_current_capability_panel()
|
||||
if hasattr(self, "_refresh_property_editor"):
|
||||
self._refresh_property_editor()
|
||||
|
||||
def _restore_scdm_feature_cache_from_disk(self) -> bool:
|
||||
if self.model is None or self.step_path is None:
|
||||
return False
|
||||
step_path = Path(self.step_path)
|
||||
try:
|
||||
fingerprint = file_fingerprint(step_path)
|
||||
except OSError:
|
||||
return False
|
||||
project_root = Path(__file__).resolve().parent.parent
|
||||
work_dir = default_scdm_work_dir(step_path, project_root=project_root, fingerprint=fingerprint)
|
||||
cache_path = work_dir / "scdm_feature_cache.json"
|
||||
raw_path = work_dir / "scdm_raw_features.json"
|
||||
|
||||
cache: dict[str, object] | None = None
|
||||
if cache_path.is_file():
|
||||
try:
|
||||
candidate = read_json(cache_path)
|
||||
revision = _safe_int_or_none(candidate.get("mapperRevision")) or 0
|
||||
if str(candidate.get("modelFingerprint") or "") == fingerprint and revision >= SCDM_FEATURE_CACHE_REVISION:
|
||||
cache = candidate
|
||||
except Exception:
|
||||
cache = None
|
||||
|
||||
if cache is None and raw_path.is_file():
|
||||
try:
|
||||
raw = read_json(raw_path)
|
||||
raw_model = raw.get("model")
|
||||
raw_fingerprint = str(raw_model.get("fingerprint") or "") if isinstance(raw_model, dict) else ""
|
||||
if raw_fingerprint == fingerprint:
|
||||
cache = attach_local_face_ids_to_scdm_cache(
|
||||
map_scdm_raw_features(raw),
|
||||
self._scdm_local_face_signatures(),
|
||||
)
|
||||
write_json(cache_path, cache)
|
||||
except Exception:
|
||||
cache = None
|
||||
|
||||
if cache is None:
|
||||
return False
|
||||
self._install_scdm_feature_cache(
|
||||
cache,
|
||||
cache_path=str(cache_path),
|
||||
message="已从本地 SCDM 识别缓存恢复;模型变更后会重新识别。",
|
||||
)
|
||||
self.statusBar().showMessage("已恢复本地 SCDM 识别缓存,参数表可直接使用。")
|
||||
return True
|
||||
|
||||
def _current_scdm_feature_cache_matches_loaded_step(self) -> bool:
|
||||
if self.step_path is None or not isinstance(getattr(self, "scdm_feature_cache", None), dict):
|
||||
return False
|
||||
cache = getattr(self, "scdm_feature_cache", None)
|
||||
try:
|
||||
fingerprint = file_fingerprint(Path(self.step_path))
|
||||
except OSError:
|
||||
return False
|
||||
revision = _safe_int_or_none(cache.get("mapperRevision")) or 0
|
||||
return str(cache.get("modelFingerprint") or "") == fingerprint and revision >= SCDM_FEATURE_CACHE_REVISION
|
||||
|
||||
def _start_scdm_probe_preload(self, *, force: bool = False) -> None:
|
||||
if self.model is None or self.step_path is None:
|
||||
return
|
||||
if not force and self._current_scdm_feature_cache_matches_loaded_step():
|
||||
return
|
||||
if not force and self._large_model_interaction_mode():
|
||||
self._defer_large_model_recognition_preloads()
|
||||
return
|
||||
@@ -1476,21 +1553,14 @@ class WindowCoreMixin:
|
||||
return
|
||||
if isinstance(result.get("backend"), dict):
|
||||
self.scdm_backend_status = dict(result["backend"])
|
||||
self.scdm_feature_cache = dict(cache)
|
||||
self.scdm_feature_cache_state = "ready"
|
||||
self.scdm_feature_cache_message = "SCDM 可修改参数识别完成。"
|
||||
self.scdm_feature_cache_path = str(result.get("cache_path") or "")
|
||||
try:
|
||||
self.model.scdm_feature_cache = dict(cache)
|
||||
except Exception:
|
||||
pass
|
||||
self._install_scdm_feature_cache(
|
||||
dict(cache),
|
||||
cache_path=str(result.get("cache_path") or ""),
|
||||
message="SCDM 可修改参数识别完成。",
|
||||
)
|
||||
objects = cache.get("objects")
|
||||
count = len(objects) if isinstance(objects, list) else 0
|
||||
self.statusBar().showMessage(f"SCDM 可修改参数识别完成:{count} 个产品化对象。")
|
||||
if hasattr(self, "_update_current_capability_panel"):
|
||||
self._update_current_capability_panel()
|
||||
if hasattr(self, "_refresh_property_editor"):
|
||||
self._refresh_property_editor()
|
||||
if hasattr(self, "_finish_pending_scdm_edit_reload"):
|
||||
self._finish_pending_scdm_edit_reload(cache_ready=True)
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user