Refactor: Integrate activeLayer and builder store into SelectFloorPlan and LoadBlueprint components; enhance getWallPointsFromBlueprint function with additional parameters for wall creation; update wall handling in WallCreator and PolygonGenerator components.

This commit is contained in:
2025-06-30 12:59:16 +05:30
parent 90df6c2b01
commit e589cb22b5
6 changed files with 174 additions and 102 deletions

View File

@@ -1,10 +1,12 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import useLayoutStore from "../../store/builder/uselayoutStore"; import useLayoutStore from "../../store/builder/uselayoutStore";
import { useDfxUpload } from "../../store/builder/store"; import { useActiveLayer, useDfxUpload } from "../../store/builder/store";
import DxfParser from "dxf-parser"; import DxfParser from "dxf-parser";
import { getWallPointsFromBlueprint } from "../../modules/builder/dfx/functions/getWallPointsFromBlueprint"; import { getWallPointsFromBlueprint } from "../../modules/builder/dfx/functions/getWallPointsFromBlueprint";
import { convertDXFToThree } from "../../modules/builder/dfx/functions/convertDxfToThree"; import { convertDXFToThree } from "../../modules/builder/dfx/functions/convertDxfToThree";
import { AIIcon } from "../icons/ExportCommonIcons"; import { AIIcon } from "../icons/ExportCommonIcons";
import { useBuilderStore } from "../../store/builder/useBuilderStore";
import { useSceneContext } from "../../modules/scene/sceneContext";
type DXFData = any; type DXFData = any;
const SelectFloorPlan: React.FC = () => { const SelectFloorPlan: React.FC = () => {
// Access layout state and state setters // Access layout state and state setters
@@ -12,10 +14,13 @@ const SelectFloorPlan: React.FC = () => {
// Access DXF-related states and setters // Access DXF-related states and setters
const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } = const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } =
useDfxUpload(); useDfxUpload();
const { activeLayer } = useActiveLayer();
const { wallThickness, wallHeight, insideMaterial, outsideMaterial } = useBuilderStore();
const { wallStore } = useSceneContext();
const { addWall } = wallStore();
// Local state to store the parsed DXF file // Local state to store the parsed DXF file
const [parsedFile, setParsedFile] = useState<DXFData | undefined>(undefined); const [parsedFile, setParsedFile] = useState<DXFData | undefined>(undefined);
const { walls } = wallStore();
// Flag to trigger generation after file upload // Flag to trigger generation after file upload
const [generate, setGenerate] = useState<boolean>(false); const [generate, setGenerate] = useState<boolean>(false);
@@ -60,6 +65,7 @@ const SelectFloorPlan: React.FC = () => {
parsedData: parsedFile, parsedData: parsedFile,
setDfxGenerate, setDfxGenerate,
objValue, objValue,
wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls
}); });
} }
}, [generate]); }, [generate]);

View File

