Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-05-21 20:51:01 +00:00
parent e0377d49fa
commit 4c9e838f93
+63 -48
View File
@@ -352,15 +352,70 @@ function MeasurementLabel({ position, text, variant, fixed = false }: { position
); );
} }
/** Renders all measurements, snap point, and hover info */ /** Renders a single measurement's geometry + label.
* Coordinates are interpreted in whichever frame the component is mounted in. */
function MeasurementGraphic({ m }: { m: import('@/stores/useModelStore').Measurement }) {
const a: [number, number, number] = [m.pointA.x, m.pointA.y, m.pointA.z];
const b: [number, number, number] = [m.pointB.x, m.pointB.y, m.pointB.z];
const mid: [number, number, number] = [
(a[0] + b[0]) / 2,
(a[1] + b[1]) / 2,
(a[2] + b[2]) / 2,
];
if (m.kind === 'hole') {
return (
<group>
<PointMarker position={a} color="#f59e0b" />
<MeasurementLabel position={a} text={m.label ?? `Ø ${m.distanceMM.toFixed(1)}`} variant="accent" />
</group>
);
}
if (m.kind === 'edge') {
return (
<group>
<PointMarker position={a} color="#22c55e" />
<PointMarker position={b} color="#22c55e" />
<Line points={[a, b]} color="#22c55e" lineWidth={2} depthTest={false} />
<MeasurementLabel position={mid} text={m.label ?? `${m.distanceMM.toFixed(1)} mm`} variant="success" />
</group>
);
}
return (
<group>
<PointMarker position={a} color="#22c55e" />
<PointMarker position={b} color="#22c55e" />
<Line points={[a, b]} color="#22c55e" lineWidth={2} depthTest={false} />
<MeasurementLabel position={mid} text={`${m.distanceMM.toFixed(1)} mm`} variant="success" />
</group>
);
}
/** Renders measurements attached to a given model, in that model's local frame.
* Mounted inside GLBModel so they follow the model when it is repositioned. */
function ModelMeasurements({ modelId }: { modelId: string }) {
const measurements = useModelStore((s) => s.measurements);
const attached = measurements.filter((m) => m.modelId === modelId);
if (attached.length === 0) return null;
return (
<>
{attached.map((m) => (
<MeasurementGraphic key={m.id} m={m} />
))}
</>
);
}
/** Renders snap indicator, hover tooltip, pending point and any *legacy*
* world-frame measurements that aren't attached to a specific model. */
function MeasurementOverlay() { function MeasurementOverlay() {
const measurements = useModelStore((s) => s.measurements); const measurements = useModelStore((s) => s.measurements);
const measurePoints = useModelStore((s) => s.measurePoints); const measurePoints = useModelStore((s) => s.measurePoints);
const snapPoint = useModelStore((s) => s.snapPoint); const snapPoint = useModelStore((s) => s.snapPoint);
const hoverInfo = useModelStore((s) => s.hoverInfo); const hoverInfo = useModelStore((s) => s.hoverInfo);
const measureMode = useModelStore((s) => s.measureMode); const measureMode = useModelStore((s) => s.measureMode);
const scaleRatio = useModelStore((s) => s.scaleRatio);
const factor = scaleRatio?.factor ?? 1;
return ( return (
<> <>
@@ -381,55 +436,15 @@ function MeasurementOverlay() {
/> />
)} )}
{/* Pending first point */} {/* Pending first point (always in world coords) */}
{measurePoints.length === 1 && ( {measurePoints.length === 1 && (
<PointMarker position={[measurePoints[0].x, measurePoints[0].y, measurePoints[0].z]} color="#e8a838" /> <PointMarker position={[measurePoints[0].x, measurePoints[0].y, measurePoints[0].z]} color="#e8a838" />
)} )}
{/* Completed measurements */} {/* Legacy world-frame measurements (no modelId) */}
{measurements.map((m) => { {measurements.filter((m) => !m.modelId).map((m) => (
const a: [number, number, number] = [m.pointA.x, m.pointA.y, m.pointA.z]; <MeasurementGraphic key={m.id} m={m} />
const b: [number, number, number] = [m.pointB.x, m.pointB.y, m.pointB.z]; ))}
const mid: [number, number, number] = [
(a[0] + b[0]) / 2,
(a[1] + b[1]) / 2,
(a[2] + b[2]) / 2,
];
if (m.kind === 'hole') {
return (
<group key={m.id}>
<PointMarker position={a} color="#f59e0b" />
<MeasurementLabel position={a} text={m.label ?? `Ø ${m.distanceMM.toFixed(1)}`} variant="accent" />
</group>
);
}
if (m.kind === 'edge') {
return (
<group key={m.id}>
<PointMarker position={a} color="#22c55e" />
<PointMarker position={b} color="#22c55e" />
<Line points={[a, b]} color="#22c55e" lineWidth={2} depthTest={false} />
<MeasurementLabel position={mid} text={m.label ?? `${m.distanceMM.toFixed(1)} mm`} variant="success" />
</group>
);
}
return (
<group key={m.id}>
<PointMarker position={a} color="#22c55e" />
<PointMarker position={b} color="#22c55e" />
<Line
points={[a, b]}
color="#22c55e"
lineWidth={2}
depthTest={false}
/>
<MeasurementLabel position={mid} text={`${m.distanceMM.toFixed(1)} mm`} variant="success" />
</group>
);
})}
</> </>
); );
} }