2026-05-21-09-29-47 修复自动拉伸基准与缩放步长

This commit is contained in:
2026-05-21 09:51:33 +08:00
parent 464b1aab59
commit d7eeedd9b3
6 changed files with 216 additions and 13 deletions

View File

@@ -80,7 +80,7 @@ const poseStepConfig: Record<ModelPoseKey, { min: number; max: number; step: num
translateX: { min: -2, max: 2, step: 0.005, minus: '-X', plus: '+X' },
translateY: { min: -2, max: 2, step: 0.005, minus: '-Y', plus: '+Y' },
translateZ: { min: -2, max: 2, step: 0.005, minus: '-Z', plus: '+Z' },
scale: { min: 0.5, max: 3, step: 0.05, minus: '-S', plus: '+S' },
scale: { min: 0.5, max: 3, step: 0.005, minus: '-S', plus: '+S' },
};
const defaultModelPose: ModelPose = {
@@ -2585,19 +2585,19 @@ export default function ReverseWorkspace({
return volumePayload;
};
const loadVisibleModelBounds = async () => {
const loadGlobalModelBounds = async () => {
if (!project) {
return null;
}
const visibleFiles = (project.stlFiles ?? []).filter((fileName) => moduleStyles[fileName]?.visible !== false);
const cacheKey = `${project.id}:${visibleFiles.join('|')}`;
const modelFiles = project.stlFiles ?? [];
const cacheKey = `${project.id}:global:${modelFiles.join('|')}`;
const cached = modelBoundsCacheRef.current.get(cacheKey);
if (cached) {
return cached;
}
const modelBox = new THREE.Box3();
const results = await Promise.allSettled(visibleFiles.map((fileName) => (
const results = await Promise.allSettled(modelFiles.map((fileName) => (
getCachedModelPreview(project.id, fileName, 1000)
)));
results.forEach((result) => {
@@ -2630,9 +2630,9 @@ export default function ReverseWorkspace({
setStretchingAxis(axis);
setFusionError('');
try {
const bounds = await loadVisibleModelBounds();
const bounds = await loadGlobalModelBounds();
if (!bounds) {
throw new Error('未获取到可见 STL 构件边界');
throw new Error('未获取到 STL 构件边界');
}
const rawSize = new THREE.Vector3().subVectors(bounds.max, bounds.min);
const rotatedSize = getRotatedModelSize(bounds, modelPose);
@@ -2651,10 +2651,21 @@ export default function ReverseWorkspace({
};
const baseScale = (Math.max(dicomSize.x, dicomSize.y, dicomSize.z) / maxModelSize) * 0.92;
const rotatedAxisSize = Math.max(rotatedSize[axis], 1e-6);
const nextScale = clampPoseValue('scale', dicomSize[axis] / (rotatedAxisSize * baseScale));
const axisFitScale = dicomSize[axis] / (rotatedAxisSize * baseScale);
const containmentScale = Math.min(
dicomSize.x / (Math.max(rotatedSize.x, 1e-6) * baseScale),
dicomSize.y / (Math.max(rotatedSize.y, 1e-6) * baseScale),
dicomSize.z / (Math.max(rotatedSize.z, 1e-6) * baseScale),
);
const limitedByVolume = axisFitScale > containmentScale + 1e-6;
const nextScale = clampPoseValue('scale', Math.min(axisFitScale, containmentScale));
const nextPose = { ...modelPose, scale: nextScale };
updateModelPose({ scale: nextScale }, { markCustom: !options.silentInitial, keepStatus: true });
setPoseImportStatus(`已按 ${axis.toUpperCase()} 方向进行三维等比例拉伸`);
setPoseImportStatus(
limitedByVolume
? `已按 ${axis.toUpperCase()} 方向拉伸,并限制在 DICOM 体范围内`
: `已按 ${axis.toUpperCase()} 方向进行三维等比例拉伸`,
);
if (options.silentInitial) {
savedWorkspaceSnapshotRef.current = createWorkspaceSnapshot({
modelPose: nextPose,
@@ -2792,7 +2803,8 @@ export default function ReverseWorkspace({
const clampPoseValue = (key: ModelPoseKey, value: number) => {
const limit = poseStepConfig[key];
return clamp(value, limit.min, limit.max);
const precision = getStepPrecision(limit.step);
return Number(clamp(value, limit.min, limit.max).toFixed(precision));
};
const updateModelPose = (partial: Partial<ModelPose>, options: { markCustom?: boolean; keepStatus?: boolean } = {}) => {