From 9970571fada4ad857667c24b8dfe1509f73578b6 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 24 May 2026 19:14:51 +0000 Subject: [PATCH] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/SmartMeasure.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/components/three/SmartMeasure.ts b/src/components/three/SmartMeasure.ts index 0e87746..90d7fa5 100644 --- a/src/components/three/SmartMeasure.ts +++ b/src/components/three/SmartMeasure.ts @@ -443,6 +443,16 @@ const _ab = new THREE.Vector3(); const _ap = new THREE.Vector3(); const _closest = new THREE.Vector3(); +function closestPointOnSegment3D(p: THREE.Vector3, a: THREE.Vector3, b: THREE.Vector3, target: THREE.Vector3): THREE.Vector3 { + _ab.subVectors(b, a); + _ap.subVectors(p, a); + const abLenSq = _ab.lengthSq(); + if (abLenSq < 1e-6) return target.copy(a); + + const t = THREE.MathUtils.clamp(_ap.dot(_ab) / abLenSq, 0, 1); + return target.copy(a).addScaledVector(_ab, t); +} + function pointToSegmentDistSq3D(p: THREE.Vector3, a: THREE.Vector3, b: THREE.Vector3): number { _ab.subVectors(b, a); _ap.subVectors(p, a); @@ -503,7 +513,7 @@ export function findNearestEdgeSegment3D( mesh: THREE.Mesh, worldPoint: THREE.Vector3, thresholdMeters: number = 0.05 -): { midpoint: THREE.Vector3; lengthMM: number; a: THREE.Vector3; b: THREE.Vector3 } | null { +): { midpoint: THREE.Vector3; snapPoint: THREE.Vector3; lengthMM: number; a: THREE.Vector3; b: THREE.Vector3 } | null { let edgeLines: THREE.LineSegments | null = null; mesh.children.forEach(c => { if (c.userData.__edgeLine && c instanceof THREE.LineSegments) { @@ -529,6 +539,7 @@ export function findNearestEdgeSegment3D( let bestDistSq = Infinity; let bestIndex = -1; + const bestClosestLocal = new THREE.Vector3(); const thresholdSq = thresholdMeters * thresholdMeters; const segCount = posAttr.count / 2; @@ -539,11 +550,13 @@ export function findNearestEdgeSegment3D( aLocal.fromBufferAttribute(posAttr, i * 2); bLocal.fromBufferAttribute(posAttr, i * 2 + 1); - const distSq = pointToSegmentDistSq3D(localPoint, aLocal, bLocal); + closestPointOnSegment3D(localPoint, aLocal, bLocal, _closest); + const distSq = localPoint.distanceToSquared(_closest); if (distSq < bestDistSq) { bestDistSq = distSq; bestIndex = i; + bestClosestLocal.copy(_closest); } } @@ -551,8 +564,9 @@ export function findNearestEdgeSegment3D( const a = new THREE.Vector3().fromBufferAttribute(posAttr, bestIndex * 2).applyMatrix4(matrix); const b = new THREE.Vector3().fromBufferAttribute(posAttr, bestIndex * 2 + 1).applyMatrix4(matrix); const midpoint = a.clone().add(b).multiplyScalar(0.5); + const snapPoint = bestClosestLocal.clone().applyMatrix4(matrix); const lengthMM = a.distanceTo(b) * 1000; - return { midpoint, lengthMM, a, b }; + return { midpoint, snapPoint, lengthMM, a, b }; } return null; } @@ -652,6 +666,6 @@ export function resolveSnap3D( const v = findNearestVertex3D(mesh, hitPoint, vertexThresholdMeters); if (v) return { point: v, type: 'vertex' }; const e = findNearestEdgeSegment3D(mesh, hitPoint, edgeThresholdMeters); - if (e) return { point: e.midpoint, type: 'edge' }; + if (e) return { point: e.snapPoint, type: 'edge' }; return { point: hitPoint.clone(), type: 'surface' }; }