import * as THREE from "three"; import { useEffect } from "react"; import * as turf from "@turf/turf"; import * as Types from "../../../../types/world/worldTypes"; import arrayLinesToObject from "../../../builder/geomentries/lines/lineConvertions/arrayLinesToObject"; interface PolygonGeneratorProps { groupRef: React.MutableRefObject; lines: Types.RefLines; } export default function PolygonGenerator({ groupRef, lines, }: PolygonGeneratorProps) { useEffect(() => { let allLines = arrayLinesToObject(lines.current); const wallLines = allLines?.filter((line) => line?.type === "WallLine"); const aisleLines = allLines?.filter((line) => line?.type === "AisleLine") const wallPoints = wallLines .map((pair) => pair?.line.map((vals) => vals.position)) .filter((wall): wall is THREE.Vector3[] => !!wall); const result = aisleLines.map((pair) => pair?.line.map((point) => ({ position: [point.position.x, point.position.z], uuid: point.uuid, })) ); if (!result || result.some((line) => !line)) { return; } const lineFeatures = result?.map((line: any) => turf.lineString(line.map((p: any) => p?.position)) ); const polygons = turf.polygonize(turf.featureCollection(lineFeatures)); 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); } }); } }, [lines.current]); 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); groupRef.current?.add(wallMesh); } }); }; return null; }