diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 68bb0a49..1b2069d4 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -39,7 +39,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const placementRef = { isChidori: useRef('false'), - setupLocation: useRef(null), + setupLocation: useRef('center'), isMaxSetup: useRef('false'), } diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index e5acf6da..13c48a08 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -4,6 +4,8 @@ import { forwardRef, useState } from 'react' const Placement = forwardRef((props, refs) => { const { getMessage } = useMessage() const [isChidori, setIsChidori] = useState('false') + const [setupLocation, setSetupLocation] = useState('center') + const [isMaxSetup, setIsMaxSetup] = useState('false') const moduleData = { header: [ @@ -33,6 +35,23 @@ const Placement = forwardRef((props, refs) => { refs.isChidori.current = e.target.value } + const handleSetupLocation = (e) => { + setSetupLocation(e.target.value) + refs.setupLocation.current = e.target.value + } + + const handleMaxSetup = (e) => { + console.log(e.target.checked) + + if (e.target.checked) { + setIsMaxSetup('true') + refs.isMaxSetup.current = 'true' + } else { + setIsMaxSetup('false') + refs.isMaxSetup.current = 'false' + } + } + return ( <>
@@ -128,15 +147,36 @@ const Placement = forwardRef((props, refs) => {
- +
- +
- +
@@ -145,7 +185,7 @@ const Placement = forwardRef((props, refs) => {
- +
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index eb6ac973..a44c4e19 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -20,6 +20,7 @@ export function useModuleBasicSetting() { const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState) // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useEvent() const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) + const [flowModuleLine, setFlowModuleLine] = useState({}) let selectedModuleInstSurfaceArray = [] const makeModuleInstArea = () => { @@ -55,10 +56,12 @@ export function useModuleBasicSetting() { setupSurface.setViewLengthText(false) canvas.add(setupSurface) - bottomModuleLine(setupSurface) - topModuleLine(setupSurface) - leftModuleLine(setupSurface) - // rightModuleLine(setupSurface) + + if (setupSurface.flowDirection === 'south' || setupSurface.flowDirection === 'north') { + setFlowModuleLine(bottomTopFlowLine(setupSurface)) + } else { + setFlowModuleLine(leftRightFlowLine(setupSurface)) + } //지붕면 선택 금지 roof.set({ @@ -74,7 +77,6 @@ export function useModuleBasicSetting() { //설치 범위 지정 클릭 이벤트 const toggleSelection = (setupSurface) => { - console.log('setupSurface', setupSurface) const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId) //최초 선택일때 if (!isExist) { @@ -391,6 +393,8 @@ export function useModuleBasicSetting() { //자동 모듈 설치(그리드 방식) const autoModuleSetup = (placementRef) => { const isChidori = placementRef.isChidori.current + const setupLocation = placementRef.setupLocation.current + const isMaxSetup = placementRef.isMaxSetup.current initEvent() const moduleSetupSurfaces = moduleSetupSurface //선택 설치면 @@ -434,6 +438,8 @@ export function useModuleBasicSetting() { moduleSetupSurfaces.forEach((moduleSetupSurface, index) => { moduleSetupSurface.fire('mousedown') + const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface) + let maxLengthLine = moduleSetupSurface.lines.reduce((acc, cur) => { return acc.length > cur.length ? acc : cur }) @@ -470,21 +476,11 @@ export function useModuleBasicSetting() { } else { convertBatchObject = polygonToTurfPolygon(containsBatchObjects[i]) } - - if (i === 0) { - difference = turf.difference(turf.featureCollection([turfModuleSetupSurface, convertBatchObject])) //한 면에 도머가 1개일때 - } else { - if (difference) { - difference = turf.difference(turf.featureCollection([difference, convertBatchObject])) //한면에 도머가 여러개일때 계속 제외시킴 - } - } } } - const bbox = turf.bbox(difference) - - let width = maxLengthLine.flowDirection === 'right' || maxLengthLine.flowDirection === 'left' ? 172.2 : 113.4 - let height = maxLengthLine.flowDirection === 'right' || maxLengthLine.flowDirection === 'left' ? 113.4 : 172.2 + let width = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 172.2 : 113.4 + let height = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 113.4 : 172.2 //배치면때는 방향쪽으로 패널이 넓게 누워져야함 if (moduleSetupSurface.flowDirection !== undefined) { @@ -492,144 +488,97 @@ export function useModuleBasicSetting() { height = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 113.4 : 172.2 } - let cols = Math.floor((bbox[2] - bbox[0]) / width) - let rows = Math.floor((bbox[3] - bbox[1]) / height) + let square + let startPoint, endPoint - // cols = cols * 2 + if (setupLocation === 'eaves') { + if (moduleSetupSurface.flowDirection === 'south') { + startPoint = flowModuleLine.find((obj) => obj.target === 'bottom') + endPoint = flowModuleLine.find((obj) => obj.target === 'top') + const totalHeight = endPoint.y1 - startPoint.y1 + const diffHeight = Math.abs(totalHeight / height) + let leftMargin = 0 + let bottomMargin = 0 - for (let col = 0; col <= cols; col++) { - for (let row = 0; row <= rows; row++) { - let x = 0, - y = 0, - square = [], - margin = 0 - if (moduleSetupSurface.flowDirection !== undefined) { - //배치면 처림 방향이 정해져있는 경우 - if (moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north') { - //남,북 - margin = (bbox[2] - bbox[0] - cols * width) / 2 //박스 끝에서 박스 시작값을 빼고 width와 계산된 cols를 곱한값을 뺀뒤 나누기 2 하면 가운데 배치됨 - if (moduleSetupSurface.flowDirection === 'south') { - //남쪽 - x = col === 0 ? moduleSetupSurface.left + margin : bbox[0] + col * width + margin //상하 위치 기준이면 좌우 가운데 정렬한다 - y = bbox[3] - row * height - } else { - //북쪽 - x = col === 0 ? moduleSetupSurface.left + margin : bbox[0] + col * width + margin - y = bbox[1] + row * height - } - } else if (moduleSetupSurface.flowDirection === 'east' || moduleSetupSurface.flowDirection === 'west') { - //동쪽 - margin = (bbox[3] - bbox[1] - rows * height) / 2 - if (moduleSetupSurface.flowDirection === 'east') { - x = bbox[2] - col * width - y = rows === 0 ? moduleSetupSurface.top + margin : bbox[1] + row * height + margin //좌우 위치 기준이면 상하 가운데 정렬한다 - } else { - x = bbox[0] + col * width - y = rows === 0 ? moduleSetupSurface.top + margin : bbox[1] + row * height + margin - } - } - } else { - //방향이 없는 경우 ex) 템플릿 - x = bbox[0] + col * width - y = bbox[1] + row * height - } + for (let i = 0; i < diffHeight; i++) { + leftMargin = i === 0 ? 1 : 0 + bottomMargin = i === 0 ? 0 : 1 - if (isChidori === 'true') { - if (row % 2 !== 0) { - square = [ - [x, y], - [x + width, y], - [x + width, y + height], - [x, y + height], - [x, y], - ] - } else { - square = [ - [x - width / 2, y], - [x - width / 2 + width, y], - [x - width / 2 + width, y + height], - [x - width / 2, y + height], - [x - width / 2, y], - ] - } - } else { square = [ - [x, y], - [x + width, y], - [x + width, y + height], - [x, y + height], - [x, y], + [startPoint.x1 + leftMargin, startPoint.y1 - height - bottomMargin], + [startPoint.x1 + leftMargin, startPoint.y1 - bottomMargin], + [startPoint.x1 + leftMargin + width, startPoint.y1 - bottomMargin], + [startPoint.x1 + leftMargin + width, startPoint.y1 - height - bottomMargin], + [startPoint.x1 + leftMargin, startPoint.y1 - height - bottomMargin], ] - } - // square = [ - // [x - width / 2, y], - // [x - width / 2 + width, y], - // [x - width / 2 + width, y + height], - // [x - width / 2, y + height], - // [x - width / 2, y], - // ] + const squarePolygon = turf.polygon([square]) - const squarePolygon = turf.polygon([square]) - const disjointFromTrestle = - turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) - if (disjointFromTrestle) { - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - const points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - if (containsBatchObjects.length > 0) { - let convertBatchObject - //도머가 있으면 적용되는 로직 - const isDisjoint = containsBatchObjects.every((batchObject) => { - if (batchObject.type === 'group') { - convertBatchObject = batchObjectGroupToTurfPolygon(batchObject) - } else { - convertBatchObject = polygonToTurfPolygon(batchObject) + //설치면 안에 있는지 확인 + const disjointFromTrestle = + turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) + + if (disjointFromTrestle) { + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + const points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + if (containsBatchObjects.length > 0) { + let convertBatchObject + //도머가 있으면 적용되는 로직 + const isDisjoint = containsBatchObjects.every((batchObject) => { + if (batchObject.type === 'group') { + convertBatchObject = batchObjectGroupToTurfPolygon(batchObject) + } else { + convertBatchObject = polygonToTurfPolygon(batchObject) + } + return turf.booleanDisjoint(squarePolygon, convertBatchObject) //도머가 여러개일수있으므로 겹치는게 있다면... + }) + if (isDisjoint) { + const tempModule = new QPolygon(points, { + fill: '#BFFD9F', + stroke: 'black', + strokeWidth: 0.1, + selectable: true, // 선택 가능하게 설정 + lockMovementX: false, // X 축 이동 잠금 + lockMovementY: false, // Y 축 이동 잠금 + lockRotation: false, // 회전 잠금 + lockScalingX: false, // X 축 크기 조정 잠금 + lockScalingY: false, // Y 축 크기 조정 잠금 + opacity: 0.8, + parentId: moduleSetupSurface.parentId, + name: 'module', + }) + tempModule.setViewLengthText(false) + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) } - return turf.booleanDisjoint(squarePolygon, convertBatchObject) //도머가 여러개일수있으므로 겹치는게 있다면... - }) - if (isDisjoint) { + } else { + //도머가 없을땐 그냥 그림 const tempModule = new QPolygon(points, { fill: '#BFFD9F', stroke: 'black', selectable: true, // 선택 가능하게 설정 - lockMovementX: false, // X 축 이동 잠금 - lockMovementY: false, // Y 축 이동 잠금 - lockRotation: false, // 회전 잠금 - lockScalingX: false, // X 축 크기 조정 잠금 - lockScalingY: false, // Y 축 크기 조정 잠금 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 opacity: 0.8, parentId: moduleSetupSurface.parentId, - lineCol: col, - lineRow: row, name: 'module', + selectable: true, }) - tempModule.setViewLengthText(false) - // canvas?.add(tempModule) + canvas?.add(tempModule) moduleSetupArray.push(tempModule) } - } else { - //도머가 없을땐 그냥 그림 - const tempModule = new QPolygon(points, { - fill: '#BFFD9F', - stroke: 'black', - selectable: true, // 선택 가능하게 설정 - lockMovementX: true, // X 축 이동 잠금 - lockMovementY: true, // Y 축 이동 잠금 - lockRotation: true, // 회전 잠금 - lockScalingX: true, // X 축 크기 조정 잠금 - lockScalingY: true, // Y 축 크기 조정 잠금 - opacity: 0.8, - parentId: moduleSetupSurface.parentId, - lineCol: col, - lineRow: row, - name: 'module', - }) - // canvas?.add(tempModule) - moduleSetupArray.push(tempModule) + startPoint = { x1: points[0].x, y1: points[0].y, x2: points[3].x, y2: points[3].y } } } } + } else if (setupLocation === 'ridge') { + } else { } + moduleSetupSurface.set({ modules: moduleSetupArray }) }) @@ -772,48 +721,9 @@ export function useModuleBasicSetting() { return hull } - const bottomModuleLine = (nowSurface) => { - let selectedLine = null - - const sortedLines = sortLinesByTopLeft(nowSurface.lines) - - const moduleWidthLength = 173.3 + 5 //임시 약간 여유를 줌 - - // if (nowSurface.flowDirection === 'east') { - // const leftFlow = nowSurface.lines.reduce( - // (acc, line, index) => { - // if (line.x1 < acc.x1 || (line.x1 === acc.x1 && line.y1 < acc.y1)) { - // return { x1: line.x1, y1: line.y1, index: index } - // } - // return acc - // }, - // { x1: Infinity, y1: Infinity, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 - // ) - // selectedLine = leftFlow - // } else if (nowSurface.flowDirection === 'west') { - // const rightFlow = nowSurface.lines.reduce( - // (acc, line, index) => { - // if (line.x1 > acc.x1 || (line.x1 === acc.x1 && line.y1 > acc.y1)) { - // return { x1: line.x1, y1: line.y1, index: index } - // } - // return acc - // }, - // { x1: 0, y1: 0, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 - // ) - // selectedLine = rightFlow - // } else if (nowSurface.flowDirection === 'north') { - // const topFlow = nowSurface.lines.reduce( - // (acc, line, index) => { - // if (line.y1 < acc.y1 || (line.y1 === acc.y1 && line.x1 < acc.x1)) { - // return { x1: line.x1, y1: line.y1, index: index } - // } - // return acc - // }, - // { x1: Infinity, y1: Infinity, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 - // ) - // selectedLine = topFlow - // } else { - const bottomFlow = nowSurface.lines.reduce( + const bottomTopFlowLine = (surface) => { + const flowArray = [] + const bottomFlow = surface.lines.reduce( (acc, line, index) => { if (line.y1 > acc.y1 || (line.y1 === acc.y1 && line.x1 > acc.x1)) { return { x1: line.x1, y1: line.y1, index: index } @@ -822,103 +732,9 @@ export function useModuleBasicSetting() { }, { x1: 0, y1: 0, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 ) - selectedLine = bottomFlow - // } + flowArray.push(bottomFlow) - let prevLines = nowSurface.lines[(selectedLine.index - 1 + nowSurface.lines.length) % nowSurface.lines.length] - let nextLines = nowSurface.lines[selectedLine.index] - const overlapCoords = { x: nextLines.x1, y: nextLines.y1 } //겹치는 꼭지점 - - const m1 = (prevLines.y2 - prevLines.y1) / (prevLines.x2 - prevLines.x1) - const m2 = (nextLines.y2 - nextLines.y1) / (nextLines.x2 - nextLines.x1) - - const c1 = prevLines.y1 - m1 * prevLines.x1 - const c2 = nextLines.y1 - m2 * nextLines.x1 - - // Step 2: Calculate intersection point - - let xIntersectPrev = 0 - let yIntersectPrev = 0 - let xIntersectNext = 0 - let yIntersectNext = 0 - - let endPoint = prevLines.y1 > nextLines.y2 ? prevLines.y1 : nextLines.y2 - let biggerEndPoint = prevLines.y1 > nextLines.y2 ? 'left' : 'right' - - //bottom일 경우 - xIntersectPrev = (endPoint - c1) / m1 - yIntersectPrev = m1 * xIntersectPrev + c1 - xIntersectNext = (endPoint - c2) / m2 - yIntersectNext = m2 * xIntersectNext + c2 - - let lineCoords - let polygonCoords - let ratio = 1 - if (biggerEndPoint === 'left') { - //왼쪽이 더 밑이면 우측 라인에 절편으로 계산 - lineCoords = [prevLines.x1, yIntersectNext, xIntersectNext, yIntersectNext] - polygonCoords = [ - { x: prevLines.x1, y: yIntersectNext }, - { x: xIntersectNext, y: yIntersectNext }, - { x: overlapCoords.x, y: overlapCoords.y }, - ] - ratio = moduleWidthLength / Math.abs(prevLines.x1 - xIntersectNext) - } else { - lineCoords = [xIntersectPrev, yIntersectPrev, nextLines.x2, yIntersectPrev] - polygonCoords = [ - { x: xIntersectPrev, y: yIntersectPrev }, - { x: nextLines.x2, y: yIntersectPrev }, - { x: overlapCoords.x, y: overlapCoords.y }, - ] - ratio = moduleWidthLength / Math.abs(nextLines.x2 - xIntersectPrev) - } - - const tempTriangle = new QPolygon(polygonCoords, { - fill: 'transparent', - stroke: 'green', - strokeWidth: 2, - originY: 'bottom', - strokeDashArray: [5, 5], - // fontSize: 15, - }) - - // canvas.add(tempTriangle) - - let cloneCoords = [] - tempTriangle.clone((clone) => { - clone.scale(ratio) - cloneCoords = clone.getCurrentPoints() - }) - - //아래쪽에선 잴 작은 - const vertexPoints = cloneCoords.reduce((acc, point, index) => (acc['y'] > point['y'] ? acc : point)) - - const differenceDistance = overlapCoords.x - vertexPoints.x - - const newTriangleCoords = cloneCoords.map((point) => { - return { x: point.x + differenceDistance, y: point.y } - }) - - const deleteBottomPoint = newTriangleCoords.reduce((acc, point) => (acc['y'] > point['y'] ? acc : point)) - const deleteIndex = newTriangleCoords.indexOf(deleteBottomPoint) - if (deleteIndex !== -1) newTriangleCoords.splice(deleteIndex, 1) - - const newLine = new QLine([newTriangleCoords[0].x, newTriangleCoords[0].y, newTriangleCoords[1].x, newTriangleCoords[1].y], { - fill: 'transparent', - stroke: 'red', - strokeWidth: 2, - selectable: true, - fontSize: 14, - }) - canvas.add(newLine) - return newLine - } - - const topModuleLine = (nowSurface) => { - let selectedLine = null - const moduleWidthLength = 173.3 + 5 //임시 약간 여유를 줌 - - const topFlow = nowSurface.lines.reduce( + const topFlow = surface.lines.reduce( (acc, line, index) => { if (line.y1 < acc.y1 || (line.y1 === acc.y1 && line.x1 < acc.x1)) { return { x1: line.x1, y1: line.y1, index: index } @@ -927,117 +743,80 @@ export function useModuleBasicSetting() { }, { x1: Infinity, y1: Infinity, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 ) - selectedLine = topFlow + flowArray.push(topFlow) - let prevLines = nowSurface.lines[(selectedLine.index - 1 + nowSurface.lines.length) % nowSurface.lines.length] - let nextLines = nowSurface.lines[selectedLine.index] - const overlapCoords = { x: nextLines.x1, y: nextLines.y1 } //겹치는 꼭지점 + let idx = 0 + let rtnObjArray = [] + flowArray.forEach((center) => { + const linesArray = new Array() - const m1 = (prevLines.y2 - prevLines.y1) / (prevLines.x2 - prevLines.x1) - const m2 = (nextLines.y2 - nextLines.y1) / (nextLines.x2 - nextLines.x1) + surface.lines.filter((line) => { + if ((center.x1 === line.x1 && center.y1 === line.y1) || (center.x1 === line.x2 && center.y1 === line.y2)) { + linesArray.push(line) + } + }) - const c1 = prevLines.y1 - m1 * prevLines.x1 - const c2 = nextLines.y1 - m2 * nextLines.x1 + let coords = [] + if (center.index === 0) { + coords = [ + { x: linesArray[0].x2, y: linesArray[0].y2 }, + { x: center.x1, y: center.y1 }, + { x: linesArray[1].x1, y: linesArray[1].y1 }, + ] + } else { + coords = [ + { x: linesArray[0].x1, y: linesArray[0].y1 }, + { x: center.x1, y: center.y1 }, + { x: linesArray[1].x2, y: linesArray[1].y2 }, + ] + } - // Step 2: Calculate intersection point + const adjust1 = coords[0].x - coords[1].x + const height1 = coords[1].y - coords[0].y + const angle1 = Math.abs(Math.round(Math.atan(height1 / adjust1) * (180 / Math.PI) * 1000) / 1000) - let xIntersectPrev = 0 - let yIntersectPrev = 0 - let xIntersectNext = 0 - let yIntersectNext = 0 + const adjust2 = coords[2].x - coords[1].x + const height2 = coords[2].y - coords[1].y + const angle2 = Math.abs(Math.round(Math.atan(height2 / adjust2) * (180 / Math.PI) * 1000) / 1000) + const angle3 = 180 - (angle1 + angle2) - let endPoint = prevLines.y1 > nextLines.y2 ? nextLines.y2 : prevLines.y1 - let biggerEndPoint = prevLines.y1 < nextLines.y2 ? 'left' : 'right' + const charlie = 173.3 + 3 // 평행선길이 약간 여유를 줌 + const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180) + const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180)) + const h = beta * Math.sin((angle1 * Math.PI) / 180) // 높이 + const sign = Math.sign(coords[0].y - coords[1].y) // 진행방향 + const top = coords[1].y + sign * h // 변경되는 높이 좌표 값 + // const line3 = new QLine([coords[1].x, coords[1].y, coords[1].x, top], { + // stroke: 'blue', + // strokeWidth: 1, + // selectable: true, + // }) + // // canvas?.add(line3) - //bottom일 경우 - xIntersectPrev = (endPoint - c1) / m1 - yIntersectPrev = m1 * xIntersectPrev + c1 - xIntersectNext = (endPoint - c2) / m2 - yIntersectNext = m2 * xIntersectNext + c2 + const pointX1 = coords[0].x + ((coords[0].y - top) / (coords[0].y - coords[1].y)) * (coords[1].x - coords[0].x) + const pointY1 = top + const pointX2 = coords[2].x + ((coords[2].y - top) / (coords[2].y - coords[1].y)) * (coords[1].x - coords[2].x) + const pointY2 = top - let lineCoords - let polygonCoords - let ratio = 1 + const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { + stroke: 'red', + strokeWidth: 1, + selectable: true, + }) + canvas?.add(finalLine) + canvas?.renderAll() - if (biggerEndPoint === 'left') { - //왼쪽이 더 밑이면 우측 라인에 절편으로 계산 - lineCoords = [prevLines.x1, yIntersectNext, xIntersectNext, yIntersectNext] - polygonCoords = [ - { x: prevLines.x1, y: yIntersectNext }, - { x: xIntersectNext, y: yIntersectNext }, - { x: overlapCoords.x, y: overlapCoords.y }, - ] - ratio = moduleWidthLength / Math.abs(prevLines.x1 - xIntersectNext) - } else { - lineCoords = [xIntersectPrev, yIntersectPrev, nextLines.x2, yIntersectPrev] - polygonCoords = [ - { x: xIntersectPrev, y: yIntersectPrev }, - { x: nextLines.x2, y: yIntersectPrev }, - { x: overlapCoords.x, y: overlapCoords.y }, - ] - ratio = moduleWidthLength / Math.abs(nextLines.x2 - xIntersectPrev) - } - - const tempTriangle = new QPolygon(polygonCoords, { - fill: 'transparent', - stroke: 'green', - strokeWidth: 2, - originY: 'top', - strokeDashArray: [5, 5], - // fontSize: 15, + const rtnObj = { target: idx === 0 ? 'bottom' : 'top', x1: pointX1, y1: pointY1, x2: pointX2, y2: pointY2 } + rtnObjArray.push(rtnObj) + ++idx }) - // canvas.add(tempTriangle) - - let cloneCoords = [] - tempTriangle.clone((clone) => { - clone.scale(ratio) - cloneCoords = clone.getCurrentPoints() - }) - - //아래쪽에선 잴 작은 - const vertexPoints = cloneCoords.reduce((acc, point, index) => (acc['y'] < point['y'] ? acc : point)) - - const differenceDistance = overlapCoords.x - vertexPoints.x - - const newTriangleCoords = cloneCoords.map((point) => { - return { x: point.x + differenceDistance, y: point.y } - }) - - // const newTriangle1 = new QPolygon(newTriangleCoords, { - // fill: 'transparent', - // stroke: 'red', - // strokeWidth: 1, - // selectable: true, - // fontSize: 14, - // }) - // canvas.add(newTriangle1) - - const deleteBottomPoint = newTriangleCoords.reduce((acc, point) => (acc['y'] < point['y'] ? acc : point)) - const deleteIndex = newTriangleCoords.indexOf(deleteBottomPoint) - if (deleteIndex !== -1) newTriangleCoords.splice(deleteIndex, 1) - - const newLine = new QLine([newTriangleCoords[0].x, newTriangleCoords[0].y, newTriangleCoords[1].x, newTriangleCoords[1].y], { - fill: 'transparent', - stroke: 'red', - strokeWidth: 2, - selectable: true, - fontSize: 14, - }) - canvas.add(newLine) - return newLine + return rtnObjArray } - const leftModuleLine = (nowSurface) => { - let selectedLine = null - - sortLinesByTopLeft(nowSurface) - - console.log('nowSurface', nowSurface) - - const moduleWidthLength = 173.3 + 5 //임시 약간 여유를 줌 - - const leftFlow = nowSurface.lines.reduce( + const leftRightFlowLine = (surface) => { + const flowArray = [] + const leftFlow = surface.lines.reduce( (acc, line, index) => { if (line.x1 < acc.x1 || (line.x1 === acc.x1 && line.y1 < acc.y1)) { return { x1: line.x1, y1: line.y1, index: index } @@ -1046,143 +825,135 @@ export function useModuleBasicSetting() { }, { x1: Infinity, y1: Infinity, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 ) - selectedLine = leftFlow + flowArray.push(leftFlow) - let prevLines = nowSurface.lines[(selectedLine.index - 1 + nowSurface.lines.length) % nowSurface.lines.length] - let nextLines = nowSurface.lines[selectedLine.index] - const overlapCoords = { x: nextLines.x1, y: nextLines.y1 } //겹치는 꼭지점 + const rightFlow = surface.lines.reduce( + (acc, line, index) => { + if (line.x1 > acc.x1 || (line.x1 === acc.x1 && line.y1 > acc.y1)) { + return { x1: line.x1, y1: line.y1, index: index } + } + return acc + }, + { x1: 0, y1: 0, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 + ) + flowArray.push(rightFlow) - const m1 = (prevLines.y2 - prevLines.y1) / (prevLines.x2 - prevLines.x1) - const m2 = (nextLines.y2 - nextLines.y1) / (nextLines.x2 - nextLines.x1) + let idx = 0 + let rtnObjArray = [] + flowArray.forEach((center) => { + const linesArray = surface.lines.filter((line) => { + if ((center.x1 === line.x1 && center.y1 === line.y1) || (center.x1 === line.x2 && center.y1 === line.y2)) { + return line + } + }) - const c1 = prevLines.y1 - m1 * prevLines.x1 - const c2 = nextLines.y1 - m2 * nextLines.x1 + let coords = [] + if (center.index === 0) { + coords = [ + { x: linesArray[1].x1, y: linesArray[1].y1 }, + { x: center.x1, y: center.y1 }, + { x: linesArray[0].x2, y: linesArray[0].y2 }, + ] + } else { + coords = [ + { x: linesArray[0].x1, y: linesArray[0].y1 }, + { x: center.x1, y: center.y1 }, + { x: linesArray[1].x2, y: linesArray[1].y2 }, + ] + } - // Step 2: Calculate intersection point + const adjust1 = coords[0].x - coords[1].x + const height1 = coords[1].y - coords[0].y + const angle1 = Math.abs(Math.round(Math.atan(adjust1 / height1) * (180 / Math.PI) * 1000) / 1000) - let xIntersectPrev = 0 - let yIntersectPrev = 0 - let xIntersectNext = 0 - let yIntersectNext = 0 + const adjust2 = coords[2].x - coords[1].x + const height2 = coords[2].y - coords[1].y + const angle2 = Math.abs(Math.round(Math.atan(adjust2 / height2) * (180 / Math.PI) * 1000) / 1000) + const angle3 = 180 - (angle1 + angle2) - let biggerEndPoint = prevLines.x1 > nextLines.x2 ? 'top' : 'bottom' - console.log('prevLines.x1', prevLines.x1) - console.log('nextLines.x2', nextLines.x2) - console.log('biggerEndPoint', biggerEndPoint) + const charlie = 173.3 + 3 // 평행선길이 약간 여유를줌 + const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180) + const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180)) - //bottom일 경우 - xIntersectPrev = prevLines.x1 - yIntersectPrev = m1 * xIntersectPrev + c1 - xIntersectNext = prevLines.x1 - yIntersectNext = m2 * xIntersectNext + c2 + const h = beta * Math.sin((angle1 * Math.PI) / 180) // 높이 + const sign = Math.sign(coords[0].x - coords[1].x) // 진행방향 + const top = coords[1].x + sign * h // 변경되는 높이 좌표 값 - let lineCoords - let polygonCoords - let ratio = 1 + // const line3 = new QLine([coords[1].x, coords[1].y, top, coords[1].y], { + // stroke: 'blue', + // strokeWidth: 1, + // selectable: true, + // }) + // canvas?.add(line3) - if (biggerEndPoint === 'top') { - //윗쪽이이 더 밑이면 아래 라인에 절편으로 계산 - lineCoords = [prevLines.x1, yIntersectNext, xIntersectNext, yIntersectNext] - polygonCoords = [ - { x: prevLines.x1, y: yIntersectNext }, - { x: xIntersectNext, y: yIntersectNext }, - { x: overlapCoords.x, y: overlapCoords.y }, - ] - ratio = moduleWidthLength / Math.abs(prevLines.x1 - xIntersectNext) - } else { - lineCoords = [xIntersectPrev, prevLines.y1, xIntersectPrev, yIntersectPrev] - polygonCoords = [ - { x: xIntersectNext, y: prevLines.y1 }, - { x: xIntersectNext, y: yIntersectNext }, - { x: overlapCoords.x, y: overlapCoords.y }, - ] - ratio = moduleWidthLength / Math.abs(prevLines.y1 - yIntersectNext) - } + const pointX1 = top + const pointY1 = coords[0].y + ((coords[0].x - top) / (coords[0].x - coords[1].x)) * (coords[1].y - coords[0].y) + const pointX2 = top + const pointY2 = coords[2].y + ((coords[2].x - top) / (coords[2].x - coords[1].x)) * (coords[1].y - coords[2].y) - const tempTriangle = new QPolygon(polygonCoords, { - fill: 'transparent', - stroke: 'green', - strokeWidth: 2, - originX: 'left', - strokeDashArray: [5, 5], - // fontSize: 15, - selectable: true, + const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { + stroke: 'red', + strokeWidth: 1, + selectable: true, + }) + canvas?.add(finalLine) + canvas?.renderAll() + + const rtnObj = { target: idx === 0 ? 'left' : 'right', x1: pointX1, y1: pointY1, x2: pointX2, y2: pointY2 } + rtnObjArray.push(rtnObj) + ++idx }) - - // canvas.add(tempTriangle) - - let cloneCoords = [] - tempTriangle.clone((clone) => { - clone.scale(ratio) - cloneCoords = clone.getCurrentPoints() - // canvas.add(clone) - }) - - canvas.remove(tempTriangle) - - //left에선 가장 왼쪽 - const vertexPoints = cloneCoords.reduce((acc, point, index) => (acc['x'] < point['x'] ? acc : point)) - const differenceDistance = overlapCoords.y - vertexPoints.y - - const newTriangleCoords = cloneCoords.map((point) => { - return { x: point.x, y: point.y + differenceDistance } - }) - - // const newTriangle1 = new QPolygon(newTriangleCoords, { - // fill: 'transparent', - // stroke: 'red', - // strokeWidth: 1, - // selectable: true, - // fontSize: 14, - // }) - // canvas.add(newTriangle1) - - const deleteLeftPoint = newTriangleCoords.reduce((acc, point) => (acc['x'] < point['x'] ? acc : point)) - const deleteIndex = newTriangleCoords.indexOf(deleteLeftPoint) - if (deleteIndex !== -1) newTriangleCoords.splice(deleteIndex, 1) - - const newLine = new QLine([newTriangleCoords[0].x, newTriangleCoords[0].y, newTriangleCoords[1].x, newTriangleCoords[1].y], { - fill: 'transparent', - stroke: 'red', - strokeWidth: 2, - viewLengthText: false, - // selectable: true, - fontSize: 14, - }) - canvas.add(newLine) - return newLine } - function sortLinesByTopLeft(surface) { - // 좌측 상단 기준으로 정렬 - const sortedLines = surface.lines.sort((a, b) => { - // x1, y1 값을 기준으로 정렬 - if (a.x1 !== b.x1) { - return a.x1 - b.x1 // x1 기준 정렬 - } else { - return a.y1 - b.y1 // x1이 같으면 y1 기준 정렬 - } - }) + const findSetupSurfaceMaxLines = (surface) => { + const leftFlow = surface.lines.reduce( + (acc, line, index) => { + if (line.x1 < acc.x1 || (line.x1 === acc.x1 && line.y1 < acc.y1)) { + return { x1: line.x1, y1: line.y1 } + } + return acc + }, + { x1: Infinity, y1: Infinity, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 + ) - // 정렬된 결과를 기반으로 좌표 재정렬 - sortedLines.forEach((line) => { - // 좌측 상단이 (0,0) 기준이 되도록 좌표 이동 - const minX = Math.min(line.x1, line.x2) - const minY = Math.min(line.y1, line.y2) + const rightFlow = surface.lines.reduce( + (acc, line, index) => { + if (line.x1 > acc.x1 || (line.x1 === acc.x1 && line.y1 > acc.y1)) { + return { x1: line.x1, y1: line.y1 } + } + return acc + }, + { x1: 0, y1: 0, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 + ) - line.set({ - x1: line.x1 - minX, - y1: line.y1 - minY, - x2: line.x2 - minX, - y2: line.y2 - minY, - }) - }) + const topFlow = surface.lines.reduce( + (acc, line, index) => { + if (line.y1 < acc.y1 || (line.y1 === acc.y1 && line.x1 < acc.x1)) { + return { x1: line.x1, y1: line.y1 } + } + return acc + }, + { x1: Infinity, y1: Infinity, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 + ) - surface.set({ - sortedLines: sortedLines, - }) + const bottomFlow = surface.lines.reduce( + (acc, line, index) => { + if (line.y1 > acc.y1 || (line.y1 === acc.y1 && line.x1 > acc.x1)) { + return { x1: line.x1, y1: line.y1 } + } + return acc + }, + { x1: 0, y1: 0, index: -1 }, // 초기값: 무한대와 유효하지 않은 인덱스 + ) - return sortedLines + const obj = { + left: leftFlow, + right: rightFlow, + top: topFlow, + bottom: bottomFlow, + } + + return obj } return {