@@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store'; import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store';
import { LineBasicMaterial, Line } from 'three'; import { LineBasicMaterial, Line } from 'three';
import { TransformControls } from '@react-three/drei'; import { TransformControls } from '@react-three/drei';
import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint'; import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
@@ -7,6 +7,8 @@ import * as Types from '../../../types/world/worldTypes';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { getUserData } from '../../../functions/getUserData'; import { getUserData } from '../../../functions/getUserData';
import { useVersionContext } from '../version/versionContext'; import { useVersionContext } from '../version/versionContext';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useSceneContext } from '../../scene/sceneContext';
/** /**
* DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene. * DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene.
@@ -22,41 +24,37 @@ const DxfFile = () => {
const { selectedVersion } = selectedVersionStore(); const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams(); const { projectId } = useParams();
const { userId, organization } = getUserData(); const { userId, organization } = getUserData();
const { activeLayer } = useActiveLayer();
const { wallThickness, wallHeight, insideMaterial, outsideMaterial, } = useBuilderStore();
// Refs for storing line objects // Refs for storing line objects
const lineRefs = useRef<Line[]>([]); const lineRefs = useRef<Line[]>([]);
const { wallStore } = useSceneContext();
const { addWall, } = wallStore();
const { walls } = wallStore();
/** /**
* Effect hook that runs when DXF wall generation is triggered. * Effect hook that runs when DXF wall generation is triggered.
* Loads initial points and lines from the DXF data and updates the scene. * Loads initial points and lines from the DXF data and updates the scene.
*/ */
useEffect(() => { useEffect(() => {
if (dfxWallGenerate) { if (dfxWallGenerate) {
// Store generated lines in ref dfxWallGenerate.map((wall: Wall) => {
// lines.current.push(...dfxWallGenerate); const data = {
// dfxWallGenerate.map((line: any) => { wallData: wall,
// const lineData = arrayLineToObject(line as Types.Line); projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
addWall(wall);
socket.emit('v1:model-Wall:add', data);
// API
// //REST // if (projectId) {
// upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
// // setLine(organization, lineData.layer!, lineData.line!, lineData.type!); // }
})
// //SOCKET
// const input = {
// organization,
// layer: lineData.layer,
// line: lineData.line,
// type: lineData.type,
// socketId: socket.id,
// versionId: selectedVersion?.versionId || '',
// projectId,
// userId
// }
// socket.emit('v1:Line:create', input);
// })
} }
}, [dfxWallGenerate]); }, [dfxWallGenerate]);
@@ -79,6 +77,7 @@ const DxfFile = () => {
getWallPointsFromBlueprint({ getWallPointsFromBlueprint({
objValue: { x: position.x, y: position.y, z: position.z }, objValue: { x: position.x, y: position.y, z: position.z },
setDfxGenerate: () => { }, setDfxGenerate: () => { },
wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls
}); });
}; };

View File

