import { useCallback } from 'react'; import { useAisleStore } from '../../../../store/builder/useAisleStore'; import * as THREE from 'three'; import { useWallStore } from '../../../../store/builder/useWallStore'; const SNAP_THRESHOLD = 0.5; // Distance threshold for snapping in meters const CAN_SNAP = true; // Whether snapping is enabled or not export const usePointSnapping = (currentPoint: { uuid: string, pointType: string, position: [number, number, number] } | null) => { const { aisles } = useAisleStore(); const { walls } = useWallStore(); const getAllOtherAislePoints = useCallback(() => { if (!currentPoint) return []; return aisles.flatMap(aisle => aisle.points.filter(point => point.pointUuid !== currentPoint.uuid) ); }, [aisles, currentPoint]); const getAllOtherWallPoints = useCallback(() => { if (!currentPoint) return []; return walls.flatMap(wall => wall.points.filter(point => point.pointUuid !== currentPoint.uuid) ); }, [walls, currentPoint]); const checkSnapForAisle = useCallback((position: [number, number, number]) => { if (!currentPoint || !CAN_SNAP) return { position: position, isSnapped: false, snappedPoint: null }; const otherPoints = getAllOtherAislePoints(); const currentVec = new THREE.Vector3(...position); for (const point of otherPoints) { const pointVec = new THREE.Vector3(...point.position); const distance = currentVec.distanceTo(pointVec); if (distance <= SNAP_THRESHOLD && currentPoint.pointType === 'Aisle') { return { position: point.position, isSnapped: true, snappedPoint: point }; } } return { position: position, isSnapped: false, snappedPoint: null }; }, [currentPoint, getAllOtherAislePoints]); const checkSnapForWall = useCallback((position: [number, number, number]) => { if (!currentPoint || !CAN_SNAP) return { position: position, isSnapped: false, snappedPoint: null }; const otherPoints = getAllOtherWallPoints(); const currentVec = new THREE.Vector3(...position); for (const point of otherPoints) { const pointVec = new THREE.Vector3(...point.position); const distance = currentVec.distanceTo(pointVec); if (distance <= SNAP_THRESHOLD && currentPoint.pointType === 'Wall') { return { position: point.position, isSnapped: true, snappedPoint: point }; } } return { position: position, isSnapped: false, snappedPoint: null }; }, [currentPoint, getAllOtherWallPoints]); return { checkSnapForAisle, checkSnapForWall, }; };