import * as THREE from "three"; import { useEffect } from "react"; import * as turf from "@turf/turf"; import * as Types from "../../../../types/world/worldTypes"; import { useThree } from "@react-three/fiber"; import { useSceneContext } from "../../../scene/sceneContext"; interface PolygonGeneratorProps { groupRef: React.MutableRefObject; } export default function PolygonGenerator({ groupRef, }: PolygonGeneratorProps) { const { aisleStore } = useSceneContext(); const { aisles } = aisleStore(); const { scene } = useThree(); useEffect(() => { // let allLines = arrayLinesToObject(lines.current); // const wallLines = allLines?.filter((line) => line?.type === "WallLine"); const result = aisles .filter( (aisle) => aisle.type.aisleType === "dotted-aisle" || aisle.type.aisleType === "solid-aisle" || aisle.type.aisleType === "dashed-aisle" || aisle.type.aisleType === "arc-aisle" ) .map((aisle) => aisle.points.map((point) => ({ position: [point.position[0], point.position[2]], uuid: point.pointUuid, })) ); const arcAndCircleResult = aisles .filter( (aisle) => aisle.type.aisleType === "circle-aisle" || aisle.type.aisleType === "arc-aisle" ) arcAndCircleResult.forEach((arc) => { const arcGroup = scene.getObjectByProperty("uuid", arc.aisleUuid); if (!arcGroup) return; const cloned = arcGroup?.clone(); cloned.position.set(cloned.position.x, cloned.position.y + 5, cloned.position.z); cloned?.traverse((child) => { if (child instanceof THREE.Mesh && child.geometry instanceof THREE.ExtrudeGeometry) { const extrudeGeometry = child.geometry as THREE.ExtrudeGeometry; extrudeGeometry.scale(1, 1, 500); child.geometry = extrudeGeometry; child.position.set(cloned.position.x, cloned.position.y + 0.1, cloned.position.z) child.rotateX(Math.PI / 2); child.name = "agv-arc-collider" groupRef.current?.add(child) } }); }); // const wallPoints = wallLines // .map((pair) => pair?.line.map((vals) => vals.position)) // .filter((wall): wall is THREE.Vector3[] => !!wall); if (!result || result.some((line) => !line)) { return; } const lineFeatures = result?.map((line: any) => turf.lineString(line.map((p: any) => p?.position)) ); const validLineFeatures = lineFeatures.filter((line) => { const coords = line.geometry.coordinates; return coords.length >= 2; }); const polygons = turf.polygonize(turf.featureCollection(validLineFeatures)); // renderWallGeometry(wallPoints); if (polygons.features.length > 0) { polygons.features.forEach((feature) => { if (feature.geometry.type === "Polygon") { const shape = new THREE.Shape(); const coords = feature.geometry.coordinates[0]; shape.moveTo(coords[0][0], coords[0][1]); for (let i = 1; i < coords.length; i++) { shape.lineTo(coords[i][0], coords[i][1]); } shape.lineTo(coords[0][0], coords[0][1]); const extrudeSettings = { depth: 5, bevelEnabled: false, }; const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); const material = new THREE.MeshBasicMaterial({ color: "blue", transparent: true, opacity: 0.5 }); const mesh = new THREE.Mesh(geometry, material); mesh.rotateX(Math.PI / 2); mesh.name = "agv-collider"; mesh.position.y = 5; mesh.receiveShadow = true; groupRef.current?.add(mesh); } }); } }, [ aisles, scene]); const renderWallGeometry = (walls: THREE.Vector3[][]) => { walls.forEach((wall) => { if (wall.length < 2) return; for (let i = 0; i < wall.length - 1; i++) { const start = new THREE.Vector3(wall[i].x, wall[i].y, wall[i].z); const end = new THREE.Vector3( wall[i + 1].x, wall[i + 1].y, wall[i + 1].z ); const wallHeight = 10; const direction = new THREE.Vector3().subVectors(end, start); const length = direction.length(); direction.normalize(); const wallGeometry = new THREE.BoxGeometry(length, wallHeight); const wallMaterial = new THREE.MeshBasicMaterial({ color: "#aaa", transparent: true, opacity: 0.5, }); const wallMesh = new THREE.Mesh(wallGeometry, wallMaterial); const midPoint = new THREE.Vector3() .addVectors(start, end) .multiplyScalar(0.5); wallMesh.position.set(midPoint.x, wallHeight / 2, midPoint.z); const quaternion = new THREE.Quaternion(); quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), direction); wallMesh.quaternion.copy(quaternion); wallMesh.name = "agv-collider"; groupRef.current?.add(wallMesh); } }); }; return null; }