@@ -1,11 +1,21 @@
import { MathUtils, Vector3, BufferGeometry } from "three"; import { MathUtils, Vector3, BufferGeometry } from "three";
import { useActiveLayer } from "../../../../store/builder/store";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { wait } from "@testing-library/user-event/dist/utils";
type DXFData = any; // Replace with actual DXF data type type DXFData = any; // Replace with actual DXF data type
type DXFEntity = any; // Replace with actual DXF entity type type DXFEntity = any; // Replace with actual DXF entity type
type WallLineVertex = [Vector3, string, number, string]; // Represents a wall segment with start point, ID, weight, and type type WallLineVertex = [Vector3, string, number, string]; // Represents a wall segment with start point, ID, weight, and type
interface Props { interface Props {
parsedData?: DXFData; // Parsed DXF file data parsedData?: DXFData; // Parsed DXF file data
setDfxGenerate?: (walls: WallLineVertex[][]) => void; // Callback to set generated walls setDfxGenerate?: any; // Callback to set generated walls
objValue: any; // Object position values for offset calculation objValue: any; // Object position values for offset calculation
wallThickness: number;
wallHeight: number;
outsideMaterial: string;
insideMaterial: string;
activeLayer: number; // Active layer for wall points
addWall: (wall: Wall) => void; // Function to add a wall to the scene
walls: Wall[]; // Array of walls to be processed
} }
/** /**
@@ -22,14 +32,20 @@ export function getWallPointsFromBlueprint({
parsedData, parsedData,
setDfxGenerate, setDfxGenerate,
objValue, objValue,
wallThickness,
wallHeight,
outsideMaterial,
insideMaterial,
activeLayer,
addWall,
walls,
}: Props) { }: Props) {
// Early return if no data is provided // Early return if no data is provided
if (!parsedData) return; if (!parsedData) return;
if (!parsedData.entities) return; if (!parsedData.entities) return;
const unit = 1000; // Conversion factor from millimeters to meters const unit = 1000; // Conversion factor from millimeters to meters
const wallVertex: WallLineVertex[][] = []; // Stores all generated wall segments const wallVertex: any[] = []; // Array to store wall vertices
// Process each entity in the DXF file // Process each entity in the DXF file
parsedData.entities.forEach((entity: DXFEntity) => { parsedData.entities.forEach((entity: DXFEntity) => {
// Handle LINE entities // Handle LINE entities
@@ -47,31 +63,39 @@ export function getWallPointsFromBlueprint({
-entity.vertices[1].y / unit -entity.vertices[1].y / unit
).add(new Vector3(objValue.x, 0, objValue.z)); ).add(new Vector3(objValue.x, 0, objValue.z));
// Check if points already exist to avoid duplicates // Create start and end points
const existingStart = wallVertex const startPoint: Point = {
.flat() pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points
.find((v) => v[0].equals(startVec)); pointType: "Wall", // Type identifier
const startPoint: WallLineVertex = existingStart || [ position: [startVec.x, startVec.y, startVec.z], // Position in 3D space
startVec, layer: activeLayer, // Default weight
MathUtils.generateUUID(), // Generate unique ID for new points };
1, // Default weight
"WallLine", // Type identifier
];
const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec)); const endPoint: Point = {
const endPoint: WallLineVertex = existingEnd || [ pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points
endVec, pointType: "Wall", // Type identifier
MathUtils.generateUUID(), position: [endVec.x, endVec.y, endVec.z], // Position in 3D space
1, layer: activeLayer,
"WallLine", };
];
// Add the line segment to our collection // Create the wall
wallVertex.push([startPoint, endPoint]); const wallSet: Wall = {
wallUuid: MathUtils.generateUUID(),
points: [startPoint, endPoint], // Store start and end points
outsideMaterial: insideMaterial,
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
decals: [],
};
wallVertex.push(wallSet); // Store wall segment in array
// Add the wall to the scene
// addWall(wallSet);
} }
// Handle LWPOLYLINE entities (connected line segments) // Handle LWPOLYLINE entities (connected line segments)
else if (entity.type === "LWPOLYLINE" && entity.vertices) { else if (entity.type === "LWPOLYLINE" && entity.vertices) {
let firstPoint: WallLineVertex | undefined; // Store first point for closing the polyline let firstPoint: Point | undefined; // Store first point for closing the polyline
// Process each vertex pair in the polyline // Process each vertex pair in the polyline
for (let i = 0; i < entity.vertices.length - 1; i++) { for (let i = 0; i < entity.vertices.length - 1; i++) {
@@ -88,37 +112,58 @@ export function getWallPointsFromBlueprint({
-entity.vertices[i + 1].y / unit -entity.vertices[i + 1].y / unit
).add(new Vector3(objValue.x, 0, objValue.z)); ).add(new Vector3(objValue.x, 0, objValue.z));
// Check for existing points // Create start and end points
const existingStart = wallVertex const startPoint: Point = {
.flat() pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points
.find((v) => v[0].equals(startVec)); pointType: "Wall", // Type identifier
const startPoint: WallLineVertex = existingStart || [ position: [startVec.x, startVec.y, startVec.z], // Position in 3D space
startVec, layer: activeLayer,
MathUtils.generateUUID(), };
1,
"WallLine",
];
const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec)); const endPoint: Point = {
const endPoint: WallLineVertex = existingEnd || [ pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points
endVec, pointType: "Wall", // Type identifier
MathUtils.generateUUID(), position: [endVec.x, endVec.y, endVec.z], // Position in 3D space
1, layer: activeLayer,
"WallLine", };
];
wallVertex.push([startPoint, endPoint]); // Create the wall segment
const wallSet: Wall = {
wallUuid: MathUtils.generateUUID(),
points: [startPoint, endPoint], // Store start and end points
outsideMaterial: insideMaterial,
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
decals: [],
};
// Add the wall segment
// addWall(wallSet);
wallVertex.push(wallSet);
// Store first point and create closing segment if this is the last vertex // Store first point and create closing segment if this is the last vertex
if (i === 0) firstPoint = startPoint; if (i === 0) firstPoint = startPoint;
if (i === entity.vertices.length - 2 && firstPoint) { if (i === entity.vertices.length - 2 && firstPoint) {
wallVertex.push([endPoint, firstPoint]); const closingWallSet: Wall = {
wallUuid: MathUtils.generateUUID(),
points: [endPoint, firstPoint], // Create closing segment
outsideMaterial: insideMaterial,
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
decals: [],
};
// Add the closing wall
wallVertex.push(closingWallSet);
// addWall(closingWallSet);
} }
} }
} }
// Handle ARC entities // Handle ARC entities
else if (entity.type === "ARC") { else if (entity.type === "ARC") {
const { center, radius, startAngle, endAngle } = entity; const { center, radius, startAngle, endAngle } = entity;
// Validate required ARC properties // Validate required ARC properties
if ( if (
!center || !center ||
@@ -154,28 +199,38 @@ export function getWallPointsFromBlueprint({
const startVec = arcPoints[i]; const startVec = arcPoints[i];
const endVec = arcPoints[i + 1]; const endVec = arcPoints[i + 1];
// Check for existing points // Create start and end points
const existingStart = wallVertex const startPoint: Point = {
.flat() pointUuid: MathUtils.generateUUID(),
.find((v) => v[0].equals(startVec)); pointType: "Wall",
const startPoint: WallLineVertex = existingStart || [ position: [startVec.x, startVec.y, startVec.z],
startVec, layer: activeLayer,
MathUtils.generateUUID(), };
1,
"WallLine",
];
const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec)); const endPoint: Point = {
const endPoint: WallLineVertex = existingEnd || [ pointUuid: MathUtils.generateUUID(),
endVec, pointType: "Wall",
MathUtils.generateUUID(), position: [endVec.x, endVec.y, endVec.z],
1, layer: activeLayer,
"WallLine", };
];
wallVertex.push([startPoint, endPoint]); // Create the wall segment
const wallSet: Wall = {
wallUuid: MathUtils.generateUUID(),
points: [startPoint, endPoint],
outsideMaterial: insideMaterial,
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
decals: [],
};
// Add the wall segment
// addWall(wallSet);
wallVertex.push(wallSet);
} }
} }
// Log unsupported entity types // Log unsupported entity types
else { else {
console.error("Unsupported entity type:", entity.type); console.error("Unsupported entity type:", entity.type);

View File

@@ -71,6 +71,7 @@ function WallCreator() {
if (wallIntersect && !pointIntersects) { if (wallIntersect && !pointIntersects) {
const wall = getWallByPoints(wallIntersect.object.userData.points); const wall = getWallByPoints(wallIntersect.object.userData.points);
console.log('wall: ', wall);
if (wall) { if (wall) {
const ThroughPoint = wallIntersect.object.userData.path.getPoints(Constants.lineConfig.lineIntersectionPoints); const ThroughPoint = wallIntersect.object.userData.path.getPoints(Constants.lineConfig.lineIntersectionPoints);
let intersectionPoint = getClosestIntersection(ThroughPoint, wallIntersect.point); let intersectionPoint = getClosestIntersection(ThroughPoint, wallIntersect.point);
@@ -294,7 +295,9 @@ function WallCreator() {
position: [position.x, position.y, position.z], position: [position.x, position.y, position.z],
layer: activeLayer layer: activeLayer
}; };
console.log('newPoint: ', newPoint);
console.log('snappedPoint: ', snappedPoint);
if (snappedPosition && snappedPoint) { if (snappedPosition && snappedPoint) {
newPoint.pointUuid = snappedPoint.pointUuid; newPoint.pointUuid = snappedPoint.pointUuid;
newPoint.position = snappedPosition; newPoint.position = snappedPosition;
@@ -316,6 +319,7 @@ function WallCreator() {
} }
} }
console.log('tempPoints: ', tempPoints);
if (tempPoints.length === 0) { if (tempPoints.length === 0) {
setTempPoints([newPoint]); setTempPoints([newPoint]);
setIsCreating(true); setIsCreating(true);
@@ -330,6 +334,7 @@ function WallCreator() {
decals: [] decals: []
}; };
addWall(wall); addWall(wall);
console.log('wall: ', wall);
// API // API

View File

@@ -12,13 +12,12 @@ interface PolygonGeneratorProps {
export default function PolygonGenerator({ export default function PolygonGenerator({
groupRef, groupRef,
}: PolygonGeneratorProps) { }: PolygonGeneratorProps) {
const { aisleStore } = useSceneContext(); const { aisleStore, wallStore } = useSceneContext();
const { aisles } = aisleStore(); const { aisles } = aisleStore();
const { scene } = useThree(); const { scene } = useThree();
const { walls } = wallStore();
useEffect(() => { useEffect(() => {
// let allLines = arrayLinesToObject(lines.current);
// const wallLines = allLines?.filter((line) => line?.type === "WallLine");
const result = aisles const result = aisles
.filter( .filter(
(aisle) => (aisle) =>
@@ -61,9 +60,12 @@ export default function PolygonGenerator({
}); });
}); });
// const wallPoints = wallLines
// .map((pair) => pair?.line.map((vals) => vals.position)) const wallPoints: THREE.Vector3[][] = walls
// .filter((wall): wall is THREE.Vector3[] => !!wall); .map((wall) =>
wall.points.map((pt) => new THREE.Vector3(pt.position[0], pt.position[1], pt.position[2]))
)
.filter(points => points.length === 2);
if (!result || result.some((line) => !line)) { if (!result || result.some((line) => !line)) {
@@ -81,7 +83,7 @@ export default function PolygonGenerator({
const polygons = turf.polygonize(turf.featureCollection(validLineFeatures)); const polygons = turf.polygonize(turf.featureCollection(validLineFeatures));
// renderWallGeometry(wallPoints); renderWallGeometry(wallPoints);
if (polygons.features.length > 0) { if (polygons.features.length > 0) {
polygons.features.forEach((feature) => { polygons.features.forEach((feature) => {
@@ -116,7 +118,7 @@ export default function PolygonGenerator({
}); });
} }
}, [ aisles, scene]); }, [aisles, scene, walls]);
const renderWallGeometry = (walls: THREE.Vector3[][]) => { const renderWallGeometry = (walls: THREE.Vector3[][]) => {
walls.forEach((wall) => { walls.forEach((wall) => {

View File

@@ -1,10 +1,14 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import useModuleStore, { useSubModuleStore, useThreeDStore } from "../../store/useModuleStore"; import useModuleStore, {
useSubModuleStore,
useThreeDStore,
} from "../../store/useModuleStore";
import { usePlayerStore, useToggleStore } from "../../store/useUIToggleStore"; import { usePlayerStore, useToggleStore } from "../../store/useUIToggleStore";
import useVersionHistoryVisibleStore, { import useVersionHistoryVisibleStore, {
useActiveSubTool, useActiveSubTool,
useActiveTool, useActiveTool,
useAddAction, useAddAction,
useDfxUpload,
useRenameModeStore, useRenameModeStore,
useSaveVersion, useSaveVersion,
useSelectedComment, useSelectedComment,
@@ -49,7 +53,7 @@ const KeyPressListener: React.FC = () => {
const { setCreateNewVersion } = useVersionHistoryStore(); const { setCreateNewVersion } = useVersionHistoryStore();
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore(); const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
const { setSelectedComment } = useSelectedComment(); const { setSelectedComment } = useSelectedComment();
const { setDfxUploaded, setDfxGenerate } = useDfxUpload();
const isTextInput = (element: Element | null): boolean => const isTextInput = (element: Element | null): boolean =>
element instanceof HTMLInputElement || element instanceof HTMLInputElement ||
element instanceof HTMLTextAreaElement || element instanceof HTMLTextAreaElement ||
@@ -160,14 +164,14 @@ const KeyPressListener: React.FC = () => {
setCreateNewVersion(true); setCreateNewVersion(true);
setVersionHistoryVisible(true); setVersionHistoryVisible(true);
setSubModule("properties"); setSubModule("properties");
setActiveModule('builder'); setActiveModule("builder");
break; break;
case "Ctrl+H": case "Ctrl+H":
if (!isPlaying) { if (!isPlaying) {
setVersionHistoryVisible(true); setVersionHistoryVisible(true);
setSubModule("properties"); setSubModule("properties");
setActiveModule('builder'); setActiveModule("builder");
} }
break; break;
@@ -195,6 +199,7 @@ const KeyPressListener: React.FC = () => {
clearComparisonProduct(); clearComparisonProduct();
setIsLogListVisible(false); setIsLogListVisible(false);
setIsRenameMode(false); setIsRenameMode(false);
setDfxUploaded([]);
setSelectedComment(null); setSelectedComment(null);
} }