Update Generated DXF Walls to backend
This commit is contained in:
parent
a2af3b445d
commit
3d5159f1b6
|
@ -2,20 +2,25 @@ 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 { useDfxUpload } from "../../store/builder/store";
|
||||||
import DxfParser from "dxf-parser";
|
import DxfParser from "dxf-parser";
|
||||||
import { Box3, BufferGeometry, MathUtils, Vector3 } from "three";
|
|
||||||
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";
|
||||||
// Define types for DXF entities and geometries
|
|
||||||
|
|
||||||
|
|
||||||
const SelectFloorPlan: React.FC = () => {
|
const SelectFloorPlan: React.FC = () => {
|
||||||
|
// Access layout state and state setters
|
||||||
const { currentLayout, setLayout } = useLayoutStore();
|
const { currentLayout, setLayout } = useLayoutStore();
|
||||||
const { setDfxUploaded, setDfxGenerate } = useDfxUpload();
|
// Access DXF-related states and setters
|
||||||
|
const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } = useDfxUpload();
|
||||||
|
|
||||||
const [parsedFile, setParsedFile] = useState<DXFData>();
|
// Local state to store the parsed DXF file
|
||||||
|
const [parsedFile, setParsedFile] = useState<DXFData | undefined>(undefined);
|
||||||
|
|
||||||
|
// Flag to trigger generation after file upload
|
||||||
const [generate, setGenerate] = useState<boolean>(false);
|
const [generate, setGenerate] = useState<boolean>(false);
|
||||||
|
|
||||||
|
// Handles file upload and DXF parsing
|
||||||
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setLayout(null); // Reset current layout
|
||||||
|
setParsedFile(undefined); // Clear any previously parsed file
|
||||||
const file = event.target.files?.[0];
|
const file = event.target.files?.[0];
|
||||||
if (!file || !file.name.endsWith(".dxf")) {
|
if (!file || !file.name.endsWith(".dxf")) {
|
||||||
alert("Please upload a valid .dxf file.");
|
alert("Please upload a valid .dxf file.");
|
||||||
|
@ -23,47 +28,60 @@ const SelectFloorPlan: React.FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
reader.onload = async (e) => {
|
reader.onload = async (e) => {
|
||||||
const dxfContent = e.target?.result as string;
|
const dxfContent = e.target?.result as string;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parser = new DxfParser();
|
const parser = new DxfParser();
|
||||||
const parsedData = parser.parse(dxfContent) as DXFData;
|
const parsedDatas = parser.parse(dxfContent) as DXFData;
|
||||||
const geometries = convertDXFToThree(parsedData);
|
const geometries = convertDXFToThree(parsedDatas);
|
||||||
|
setParsedFile(parsedDatas);
|
||||||
setParsedFile(parsedData);
|
setObjValue({ x: 0, y: 0, z: 0 });
|
||||||
setDfxUploaded(geometries);
|
setDfxUploaded(geometries);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
echo.error("Failed to import your .dxf file")
|
console.error("Failed to import your .dxf file", error);
|
||||||
|
} finally {
|
||||||
|
// ✅ Reset input AFTER processing
|
||||||
|
event.target.value = "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
reader.readAsText(file);
|
reader.readAsText(file); // Read the uploaded file as text
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Trigger wall point generation when `generate` flag changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (parsedFile !== undefined)
|
if (parsedFile !== undefined) {
|
||||||
getWallPointsFromBlueprint({ parsedData: parsedFile, setDfxGenerate })
|
getWallPointsFromBlueprint({ parsedData: parsedFile, setDfxGenerate, objValue });
|
||||||
}, [generate])
|
}
|
||||||
|
}, [generate]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("parsedFile: ", parsedFile);
|
||||||
|
}, [parsedFile]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="select-floorplane-wrapper">
|
<div className="select-floorplane-wrapper">
|
||||||
Preset Layouts
|
Preset Layouts
|
||||||
|
|
||||||
<div className="presets-container">
|
<div className="presets-container">
|
||||||
<button
|
<button
|
||||||
className={`preset ${currentLayout === "layout1" ? "active" : ""}`}
|
className={`preset ${currentLayout === "layout1" ? "active" : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setLayout("layout1");
|
setLayout("layout1");
|
||||||
|
setDfxUploaded([]);
|
||||||
|
setGenerate(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Preset 1
|
Preset 1
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={`preset ${currentLayout === "layout2" ? "active" : ""}`}
|
className={`preset ${currentLayout === "layout2" ? "active" : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setLayout("layout2");
|
setLayout("layout2");
|
||||||
|
setDfxUploaded([]);
|
||||||
|
setGenerate(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Preset 2
|
Preset 2
|
||||||
|
@ -76,6 +94,7 @@ const SelectFloorPlan: React.FC = () => {
|
||||||
style={{ display: "none", width: "10px" }}
|
style={{ display: "none", width: "10px" }}
|
||||||
onChange={handleFileUpload}
|
onChange={handleFileUpload}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
htmlFor="file-upload"
|
htmlFor="file-upload"
|
||||||
className="preset"
|
className="preset"
|
||||||
|
@ -86,24 +105,21 @@ const SelectFloorPlan: React.FC = () => {
|
||||||
>
|
>
|
||||||
Upload
|
Upload
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
id="generate-upload"
|
id="generate-upload"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDfxUploaded([])
|
setDfxUploaded([]);
|
||||||
|
setLayout(null);
|
||||||
setGenerate(!generate);
|
setGenerate(!generate);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Generate
|
Generate
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div >
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SelectFloorPlan;
|
export default SelectFloorPlan;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -314,7 +314,13 @@ export default function Builder() {
|
||||||
<CalculateAreaGroup />
|
<CalculateAreaGroup />
|
||||||
<NavMesh lines={lines} />
|
<NavMesh lines={lines} />
|
||||||
|
|
||||||
<DxfFile lines={lines} dragPointControls={dragPointControls} currentLayerPoint={currentLayerPoint} floorPlanGroupLine={floorPlanGroupLine} floorPlanGroupPoint={floorPlanGroupPoint} setUpdateScene={setUpdateScene} />
|
<DxfFile
|
||||||
|
lines={lines}
|
||||||
|
dragPointControls={dragPointControls}
|
||||||
|
currentLayerPoint={currentLayerPoint}
|
||||||
|
floorPlanGroupLine={floorPlanGroupLine}
|
||||||
|
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||||
|
/>
|
||||||
|
|
||||||
<LayoutImage />
|
<LayoutImage />
|
||||||
</Bvh>
|
</Bvh>
|
||||||
|
|
|
@ -1,38 +1,145 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { useDfxUpload, useToggleView } from '../../../store/builder/store';
|
import { useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store';
|
||||||
import { LineBasicMaterial, Line } from "three";
|
import { LineBasicMaterial, Line } from 'three';
|
||||||
import loadInitialPoint from '../IntialLoad/loadInitialPoint';
|
import loadInitialPoint from '../IntialLoad/loadInitialPoint';
|
||||||
import loadInitialLine from '../IntialLoad/loadInitialLine';
|
import loadInitialLine from '../IntialLoad/loadInitialLine';
|
||||||
import { TransformControls } from '@react-three/drei';
|
import { TransformControls } from '@react-three/drei';
|
||||||
|
import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
|
||||||
|
import * as Types from '../../../types/world/worldTypes';
|
||||||
|
import arrayLineToObject from '../geomentries/lines/lineConvertions/arrayLineToObject';
|
||||||
|
|
||||||
const DxfFile = ({ floorPlanGroupPoint, currentLayerPoint, dragPointControls, floorPlanGroupLine, lines, setUpdateScene }: any) => {
|
// Interface defining the props for the DxfFile component
|
||||||
const { dfxuploaded, dfxWallGenerate } = useDfxUpload();
|
interface DxfFileProps {
|
||||||
|
lines: Types.RefLines; // Reference to lines in the DXF file
|
||||||
|
floorPlanGroupPoint: Types.RefGroup; // Reference to floor plan points group
|
||||||
|
dragPointControls: Types.RefDragControl; // Reference to drag controls
|
||||||
|
floorPlanGroupLine: Types.RefGroup; // Reference to floor plan lines group
|
||||||
|
currentLayerPoint: Types.RefMeshArray; // Reference to current layer points
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene.
|
||||||
|
* It processes the DXF data to create points and lines representing walls and allows
|
||||||
|
* transformation controls for interactive editing.
|
||||||
|
*/
|
||||||
|
const DxfFile = ({
|
||||||
|
floorPlanGroupPoint,
|
||||||
|
currentLayerPoint,
|
||||||
|
dragPointControls,
|
||||||
|
floorPlanGroupLine,
|
||||||
|
lines,
|
||||||
|
}: DxfFileProps) => {
|
||||||
|
// State management hooks
|
||||||
|
const { dfxuploaded, dfxWallGenerate, setObjValue, objValue } = useDfxUpload();
|
||||||
|
const { setUpdateScene } = useUpdateScene();
|
||||||
const { toggleView } = useToggleView();
|
const { toggleView } = useToggleView();
|
||||||
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
|
// Refs for storing line objects
|
||||||
|
const lineRefs = useRef<Line[]>([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Effect hook that runs when DXF wall generation is triggered.
|
||||||
|
* Loads initial points and lines from the DXF data and updates the scene.
|
||||||
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dfxWallGenerate && dragPointControls && floorPlanGroupPoint && currentLayerPoint && floorPlanGroupLine) {
|
if (
|
||||||
lines.current = dfxWallGenerate;
|
dfxWallGenerate &&
|
||||||
|
dragPointControls &&
|
||||||
|
floorPlanGroupPoint &&
|
||||||
|
currentLayerPoint &&
|
||||||
|
floorPlanGroupLine
|
||||||
|
) {
|
||||||
|
// Store generated lines in ref
|
||||||
|
lines.current.push(...dfxWallGenerate);
|
||||||
|
dfxWallGenerate.map((line: any) => {
|
||||||
|
const lineData = arrayLineToObject(line as Types.Line);
|
||||||
|
const email = localStorage.getItem('email')
|
||||||
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
|
|
||||||
|
//REST
|
||||||
|
|
||||||
|
// setLine(organization, lineData.layer!, lineData.line!, lineData.type!);
|
||||||
|
|
||||||
|
//SOCKET
|
||||||
|
|
||||||
|
const input = {
|
||||||
|
organization: organization,
|
||||||
|
layer: lineData.layer,
|
||||||
|
line: lineData.line,
|
||||||
|
type: lineData.type,
|
||||||
|
socketId: socket.id
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:Line:create', input);
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// Load initial points and lines from DXF data
|
||||||
loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls);
|
loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls);
|
||||||
loadInitialLine(floorPlanGroupLine, lines);
|
loadInitialLine(floorPlanGroupLine, lines);
|
||||||
|
|
||||||
|
// Trigger scene update
|
||||||
setUpdateScene(true);
|
setUpdateScene(true);
|
||||||
}
|
}
|
||||||
}, [lines, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls, dfxWallGenerate])
|
}, [
|
||||||
|
lines,
|
||||||
|
floorPlanGroupLine,
|
||||||
|
floorPlanGroupPoint,
|
||||||
|
currentLayerPoint,
|
||||||
|
dragPointControls,
|
||||||
|
dfxWallGenerate,
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles transformation changes for individual lines.
|
||||||
|
* Updates the object value state with new position and recalculates wall points.
|
||||||
|
* @param index - Index of the line being transformed
|
||||||
|
*/
|
||||||
|
const handleTransformChange = (index: number) => {
|
||||||
|
const line = lineRefs.current[index];
|
||||||
|
if (!line) return;
|
||||||
|
|
||||||
|
// Get current position of the line
|
||||||
|
const position = line.position;
|
||||||
|
|
||||||
|
// Update state with new position
|
||||||
|
setObjValue({ x: position.x, y: position.y, z: position.z });
|
||||||
|
|
||||||
|
// Recalculate wall points based on new position
|
||||||
|
getWallPointsFromBlueprint({
|
||||||
|
objValue: { x: position.x, y: position.y, z: position.z },
|
||||||
|
setDfxGenerate: () => { },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{dfxuploaded && dfxuploaded.length > 0 && toggleView && dfxuploaded?.map((geometry: any, index: any) => (
|
{/* Render DXF lines with transform controls when DXF data is available and view is toggled */}
|
||||||
<TransformControls>
|
{dfxuploaded &&
|
||||||
<group>
|
dfxuploaded.length > 0 &&
|
||||||
<primitive
|
toggleView &&
|
||||||
|
dfxuploaded?.map((geometry: any, index: number) => {
|
||||||
|
// Create a new line object for each geometry in the DXF data
|
||||||
|
const line = new Line(geometry, new LineBasicMaterial({ color: 'red' }));
|
||||||
|
line.rotation.set(-Math.PI / 2, 0, 0);
|
||||||
|
|
||||||
|
// Store line reference
|
||||||
|
lineRefs.current[index] = line;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TransformControls
|
||||||
key={index}
|
key={index}
|
||||||
object={new Line(geometry, new LineBasicMaterial({ color: 'red' }))}
|
object={line}
|
||||||
rotation={[-Math.PI / 2, 0, 0]}
|
onMouseUp={() => handleTransformChange(index)}
|
||||||
/>
|
>
|
||||||
</group>
|
{/* Render the line with current position from state */}
|
||||||
|
<primitive object={line} position={[objValue.x, objValue.y, objValue.z]} />
|
||||||
</TransformControls>
|
</TransformControls>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default DxfFile;
|
export default DxfFile;
|
|
@ -1,41 +1,59 @@
|
||||||
import { MathUtils, Vector3, BufferGeometry } from "three";
|
import { MathUtils, Vector3, BufferGeometry } from "three";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
parsedData: DXFData;
|
parsedData?: DXFData; // Parsed DXF file data
|
||||||
setDfxGenerate: (walls: WallLineVertex[][]) => void;
|
setDfxGenerate?: (walls: WallLineVertex[][]) => void; // Callback to set generated walls
|
||||||
|
objValue: any; // Object position values for offset calculation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes DXF entities to generate wall points for a blueprint.
|
||||||
|
* Handles LINE, LWPOLYLINE, and ARC entity types, converting them to wall segments.
|
||||||
|
* Applies unit conversion and positional offsets to all points.
|
||||||
|
*
|
||||||
|
* @param {Props} params - Configuration parameters
|
||||||
|
* @param {DXFData} params.parsedData - Parsed DXF file data
|
||||||
|
* @param {Function} params.setDfxGenerate - Callback to store generated walls
|
||||||
|
* @param {Object} params.objValue - Contains x,y,z offsets for position adjustment
|
||||||
|
*/
|
||||||
export function getWallPointsFromBlueprint({
|
export function getWallPointsFromBlueprint({
|
||||||
parsedData,
|
parsedData,
|
||||||
setDfxGenerate,
|
setDfxGenerate,
|
||||||
|
objValue,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
// Early return if no data is provided
|
||||||
|
if (!parsedData) return;
|
||||||
if (!parsedData.entities) return;
|
if (!parsedData.entities) return;
|
||||||
|
|
||||||
const unit = 1000; // Convert mm to meters
|
const unit = 1000; // Conversion factor from millimeters to meters
|
||||||
|
const wallVertex: WallLineVertex[][] = []; // Stores all generated wall segments
|
||||||
const wallVertex: WallLineVertex[][] = [];
|
|
||||||
|
|
||||||
|
// Process each entity in the DXF file
|
||||||
parsedData.entities.forEach((entity: DXFEntity) => {
|
parsedData.entities.forEach((entity: DXFEntity) => {
|
||||||
|
// Handle LINE entities
|
||||||
if (entity.type === "LINE" && entity.vertices) {
|
if (entity.type === "LINE" && entity.vertices) {
|
||||||
|
// Create start and end vectors with unit conversion and position offset
|
||||||
const startVec = new Vector3(
|
const startVec = new Vector3(
|
||||||
entity.vertices[0].x / unit,
|
entity.vertices[0].x / unit,
|
||||||
0.01,
|
0.01, // Slightly above ground to avoid z-fighting
|
||||||
-entity.vertices[0].y / unit
|
-entity.vertices[0].y / unit // Invert Y-axis to match Three.js coordinate system
|
||||||
);
|
).add(new Vector3(objValue.x, 0, objValue.z));
|
||||||
|
|
||||||
const endVec = new Vector3(
|
const endVec = new Vector3(
|
||||||
entity.vertices[1].x / unit,
|
entity.vertices[1].x / unit,
|
||||||
0.01,
|
0.01,
|
||||||
-entity.vertices[1].y / unit
|
-entity.vertices[1].y / unit
|
||||||
);
|
).add(new Vector3(objValue.x, 0, objValue.z));
|
||||||
|
|
||||||
|
// Check if points already exist to avoid duplicates
|
||||||
const existingStart = wallVertex
|
const existingStart = wallVertex
|
||||||
.flat()
|
.flat()
|
||||||
.find((v) => v[0].equals(startVec));
|
.find((v) => v[0].equals(startVec));
|
||||||
const startPoint: WallLineVertex = existingStart || [
|
const startPoint: WallLineVertex = existingStart || [
|
||||||
startVec,
|
startVec,
|
||||||
MathUtils.generateUUID(),
|
MathUtils.generateUUID(), // Generate unique ID for new points
|
||||||
1,
|
1, // Default weight
|
||||||
"WallLine",
|
"WallLine", // Type identifier
|
||||||
];
|
];
|
||||||
|
|
||||||
const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec));
|
const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec));
|
||||||
|
@ -46,22 +64,29 @@ export function getWallPointsFromBlueprint({
|
||||||
"WallLine",
|
"WallLine",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Add the line segment to our collection
|
||||||
wallVertex.push([startPoint, endPoint]);
|
wallVertex.push([startPoint, endPoint]);
|
||||||
} else if (entity.type === "LWPOLYLINE" && entity.vertices) {
|
}
|
||||||
let firstPoint: WallLineVertex | undefined;
|
// Handle LWPOLYLINE entities (connected line segments)
|
||||||
|
else if (entity.type === "LWPOLYLINE" && entity.vertices) {
|
||||||
|
let firstPoint: WallLineVertex | undefined; // Store first point for closing 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++) {
|
||||||
|
// Convert vertices to Three.js vectors with offset
|
||||||
const startVec = new Vector3(
|
const startVec = new Vector3(
|
||||||
entity.vertices[i].x / unit,
|
entity.vertices[i].x / unit,
|
||||||
0.01,
|
0.01,
|
||||||
-entity.vertices[i].y / unit
|
-entity.vertices[i].y / unit
|
||||||
);
|
).add(new Vector3(objValue.x, 0, objValue.z));
|
||||||
|
|
||||||
const endVec = new Vector3(
|
const endVec = new Vector3(
|
||||||
entity.vertices[i + 1].x / unit,
|
entity.vertices[i + 1].x / unit,
|
||||||
0.01,
|
0.01,
|
||||||
-entity.vertices[i + 1].y / unit
|
-entity.vertices[i + 1].y / unit
|
||||||
);
|
).add(new Vector3(objValue.x, 0, objValue.z));
|
||||||
|
|
||||||
|
// Check for existing points
|
||||||
const existingStart = wallVertex
|
const existingStart = wallVertex
|
||||||
.flat()
|
.flat()
|
||||||
.find((v) => v[0].equals(startVec));
|
.find((v) => v[0].equals(startVec));
|
||||||
|
@ -82,36 +107,52 @@ export function getWallPointsFromBlueprint({
|
||||||
|
|
||||||
wallVertex.push([startPoint, endPoint]);
|
wallVertex.push([startPoint, endPoint]);
|
||||||
|
|
||||||
|
// 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]);
|
wallVertex.push([endPoint, firstPoint]);
|
||||||
}
|
}
|
||||||
} else if (entity.type === "ARC") {
|
}
|
||||||
|
}
|
||||||
|
// Handle ARC entities
|
||||||
|
else if (entity.type === "ARC") {
|
||||||
const { center, radius, startAngle, endAngle } = entity;
|
const { center, radius, startAngle, endAngle } = entity;
|
||||||
|
// Validate required ARC properties
|
||||||
if (
|
if (
|
||||||
!center ||
|
!center ||
|
||||||
radius === undefined ||
|
radius === undefined ||
|
||||||
startAngle === undefined ||
|
startAngle === undefined ||
|
||||||
endAngle === undefined
|
endAngle === undefined
|
||||||
)
|
) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const numSegments = 16;
|
|
||||||
const angleStep = (endAngle - startAngle) / numSegments;
|
|
||||||
|
|
||||||
const arcPoints: Vector3[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i <= numSegments; i++) {
|
|
||||||
const angle = startAngle + i * angleStep;
|
|
||||||
const x = center.x + radius * Math.cos(angle);
|
|
||||||
const y = -center.y + radius * Math.sin(angle);
|
|
||||||
arcPoints.push(new Vector3(x / unit, 0.01, y / unit));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert ARC to series of line segments
|
||||||
|
const numSegments = 16; // Number of segments to approximate the arc
|
||||||
|
const angleStep = (endAngle - startAngle) / numSegments;
|
||||||
|
const arcPoints: Vector3[] = []; // Stores points along the arc
|
||||||
|
|
||||||
|
// Generate points along the arc
|
||||||
|
for (let i = 0; i <= numSegments; i++) {
|
||||||
|
const angle = startAngle + i * angleStep;
|
||||||
|
// Calculate arc point in DXF coordinate system
|
||||||
|
const x = center.x + radius * Math.cos(angle);
|
||||||
|
const y = -center.y + radius * Math.sin(angle); // Invert Y-axis
|
||||||
|
|
||||||
|
// Convert to Three.js vector with offset
|
||||||
|
const vec = new Vector3(x / unit, 0.01, y / unit).add(
|
||||||
|
new Vector3(objValue.x, 0, objValue.z)
|
||||||
|
);
|
||||||
|
|
||||||
|
arcPoints.push(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create line segments between arc points
|
||||||
for (let i = 0; i < arcPoints.length - 1; i++) {
|
for (let i = 0; i < arcPoints.length - 1; i++) {
|
||||||
const startVec = arcPoints[i];
|
const startVec = arcPoints[i];
|
||||||
const endVec = arcPoints[i + 1];
|
const endVec = arcPoints[i + 1];
|
||||||
|
|
||||||
|
// Check for existing points
|
||||||
const existingStart = wallVertex
|
const existingStart = wallVertex
|
||||||
.flat()
|
.flat()
|
||||||
.find((v) => v[0].equals(startVec));
|
.find((v) => v[0].equals(startVec));
|
||||||
|
@ -132,10 +173,13 @@ export function getWallPointsFromBlueprint({
|
||||||
|
|
||||||
wallVertex.push([startPoint, endPoint]);
|
wallVertex.push([startPoint, endPoint]);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
// Log unsupported entity types
|
||||||
|
else {
|
||||||
console.error("Unsupported entity type:", entity.type);
|
console.error("Unsupported entity type:", entity.type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setDfxGenerate(wallVertex);
|
// Return the generated walls through callback if provided
|
||||||
|
setDfxGenerate && setDfxGenerate(wallVertex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,8 +494,10 @@ export const useProcessBar = create<any>((set: any) => ({
|
||||||
export const useDfxUpload = create<any>((set: any) => ({
|
export const useDfxUpload = create<any>((set: any) => ({
|
||||||
dfxuploaded: [],
|
dfxuploaded: [],
|
||||||
dfxWallGenerate: [],
|
dfxWallGenerate: [],
|
||||||
|
objValue: { x: 0, y: 0, z: 0 },
|
||||||
setDfxUploaded: (x: any) => set({ dfxuploaded: x }),
|
setDfxUploaded: (x: any) => set({ dfxuploaded: x }),
|
||||||
setDfxGenerate: (x: any) => set({ dfxWallGenerate: x }),
|
setDfxGenerate: (x: any) => set({ dfxWallGenerate: x }),
|
||||||
|
setObjValue: (x: any) => set({ objValue: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
type InputValuesStore = {
|
type InputValuesStore = {
|
||||||
|
@ -551,7 +553,7 @@ interface CompareStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCompareStore = create<CompareStore>((set) => ({
|
export const useCompareStore = create<CompareStore>((set) => ({
|
||||||
comparePopUp: false,
|
comparePopUp: true,
|
||||||
setComparePopUp: (value) => set({ comparePopUp: value }),
|
setComparePopUp: (value) => set({ comparePopUp: value }),
|
||||||
toggleComparePopUp: () =>
|
toggleComparePopUp: () =>
|
||||||
set((state) => ({ comparePopUp: !state.comparePopUp })),
|
set((state) => ({ comparePopUp: !state.comparePopUp })),
|
||||||
|
|
Loading…
Reference in New Issue