Dwinzo_dev/app/src/modules/duplicate/duplicateBuilder/duplicateZone/zoneDuplicate.tsx

183 lines
7.4 KiB
TypeScript

import { useEffect, useMemo, useRef, useState } from "react";
import { Html } from "@react-three/drei";
import * as THREE from "three";
import {
useToggleView,
useZonePoints,
} from "../../../../store/builder/store";
import { getZonesApi } from "../../../../services/factoryBuilder/zones/getZonesApi";
import * as CONSTANTS from "../../../../types/world/worldConstants";
import * as turf from "@turf/turf";
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
const ZoneDuplicate = ({ projectId }: { projectId: string }) => {
const [zones, setZones] = useState([]);
const { setZonePoints } = useZonePoints();
const { selectedZone } = useSelectedZoneStore();
const { toggleView } = useToggleView();
const groupsRef = useRef<any>();
const zoneMaterial = useMemo(
() =>
new THREE.ShaderMaterial({
side: THREE.DoubleSide,
vertexShader: `
varying vec2 vUv;
void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv;
}
`,
fragmentShader: `
varying vec2 vUv;
uniform vec3 uOuterColor;
void main(){
float alpha = 1.0 - vUv.y;
gl_FragColor = vec4(uOuterColor, alpha);
}
`,
uniforms: {
uOuterColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) },
},
transparent: true,
depthWrite: false,
}),
[]
);
useEffect(() => {
const fetchZones = async () => {
const email = localStorage.getItem("email");
if (!email) return;
const organization = email.split("@")[1].split(".")[0];
const data = await getZonesApi(organization, projectId);
if (data.length > 0) {
const fetchedZones = data.map((zone: any) => ({
zoneUuid: zone.zoneUuid,
zoneName: zone.zoneName,
points: zone.points,
viewPortCenter: zone.viewPortCenter,
viewPortposition: zone.viewPortposition,
layer: zone.layer,
}));
setZones(fetchedZones);
const fetchedPoints = data.flatMap((zone: any) =>
zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point))
);
setZonePoints(fetchedPoints);
}
};
fetchZones();
}, []);
return (
<group ref={groupsRef} name="zoneGroup">
<group name="zones" visible={!toggleView}>
{zones.map((zone: any) => (
<group
key={zone.zoneUuid}
name={zone.zoneName}
visible={zone.zoneUuid === selectedZone.zoneUuid}
>
{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]);
const point2 = new THREE.Vector3(
nextPoint[0],
nextPoint[1],
nextPoint[2]
);
const planeWidth = point1.distanceTo(point2);
const planeHeight = CONSTANTS.zoneConfig.height;
const midpoint = new THREE.Vector3(
(point1.x + point2.x) / 2,
CONSTANTS.zoneConfig.height / 2 +
(zone.layer - 1) * CONSTANTS.zoneConfig.height,
(point1.z + point2.z) / 2
);
const angle = Math.atan2(
point2.z - point1.z,
point2.x - point1.x
);
return (
<mesh
key={index}
position={midpoint}
rotation={[0, -angle, 0]}
>
<planeGeometry args={[planeWidth, planeHeight]} />
<primitive
object={zoneMaterial.clone()}
attach="material"
/>
</mesh>
);
})}
{!toggleView &&
(() => {
const points3D = zone.points || [];
const coords2D = points3D.map((p: any) => [p[0], p[2]]);
// Ensure the polygon is closed
if (
coords2D.length >= 4 &&
(coords2D[0][0] !== coords2D[coords2D.length - 1][0] ||
coords2D[0][1] !== coords2D[coords2D.length - 1][1])
) {
coords2D.push(coords2D[0]);
}
if (coords2D.length < 4) return null;
const polygon = turf.polygon([coords2D]);
const center2D = turf.center(polygon).geometry.coordinates;
// Calculate the average Y value
const sumY = points3D.reduce(
(sum: number, p: any) => sum + p[1],
0
);
const avgY = points3D.length > 0 ? sumY / points3D.length : 0;
const htmlPosition: [number, number, number] = [
center2D[0],
avgY + (CONSTANTS.zoneConfig.height || 0) + 1.5,
center2D[1],
];
return (
<Html
// data
key={zone.zoneUuid}
position={htmlPosition}
// class
className="zone-name-wrapper"
// others
center
>
<div className="zone-name">{zone.zoneName}</div>
</Html>
);
})()}
</group>
))}
</group>
</group>
);
};
export default ZoneDuplicate;