Merge pull request 'simulation' (#4) from simulation into main

Reviewed-on: http://185.100.212.76:7776/Dwinzo-Beta/Dwinzo_dev/pulls/4
This commit is contained in:
Vishnu 2025-03-26 05:58:19 +00:00
commit 6971fff571
3 changed files with 537 additions and 22759 deletions

57
app/.gitignore vendored
View File

@ -1,28 +1,29 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies # dependencies
/node_modules /node_modules
/.pnp /package-lock.json
.pnp.js /.pnp
.pnp.js
# testing
/coverage # testing
/coverage
# production
/build # production
/build
# misc
.DS_Store # misc
.env.local .DS_Store
.env.development.local .env.local
.env.test.local .env.development.local
.env.production.local .env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log* npm-debug.log*
yarn-error.log* yarn-debug.log*
yarn-error.log*
# remove zip
*.zip # remove zip
**/temp/ *.zip
**/temp/

22266
app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,466 +1,509 @@
import React, { useState, useEffect, useMemo, useRef } from "react"; import React, { useState, useEffect, useMemo, useRef } from "react";
import { Line, Sphere } from "@react-three/drei"; import { Line, Sphere } from "@react-three/drei";
import { useThree, useFrame } from "@react-three/fiber"; import { useThree, useFrame } from "@react-three/fiber";
import * as THREE from "three"; import * as THREE from "three";
import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store"; import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store";
// import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi"; // import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi";
// import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi"; // import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi";
import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi"; import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
import * as CONSTANTS from '../../../types/world/worldConstants'; import * as CONSTANTS from '../../../types/world/worldConstants';
const ZoneGroup: React.FC = () => { const ZoneGroup: React.FC = () => {
const { camera, pointer, gl, raycaster, scene, controls } = useThree(); const { camera, pointer, gl, raycaster, scene, controls } = useThree();
const [startPoint, setStartPoint] = useState<THREE.Vector3 | null>(null); const [startPoint, setStartPoint] = useState<THREE.Vector3 | null>(null);
const [endPoint, setEndPoint] = useState<THREE.Vector3 | null>(null); const [endPoint, setEndPoint] = useState<THREE.Vector3 | null>(null);
const { zones, setZones } = useZones(); const { zones, setZones } = useZones();
const { zonePoints, setZonePoints } = useZonePoints(); const { zonePoints, setZonePoints } = useZonePoints();
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
const [draggedSphere, setDraggedSphere] = useState<THREE.Vector3 | null>(null); const [draggedSphere, setDraggedSphere] = useState<THREE.Vector3 | null>(null);
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
const { removedLayer, setRemovedLayer } = useRemovedLayer(); const { removedLayer, setRemovedLayer } = useRemovedLayer();
const { toolMode, setToolMode } = useToolMode(); const { toolMode, setToolMode } = useToolMode();
const { movePoint, setMovePoint } = useMovePoint(); const { movePoint, setMovePoint } = useMovePoint();
const { deleteModels, setDeleteModels } = useDeleteModels(); const { deleteModels, setDeleteModels } = useDeleteModels();
const { activeLayer, setActiveLayer } = useActiveLayer(); const { activeLayer, setActiveLayer } = useActiveLayer();
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const groupsRef = useRef<any>(); const groupsRef = useRef<any>();
const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({ const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({
side: THREE.DoubleSide, side: THREE.DoubleSide,
vertexShader: ` vertexShader: `
varying vec2 vUv; varying vec2 vUv;
void main(){ void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv; vUv = uv;
} }
`, `,
fragmentShader: ` fragmentShader: `
varying vec2 vUv; varying vec2 vUv;
uniform vec3 uColor; uniform vec3 uColor;
void main(){ void main(){
float alpha = 1.0 - vUv.y; float alpha = 1.0 - vUv.y;
gl_FragColor = vec4(uColor, alpha); gl_FragColor = vec4(uColor, alpha);
} }
`, `,
uniforms: { uniforms: {
uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) }, uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) },
}, },
transparent: true, transparent: true,
}), []); }), []);
useEffect(() => { useEffect(() => {
const fetchZones = async () => { const fetchZones = async () => {
const email = localStorage.getItem('email'); const email = localStorage.getItem('email');
if (!email) return; if (!email) return;
const organization = email.split("@")[1].split(".")[0]; const organization = email.split("@")[1].split(".")[0];
const data = await getZonesApi(organization); const data = await getZonesApi(organization);
if (data.data && data.data.length > 0) { if (data.data && data.data.length > 0) {
const fetchedZones = data.data.map((zone: any) => ({ const fetchedZones = data.data.map((zone: any) => ({
zoneId: zone.zoneId, zoneId: zone.zoneId,
zoneName: zone.zoneName, zoneName: zone.zoneName,
points: zone.points, points: zone.points,
layer: zone.layer layer: zone.layer
})); }));
setZones(fetchedZones); setZones(fetchedZones);
const fetchedPoints = data.data.flatMap((zone: any) => const fetchedPoints = data.data.flatMap((zone: any) =>
zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point)) zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point))
); );
setZonePoints(fetchedPoints); setZonePoints(fetchedPoints);
} }
}; };
fetchZones(); fetchZones();
}, []); }, []);
useEffect(() => { useEffect(() => {
localStorage.setItem('zones', JSON.stringify(zones)); localStorage.setItem('zones', JSON.stringify(zones));
}, [zones]) }, [zones])
useEffect(() => { useEffect(() => {
if (removedLayer) { if (removedLayer) {
const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer); const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer);
setZones(updatedZones); setZones(updatedZones);
const updatedzonePoints = zonePoints.filter((_: any, index: any) => { const updatedzonePoints = zonePoints.filter((_: any, index: any) => {
const zoneIndex = Math.floor(index / 4); const zoneIndex = Math.floor(index / 4);
return zones[zoneIndex]?.layer !== removedLayer; return zones[zoneIndex]?.layer !== removedLayer;
}); });
setZonePoints(updatedzonePoints); setZonePoints(updatedzonePoints);
zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => { zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => {
deleteZoneFromBackend(zone.zoneId); deleteZoneFromBackend(zone.zoneId);
}); });
setRemovedLayer(null); setRemovedLayer(null);
} }
}, [removedLayer]); }, [removedLayer]);
useEffect(() => { useEffect(() => {
if (toolMode !== "Zone") { if (toolMode !== "Zone") {
setStartPoint(null); setStartPoint(null);
setEndPoint(null); setEndPoint(null);
} else { } else {
setDeletePointOrLine(false); setDeletePointOrLine(false);
setMovePoint(false); setMovePoint(false);
setDeleteModels(false); setDeleteModels(false);
} }
if (!toggleView) { if (!toggleView) {
setStartPoint(null); setStartPoint(null);
setEndPoint(null); setEndPoint(null);
} }
}, [toolMode, toggleView]); }, [toolMode, toggleView]);
const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => { const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
const email = localStorage.getItem('email'); const email = localStorage.getItem('email');
const userId = localStorage.getItem('userId'); const userId = localStorage.getItem('userId');
const organization = (email!.split("@")[1]).split(".")[0]; const organization = (email!.split("@")[1]).split(".")[0];
const input = { const calculateCenter = (points: number[][]) => {
userId: userId, if (!points || points.length === 0) return null;
organization: organization,
zoneData: { let sumX = 0, sumY = 0, sumZ = 0;
zoneName: zone.zoneName, const numPoints = points.length;
zoneId: zone.zoneId,
points: zone.points, points.forEach(([x, y, z]) => {
layer: zone.layer sumX += x;
} sumY += y;
} sumZ += z;
});
socket.emit('v2:zone:set', input);
}; return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
};
const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
const target: [number, number, number] | null = calculateCenter(zone.points);
const email = localStorage.getItem('email'); if (!target) return;
const userId = localStorage.getItem('userId'); const position = [target[0], 75, target[2]];
const organization = (email!.split("@")[1]).split(".")[0];
const input = {
const input = { userId: userId,
userId: userId, organization: organization,
organization: organization, zoneData: {
zoneData: { zoneName: zone.zoneName,
zoneName: zone.zoneName, zoneId: zone.zoneId,
zoneId: zone.zoneId, points: zone.points,
points: zone.points, viewPortCenter: target,
layer: zone.layer viewPortposition: position,
} layer: zone.layer
} }
}
socket.emit('v2:zone:set', input);
}; socket.emit('v2:zone:set', input);
};
const deleteZoneFromBackend = async (zoneId: string) => {
const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
const email = localStorage.getItem('email');
const userId = localStorage.getItem('userId'); const email = localStorage.getItem('email');
const organization = (email!.split("@")[1]).split(".")[0]; const userId = localStorage.getItem('userId');
const organization = (email!.split("@")[1]).split(".")[0];
const input = {
userId: userId, const calculateCenter = (points: number[][]) => {
organization: organization, if (!points || points.length === 0) return null;
zoneId: zoneId
} let sumX = 0, sumY = 0, sumZ = 0;
const numPoints = points.length;
socket.emit('v2:zone:delete', input);
}; points.forEach(([x, y, z]) => {
sumX += x;
const handleDeleteZone = (zoneId: string) => { sumY += y;
const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId); sumZ += z;
setZones(updatedZones); });
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId); return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
if (zoneIndex !== -1) { };
const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point)); const target: [number, number, number] | null = calculateCenter(zone.points);
const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); if (!target) return;
setZonePoints(updatedzonePoints); const position = [target[0], 75, target[2]];
}
const input = {
deleteZoneFromBackend(zoneId); userId: userId,
}; organization: organization,
zoneData: {
useEffect(() => { zoneName: zone.zoneName,
if (!camera || !toggleView) return; zoneId: zone.zoneId,
const canvasElement = gl.domElement; points: zone.points,
viewPortCenter: target,
let drag = false; viewPortposition: position,
let isLeftMouseDown = false; layer: zone.layer
}
const onMouseDown = (evt: any) => { }
if (evt.button === 0) {
isLeftMouseDown = true; socket.emit('v2:zone:set', input);
drag = false; };
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(groupsRef.current.children, true); const deleteZoneFromBackend = async (zoneId: string) => {
if (intersects.length > 0 && movePoint) { const email = localStorage.getItem('email');
const clickedObject = intersects[0].object; const userId = localStorage.getItem('userId');
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); const organization = (email!.split("@")[1]).split(".")[0];
if (sphereIndex !== -1) {
(controls as any).enabled = false; const input = {
setDraggedSphere(zonePoints[sphereIndex]); userId: userId,
setIsDragging(true); organization: organization,
} zoneId: zoneId
} }
}
}; socket.emit('v2:zone:delete', input);
};
const onMouseUp = (evt: any) => {
if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) { const handleDeleteZone = (zoneId: string) => {
isLeftMouseDown = false; const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId);
setZones(updatedZones);
if (!startPoint && !movePoint) {
raycaster.setFromCamera(pointer, camera); const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId);
const intersectionPoint = new THREE.Vector3(); if (zoneIndex !== -1) {
const point = raycaster.ray.intersectPlane(plane, intersectionPoint); const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
if (point) { zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point));
setStartPoint(point); const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4);
setEndPoint(null); setZonePoints(updatedzonePoints);
} }
} else if (startPoint && !movePoint) {
raycaster.setFromCamera(pointer, camera); deleteZoneFromBackend(zoneId);
const intersectionPoint = new THREE.Vector3(); };
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (!point) return; useEffect(() => {
if (!camera || !toggleView) return;
const points = [ const canvasElement = gl.domElement;
[startPoint.x, 0.15, startPoint.z],
[point.x, 0.15, startPoint.z], let drag = false;
[point.x, 0.15, point.z], let isLeftMouseDown = false;
[startPoint.x, 0.15, point.z],
[startPoint.x, 0.15, startPoint.z], const onMouseDown = (evt: any) => {
] as [number, number, number][]; if (evt.button === 0) {
isLeftMouseDown = true;
const zoneName = `Zone ${zones.length + 1}`; drag = false;
const zoneId = THREE.MathUtils.generateUUID();
const newZone = { raycaster.setFromCamera(pointer, camera);
zoneId, const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
zoneName,
points: points, if (intersects.length > 0 && movePoint) {
layer: activeLayer const clickedObject = intersects[0].object;
}; const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
if (sphereIndex !== -1) {
const newZones = [...zones, newZone]; (controls as any).enabled = false;
setDraggedSphere(zonePoints[sphereIndex]);
setZones(newZones); setIsDragging(true);
}
const newzonePoints = [ }
new THREE.Vector3(startPoint.x, 0.15, startPoint.z), }
new THREE.Vector3(point.x, 0.15, startPoint.z), };
new THREE.Vector3(point.x, 0.15, point.z),
new THREE.Vector3(startPoint.x, 0.15, point.z), const onMouseUp = (evt: any) => {
]; if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) {
isLeftMouseDown = false;
const updatedZonePoints = [...zonePoints, ...newzonePoints];
setZonePoints(updatedZonePoints); if (!startPoint && !movePoint) {
raycaster.setFromCamera(pointer, camera);
addZoneToBackend(newZone); const intersectionPoint = new THREE.Vector3();
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
setStartPoint(null); if (point) {
setEndPoint(null); setStartPoint(point);
} setEndPoint(null);
} else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) { }
raycaster.setFromCamera(pointer, camera); } else if (startPoint && !movePoint) {
const intersects = raycaster.intersectObjects(groupsRef.current.children, true); raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
if (intersects.length > 0) { const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
const clickedObject = intersects[0].object; if (!point) return;
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); const points = [
if (sphereIndex !== -1) { [startPoint.x, 0.15, startPoint.z],
const zoneIndex = Math.floor(sphereIndex / 4); [point.x, 0.15, startPoint.z],
const zoneId = zones[zoneIndex].zoneId; [point.x, 0.15, point.z],
handleDeleteZone(zoneId); [startPoint.x, 0.15, point.z],
return; [startPoint.x, 0.15, startPoint.z],
} ] as [number, number, number][];
}
} const zoneName = `Zone ${zones.length + 1}`;
const zoneId = THREE.MathUtils.generateUUID();
if (evt.button === 0) { const newZone = {
if (isDragging && draggedSphere) { zoneId,
setIsDragging(false); zoneName,
setDraggedSphere(null); points: points,
layer: activeLayer
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); };
if (sphereIndex !== -1) {
const zoneIndex = Math.floor(sphereIndex / 4); const newZones = [...zones, newZone];
if (zoneIndex !== -1 && zones[zoneIndex]) { setZones(newZones);
updateZoneToBackend(zones[zoneIndex]);
} const newzonePoints = [
} new THREE.Vector3(startPoint.x, 0.15, startPoint.z),
} new THREE.Vector3(point.x, 0.15, startPoint.z),
} new THREE.Vector3(point.x, 0.15, point.z),
}; new THREE.Vector3(startPoint.x, 0.15, point.z),
];
const onMouseMove = () => {
if (isLeftMouseDown) { const updatedZonePoints = [...zonePoints, ...newzonePoints];
drag = true; setZonePoints(updatedZonePoints);
}
raycaster.setFromCamera(pointer, camera); addZoneToBackend(newZone);
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
setStartPoint(null);
if (intersects.length > 0 && intersects[0].object.name.includes('point')) { setEndPoint(null);
gl.domElement.style.cursor = movePoint ? "pointer" : "default"; }
} else { } else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) {
gl.domElement.style.cursor = "default"; raycaster.setFromCamera(pointer, camera);
} const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
if (isDragging && draggedSphere) {
raycaster.setFromCamera(pointer, camera); if (intersects.length > 0) {
const intersectionPoint = new THREE.Vector3(); const clickedObject = intersects[0].object;
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point) { const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
draggedSphere.set(point.x, 0.15, point.z); if (sphereIndex !== -1) {
const zoneIndex = Math.floor(sphereIndex / 4);
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); const zoneId = zones[zoneIndex].zoneId;
if (sphereIndex !== -1) { handleDeleteZone(zoneId);
const zoneIndex = Math.floor(sphereIndex / 4); return;
const cornerIndex = sphereIndex % 4; }
}
const updatedZones = zones.map((zone: any, index: number) => { }
if (index === zoneIndex) {
const updatedPoints = [...zone.points]; if (evt.button === 0) {
updatedPoints[cornerIndex] = [point.x, 0.15, point.z]; if (isDragging && draggedSphere) {
updatedPoints[4] = updatedPoints[0]; setIsDragging(false);
return { ...zone, points: updatedPoints }; setDraggedSphere(null);
}
return zone; const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
}); if (sphereIndex !== -1) {
const zoneIndex = Math.floor(sphereIndex / 4);
setZones(updatedZones);
} if (zoneIndex !== -1 && zones[zoneIndex]) {
} updateZoneToBackend(zones[zoneIndex]);
} }
}; }
}
const onContext = (event: any) => { }
event.preventDefault(); };
setStartPoint(null);
setEndPoint(null); const onMouseMove = () => {
}; if (isLeftMouseDown) {
drag = true;
if (toolMode === 'Zone' || deletePointOrLine || movePoint) { }
canvasElement.addEventListener("mousedown", onMouseDown); raycaster.setFromCamera(pointer, camera);
canvasElement.addEventListener("mouseup", onMouseUp); const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
canvasElement.addEventListener("mousemove", onMouseMove);
canvasElement.addEventListener("contextmenu", onContext); if (intersects.length > 0 && intersects[0].object.name.includes('point')) {
} gl.domElement.style.cursor = movePoint ? "pointer" : "default";
return () => { } else {
canvasElement.removeEventListener("mousedown", onMouseDown); gl.domElement.style.cursor = "default";
canvasElement.removeEventListener("mouseup", onMouseUp); }
canvasElement.removeEventListener("mousemove", onMouseMove); if (isDragging && draggedSphere) {
canvasElement.removeEventListener("contextmenu", onContext); raycaster.setFromCamera(pointer, camera);
}; const intersectionPoint = new THREE.Vector3();
}, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]); const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point) {
useFrame(() => { draggedSphere.set(point.x, 0.15, point.z);
if (!startPoint) return;
raycaster.setFromCamera(pointer, camera); const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
const intersectionPoint = new THREE.Vector3(); if (sphereIndex !== -1) {
const point = raycaster.ray.intersectPlane(plane, intersectionPoint); const zoneIndex = Math.floor(sphereIndex / 4);
if (point) { const cornerIndex = sphereIndex % 4;
setEndPoint(point);
} const updatedZones = zones.map((zone: any, index: number) => {
}); if (index === zoneIndex) {
return ( const updatedPoints = [...zone.points];
<group ref={groupsRef} name='zoneGroup' > updatedPoints[cornerIndex] = [point.x, 0.15, point.z];
<group name="zones" visible={!toggleView}> updatedPoints[4] = updatedPoints[0];
{zones return { ...zone, points: updatedPoints };
.map((zone: any) => ( }
<group key={zone.zoneId} name={zone.zoneName}> return zone;
{zone.points.slice(0, -1).map((point: [number, number, number], index: number) => { });
const nextPoint = zone.points[index + 1];
setZones(updatedZones);
const point1 = new THREE.Vector3(point[0], point[1], point[2]); }
const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]); }
}
const planeWidth = point1.distanceTo(point2); };
const planeHeight = CONSTANTS.wallConfig.height;
const onContext = (event: any) => {
const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2); event.preventDefault();
setStartPoint(null);
const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x); setEndPoint(null);
};
return (
<mesh if (toolMode === 'Zone' || deletePointOrLine || movePoint) {
key={index} canvasElement.addEventListener("mousedown", onMouseDown);
position={midpoint} canvasElement.addEventListener("mouseup", onMouseUp);
rotation={[0, -angle, 0]} canvasElement.addEventListener("mousemove", onMouseMove);
> canvasElement.addEventListener("contextmenu", onContext);
<planeGeometry args={[planeWidth, planeHeight]} /> }
<primitive return () => {
object={zoneMaterial.clone()} canvasElement.removeEventListener("mousedown", onMouseDown);
attach="material" canvasElement.removeEventListener("mouseup", onMouseUp);
/> canvasElement.removeEventListener("mousemove", onMouseMove);
</mesh> canvasElement.removeEventListener("contextmenu", onContext);
); };
})} }, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]);
</group>
))} useFrame(() => {
</group> if (!startPoint) return;
<group name='zoneLines' visible={toggleView}> raycaster.setFromCamera(pointer, camera);
{zones const intersectionPoint = new THREE.Vector3();
.filter((zone: any) => zone.layer === activeLayer) const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
.map((zone: any) => ( if (point) {
<Line setEndPoint(point);
key={zone.zoneId} }
points={zone.points} });
color="#007BFF" return (
lineWidth={3} <group ref={groupsRef} name='zoneGroup' >
onClick={(e) => { <group name="zones" visible={!toggleView}>
e.stopPropagation(); {zones
if (deletePointOrLine) { .map((zone: any) => (
handleDeleteZone(zone.zoneId); <group key={zone.zoneId} name={zone.zoneName}>
} {zone.points.slice(0, -1).map((point: [number, number, number], index: number) => {
}} const nextPoint = zone.points[index + 1];
/>
))} const point1 = new THREE.Vector3(point[0], point[1], point[2]);
</group> const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]);
<group name="zonePoints" visible={toggleView}>
{zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => ( const planeWidth = point1.distanceTo(point2);
zone.points.slice(0, 4).map((point: any, pointIndex: number) => ( const planeHeight = CONSTANTS.wallConfig.height;
<Sphere
key={`${zone.zoneId}-point-${pointIndex}`} const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2);
position={new THREE.Vector3(...point)}
args={[0.3, 16, 16]} const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x);
name={`point-${zone.zoneId}-${pointIndex}`}
> return (
<meshBasicMaterial color="red" /> <mesh
</Sphere> key={index}
)) position={midpoint}
))} rotation={[0, -angle, 0]}
</group> >
<group name="tempGroup" visible={toggleView}> <planeGeometry args={[planeWidth, planeHeight]} />
{startPoint && endPoint && ( <primitive
<Line object={zoneMaterial.clone()}
points={[ attach="material"
[startPoint.x, 0.15, startPoint.z], />
[endPoint.x, 0.15, startPoint.z], </mesh>
[endPoint.x, 0.15, endPoint.z], );
[startPoint.x, 0.15, endPoint.z], })}
[startPoint.x, 0.15, startPoint.z], </group>
]} ))}
color="#C164FF" </group>
lineWidth={3} <group name='zoneLines' visible={toggleView}>
/> {zones
)} .filter((zone: any) => zone.layer === activeLayer)
</group> .map((zone: any) => (
</group> <Line
); key={zone.zoneId}
}; points={zone.points}
color="#007BFF"
lineWidth={3}
onClick={(e) => {
e.stopPropagation();
if (deletePointOrLine) {
handleDeleteZone(zone.zoneId);
}
}}
/>
))}
</group>
<group name="zonePoints" visible={toggleView}>
{zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => (
zone.points.slice(0, 4).map((point: any, pointIndex: number) => (
<Sphere
key={`${zone.zoneId}-point-${pointIndex}`}
position={new THREE.Vector3(...point)}
args={[0.3, 16, 16]}
name={`point-${zone.zoneId}-${pointIndex}`}
>
<meshBasicMaterial color="red" />
</Sphere>
))
))}
</group>
<group name="tempGroup" visible={toggleView}>
{startPoint && endPoint && (
<Line
points={[
[startPoint.x, 0.15, startPoint.z],
[endPoint.x, 0.15, startPoint.z],
[endPoint.x, 0.15, endPoint.z],
[startPoint.x, 0.15, endPoint.z],
[startPoint.x, 0.15, startPoint.z],
]}
color="#C164FF"
lineWidth={3}
/>
)}
</group>
</group>
);
};
export default ZoneGroup; export default ZoneGroup;