From 94a7502e6ee72a845b4fa56cc1fa0ca69519f7c5 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 1 Aug 2024 18:07:43 +0900 Subject: [PATCH] =?UTF-8?q?polygon=20divide=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 50 ++++- src/components/fabric/QLine.js | 40 ++-- src/hooks/useCanvas.js | 20 +- src/hooks/useMode.js | 8 +- src/util/qline-utils.js | 14 +- src/util/qpolygon-utils.js | 353 ++++++++++++++++++++++++++++++--- 6 files changed, 418 insertions(+), 67 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index e3009432..8d2fc35b 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -257,20 +257,64 @@ export default function Roof2() { ] const types = [type1, type2, type3, type4, type1A, type1B, eightPoint, eightPoint2, eightPoint3, eightPoint4, twelvePoint] - - const polygon = new QPolygon(type1B, { + const newP = [ + { x: 450, y: 450 }, + { x: 650, y: 250 }, + { x: 675, y: 275 }, + { x: 450, y: 850 }, + ] + const polygon = new QPolygon(type4, { fill: 'transparent', stroke: 'black', strokeWidth: 1, - selectable: true, + selectable: false, fontSize: fontSize, name: 'QPolygon1', }) canvas?.add(polygon) + polygon.set('strokeDashArray', [10, 5, 2, 5]) + polygon.set('stroke', 'blue') + polygon.set('strokeWidth', 1) + + // const newPolygon = fabric.util.clone(polygon) + handleOuterlinesTest2(polygon) + const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') + + roofs.forEach((roof) => { + let maxLengthLine = roof.lines.reduce((acc, cur) => { + return acc.length > cur.length ? acc : cur + }) + + // 패턴 소스를 위한 임시 캔버스 생성 + const patternSourceCanvas = document.createElement('canvas') + if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { + patternSourceCanvas.width = 20 * window.devicePixelRatio || 1 + patternSourceCanvas.height = 10 * window.devicePixelRatio || 1 + } else { + patternSourceCanvas.width = 10 * window.devicePixelRatio || 1 + patternSourceCanvas.height = 20 * window.devicePixelRatio || 1 + } + + const ctx = patternSourceCanvas.getContext('2d') + + // 벽돌 패턴 그리기 + ctx.scale(window.devicePixelRatio || 1, window.devicePixelRatio || 1) + ctx.strokeStyle = 'green' + ctx.lineWidth = 0.4 + ctx.strokeRect(0, 0, 100, 100) + // 패턴 생성 + const pattern = new fabric.Pattern({ + source: patternSourceCanvas, + repeat: 'repeat', + }) + + roof.set('fill', pattern) + }) + // const lines = togglePolygonLine(polygon) // togglePolygonLine(lines[0]) } diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 2d1e87df..e6a2bc65 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -10,8 +10,9 @@ export const QLine = fabric.util.createClass(fabric.Line, { length: 0, direction: null, idx: 0, + area: 0, initialize: function (points, options, canvas) { - this.callSuper('initialize', points, options) + this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? false }) if (options.id) { this.id = options.id } else { @@ -23,16 +24,9 @@ export const QLine = fabric.util.createClass(fabric.Line, { point = Math.round(point) }) - const scaleX = this.scaleX - const scaleY = this.scaleY - const x1 = this.left - const y1 = this.top - const x2 = this.left + this.width * scaleX - const y2 = this.top + this.height * scaleY this.idx = options.idx ?? 0 - const dx = x2 - x1 - const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) + + this.setLength() this.direction = options.direction ?? getDirection({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) @@ -67,9 +61,22 @@ export const QLine = fabric.util.createClass(fabric.Line, { }) }, + setLength() { + const scaleX = this.scaleX + const scaleY = this.scaleY + const x1 = this.left + const y1 = this.top + const x2 = this.left + this.width * scaleX + const y2 = this.top + this.height * scaleY + const dx = x2 - x1 + const dy = y2 - y1 + this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) + }, + addLengthText() { const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id) + this.setLength() const scaleX = this.scaleX const scaleY = this.scaleY const x1 = this.left @@ -79,13 +86,10 @@ export const QLine = fabric.util.createClass(fabric.Line, { if (thisText) { thisText.set({ text: this.length.toFixed(0).toString(), left: (x1 + x2) / 2, top: (y1 + y2) / 2 }) + this.text = thisText return } - const dx = x2 - x1 - const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) - const text = new fabric.Textbox(this.length.toFixed(0).toString(), { left: (x1 + x2) / 2, top: (y1 + y2) / 2, @@ -113,4 +117,12 @@ export const QLine = fabric.util.createClass(fabric.Line, { setCanvas(canvas) { this.canvas = canvas }, + + setViewLengthText(bool) { + const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id) + if (thisText) { + thisText.set({ visible: bool }) + } + return this + }, }) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index c1ba723a..31b223bf 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -7,6 +7,8 @@ import { canvasSizeState, fontSizeState } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' import QRect from '@/components/fabric/QRect' import { QPolygon } from '@/components/fabric/QPolygon' +import { defineQLine } from '@/util/qline-utils' +import { defineQPloygon } from '@/util/qpolygon-utils' export function useCanvas(id) { const [canvas, setCanvas] = useState() @@ -115,22 +117,8 @@ export function useCanvas(id) { QPolygon.prototype.canvas = canvas QLine.prototype.canvas = canvas QRect.prototype.canvas = canvas - - fabric.QLine.fromObject = function (object, callback) { - function _callback(instance) { - delete instance.points - callback && callback(instance) - } - - const options = fabric.util.object.clone(object, true) - options.points = [object.x1, object.y1, object.x2, object.y2] - - fabric.Object._fromObject('QLine', options, _callback, 'points') - } - - fabric.QPolygon.fromObject = function (object, callback) { - fabric.Object._fromObject('QPolygon', object, callback, 'points') - } + defineQLine() + defineQPloygon() } /** diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 4533d7a2..563dd65a 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -18,7 +18,7 @@ import { fabric } from 'fabric' import { QPolygon } from '@/components/fabric/QPolygon' export const Mode = { - DRAW_LINE: 'drawLine', // 기준선 긋기모드 + DRAW_LINE: 'drawLine', // 기준선 긋기모드` EDIT: 'edit', TEMPLATE: 'template', PATTERNA: 'patterna', @@ -641,6 +641,9 @@ export function useMode() { * a : 시작점, b : 끝점 */ const drawLineWithLength = (a, b) => { + if (!a || !b) { + return + } const line = new QLine([a.left, a.top, b.left, b.top], { stroke: 'black', strokeWidth: 2, @@ -700,7 +703,6 @@ export function useMode() { stroke: 'black', fill: 'transparent', viewLengthText: true, - selectable: true, fontSize: fontSize, }, canvas, @@ -1174,6 +1176,7 @@ export function useMode() { setRoof(roof) roof.drawHelpLine() + roof.divideLine() } const togglePolygonLine = (obj) => { @@ -3237,6 +3240,7 @@ export function useMode() { fill: pattern, selectable: false, fontSize: 15, // fontSize는 필요에 따라 조정 + sort: false, lockMovementX: true, lockMovementY: true, lockRotation: true, diff --git a/src/util/qline-utils.js b/src/util/qline-utils.js index 77821886..6443efb2 100644 --- a/src/util/qline-utils.js +++ b/src/util/qline-utils.js @@ -2,8 +2,14 @@ import { fabric } from 'fabric' import { QLine } from '@/components/fabric/QLine' export const defineQLine = () => { - /*fabric.QLine = QLine - fabric.QLine.fromObject = (object, callback) => { - return new fabric.QLine([object.x1, object.y1, object.x2, object.y2], object) - }*/ + fabric.QLine.fromObject = function (object, callback) { + function _callback(instance) { + delete instance.points + callback && callback(instance) + } + const options = fabric.util.object.clone(object, true) + options.points = [object.x1, object.y1, object.x2, object.y2] + + fabric.Object._fromObject('QLine', options, _callback, 'points') + } } diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index af5d676e..078303d0 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1,6 +1,7 @@ import { fabric } from 'fabric' import { QLine } from '@/components/fabric/QLine' -import { calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' +import { calculateIntersection, distanceBetweenPoints, findClosestPoint, getDirectionByPoint } from '@/util/canvas-util' +import { QPolygon } from '@/components/fabric/QPolygon' export const defineQPloygon = () => { fabric.QPolygon.fromObject = function (object, callback) { @@ -19,7 +20,7 @@ export const drawHelpLineInHexagon = (polygon, chon) => { const ridgeStartPoints = [] const ridgeEndPoints = [] - const centerInterSectionPoints = [] + let centerInterSectionPoints = [] // polygon.lines = polygon.lines.sort((a, b) => a.length - b.length) polygon.wall.lines = getOneSideLines(polygon.wall) @@ -101,9 +102,9 @@ export const drawHelpLineInHexagon = (polygon, chon) => { : nextLine.startPoint line.connectedPoint = { interSectionPoint, area, startPoint, endPoint } - line.connectedPoints.push(interSectionPoint) + line.connectedPoints.push({ interSectionPoint, area, startPoint, endPoint }) nextLine.connectedPoint = { interSectionPoint, area, startPoint, endPoint } - nextLine.connectedPoints.push(interSectionPoint) + nextLine.connectedPoints.push({ interSectionPoint, area, startPoint, endPoint }) } } }) @@ -150,6 +151,12 @@ export const drawHelpLineInHexagon = (polygon, chon) => { name: 'hip', }) + line.startPoint = point.startPoint + line.endPoint = point.interSectionPoint + + line2.startPoint = point.endPoint + line2.endPoint = point.interSectionPoint + polygon.hips.push(line) polygon.hips.push(line2) @@ -165,20 +172,26 @@ export const drawHelpLineInHexagon = (polygon, chon) => { uniqueInterSectionPoints.forEach((point) => { const interSectionPoint = point.interSectionPoint - if (connectedPoint.x === interSectionPoint.x && connectedPoint.y === interSectionPoint.y) { + if (connectedPoint.interSectionPoint.x === interSectionPoint.x && connectedPoint.interSectionPoint.y === interSectionPoint.y) { removedIdx.push(line.idx) } }) }) }) - const notIntersectedLines = helpLines.filter((line) => !removedIdx.includes(line.idx)) + let notIntersectedLines = helpLines.filter((line) => !removedIdx.includes(line.idx)) + + notIntersectedLines = notIntersectedLines.map((line) => { + return { ...line, centerInterSectionPoints: [] } + }) notIntersectedLines.forEach((line) => { centerLines.forEach((centerLine) => { const interSectionPoint = calculateIntersection(line, centerLine) if (interSectionPoint && polygon.inPolygon(interSectionPoint) && polygon.wall.inPolygon(interSectionPoint)) { + line.centerInterSectionPoints.push(interSectionPoint) + interSectionPoint.lineIdx = line.idx centerInterSectionPoints.push(interSectionPoint) } }) @@ -187,11 +200,12 @@ export const drawHelpLineInHexagon = (polygon, chon) => { // centerInterSectionPoints에서 ridgeStartPoints와 x가 같거나 y가 같은것중 가장 가까운 점들을 찾는다. ridgeStartPoints.forEach((point) => { const xPoints = centerInterSectionPoints.filter((centerPoint) => Math.abs(centerPoint.x - point.x) < 2) + const yPoints = centerInterSectionPoints.filter((centerPoint) => Math.abs(centerPoint.y - point.y) < 2) let closestPoint if (xPoints.length === 0) { closestPoint = findClosestPoint(point, yPoints) - } else { + } else if (yPoints.length === 0) { closestPoint = findClosestPoint(point, xPoints) } @@ -200,44 +214,119 @@ export const drawHelpLineInHexagon = (polygon, chon) => { stroke: 'purple', fontSize: polygon.fontSize, name: 'ridge', + direction: getDirectionByPoint(point, closestPoint), }) + + line.startPoint = point + line.endPoint = closestPoint + polygon.ridges.push(line) polygon.canvas.add(line) ridgeEndPoints.push(closestPoint) + + notIntersectedLines = notIntersectedLines.filter((line) => line.idx !== closestPoint.lineIdx) } }) + centerInterSectionPoints = [] + notIntersectedLines.forEach((line) => { + centerInterSectionPoints.push(...line.centerInterSectionPoints) + }) + // ridgeEndPoints끼리 이어준다. - const remainingPoints = ridgeEndPoints + const remainingPoints = [...ridgeEndPoints] + + // ridgeEndPoint에서 centerInterSectionPoints와 45도인 점을 찾아 이어준다. + + ridgeEndPoints.forEach((ridgePoint) => { + const filteredCenterInterSectionPoints = centerInterSectionPoints.filter((centerPoint) => { + const degree = calculateAngle(ridgePoint, centerPoint) + return Math.abs(degree) === 45 || Math.abs(degree) === 135 + })[0] + + if (filteredCenterInterSectionPoints) { + const line = new QLine([ridgePoint.x, ridgePoint.y, filteredCenterInterSectionPoints.x, filteredCenterInterSectionPoints.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + name: 'hip', + }) + + line.startPoint = ridgePoint + line.endPoint = filteredCenterInterSectionPoints + + polygon.hips.push(line) + polygon.canvas.add(line) + + ridgeStartPoints.push(filteredCenterInterSectionPoints) + + polygon.points.forEach((point) => { + const degree = calculateAngle(ridgePoint, point) + + if (Math.abs(degree) % 45 < 1) { + const line = new QLine([ridgePoint.x, ridgePoint.y, point.x, point.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + name: 'hip', + }) + + polygon.hips.push(line) + polygon.canvas.add(line) + } + }) + } + }) + + // ridgeEndPoint끼리 연결한다. + while (remainingPoints.length > 1) { + const startPoint = remainingPoints.shift() + const endPoint = remainingPoints.shift() + + const line = new QLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + name: 'connectRidge', + }) + + line.startPoint = startPoint + line.endPoint = endPoint + + polygon.connectRidges.push(line) - remainingPoints.forEach((ridgePoint) => { polygon.points.forEach((point) => { - const degree = calculateAngle(ridgePoint, point) + const degree = calculateAngle(startPoint, point) - if (Math.abs(degree) % 45 < 1) { - const line = new QLine([ridgePoint.x, ridgePoint.y, point.x, point.y], { + if (Math.abs(degree) === 45 || Math.abs(degree) === 135) { + const line = new QLine([startPoint.x, startPoint.y, point.x, point.y], { stroke: 'purple', fontSize: polygon.fontSize, name: 'hip', }) + line.startPoint = startPoint + line.endPoint = point + polygon.hips.push(line) polygon.canvas.add(line) } }) - }) - while (remainingPoints.length > 0) { - const point = remainingPoints.shift() - const closestPoint = findClosestPoint(point, remainingPoints) - if (!closestPoint) continue - // 마루끼리 연결 - const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], { - stroke: 'purple', - fontSize: polygon.fontSize, - name: 'connectRidge', + polygon.points.forEach((point) => { + const degree = calculateAngle(endPoint, point) + + if (Math.abs(degree) === 45 || Math.abs(degree) === 135) { + const line = new QLine([endPoint.x, endPoint.y, point.x, point.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + name: 'hip', + }) + + line.startPoint = endPoint + line.endPoint = point + + polygon.hips.push(line) + polygon.canvas.add(line) + } }) - polygon.connectRidges.push(line) polygon.canvas.add(line) } @@ -246,7 +335,7 @@ export const drawHelpLineInHexagon = (polygon, chon) => { export const drawCenterLines = (polygon) => { const centerLines = [] - const oneSideLines = getOneSideLines(polygon) + const oneSideLines = polygon.lines.map((line) => getOneSideLine(line)) const horizontalLines = oneSideLines.filter((line) => line.direction === 'right') const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom') @@ -261,9 +350,6 @@ export const drawCenterLines = (polygon) => { horizontalLines.forEach((line, index) => { const nextLine = horizontalLines[(index + 1) % horizontalLines.length] - line.set({ strokeWidth: 5 }) - nextLine.set({ strokeWidth: 5 }) - polygon.canvas.renderAll() const startCenterX = Math.min(line.x1, nextLine.x1) @@ -319,6 +405,8 @@ const getOneSideLines = (polygon) => { line.x2 = newX2 line.y2 = newY2 line.direction = 'bottom' + line.startPoint = { x: newX1, y: newY1 } + line.endPoint = { x: newX2, y: newY2 } } else if (line.direction === 'left') { newX1 = line.x2 newY1 = line.y2 @@ -330,11 +418,13 @@ const getOneSideLines = (polygon) => { line.x2 = newX2 line.y2 = newY2 line.direction = 'right' + line.startPoint = { x: newX1, y: newY1 } + line.endPoint = { x: newX2, y: newY2 } } return line }) } -const calculateAngle = (point1, point2) => { +export const calculateAngle = (point1, point2) => { const deltaX = point2.x - point1.x const deltaY = point2.y - point1.y const angleInRadians = Math.atan2(deltaY, deltaX) @@ -375,3 +465,210 @@ const calculateTriangleArea = (point1, point2, point3) => { return Math.abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2 } + +// polygon을 나눈다. +export const dividePolygon = (polygon) => { + let hips = polygon.hips + const ridges = polygon.ridges.map((ridge) => getOneSideLine(ridge)) + const connectRidges = polygon.connectRidges + const polygonLines = polygon.lines + + hips.forEach((hip) => { + // hips의 startPoint와 endPoint를 polygon의 points와 비교하여 같은 점이 endPoint일 경우 startPoint로 변경한다. + const startPoint = polygon.points.find((point) => point.x === hip.endPoint.x && point.y === hip.endPoint.y) + if (startPoint) { + const temp = hip.startPoint + hip.startPoint = hip.endPoint + hip.endPoint = temp + } + }) + hips = [...hips, ...connectRidges] + polygon.setViewLengthText(false) + + polygonLines.forEach((line) => { + let ridge + + const startPoint = line.startPoint + const endPoint = line.endPoint + let polygonPoints = [] + + polygonPoints.push(startPoint) + + polygonPoints.push(endPoint) + + const startHip = hips.find((hip) => hip.startPoint.x === startPoint.x && hip.startPoint.y === startPoint.y) + const endHip = hips.find((hip) => hip.startPoint.x === endPoint.x && hip.startPoint.y === endPoint.y) + + if (startHip && endHip && startHip.endPoint.x === endHip.endPoint.x && startHip.endPoint.y === endHip.endPoint.y) { + polygonPoints.push(startHip.endPoint) + + const newPolygon = new QPolygon(polygonPoints, { + fontSize: polygon.fontSize, + id: polygon.id, + name: 'roof', + selectable: true, + stroke: 'black', + fill: 'transparent', + strokeWidth: 3, + }) + + polygon.canvas.add(newPolygon) + return + } + + let connectedRidge = ridges.find( + (ridge) => + (ridge.startPoint.x === startHip.endPoint.x && ridge.startPoint.y === startHip.endPoint.y) || + (ridge.endPoint.x === startHip.endPoint.x && ridge.endPoint.y === startHip.endPoint.y), + ) + + const hipStartPoint = startHip.endPoint + const hipEndPoint = endHip.endPoint + const restRidgeConnection = connectRidges[0] + + if (connectedRidge.startPoint.x === hipStartPoint.x && connectedRidge.startPoint.y === hipStartPoint.y) { + if (connectedRidge.endPoint.x === hipEndPoint.x && connectedRidge.endPoint.y === hipEndPoint.y) { + polygonPoints.push(connectedRidge.endPoint) + polygonPoints.push(connectedRidge.startPoint) + + const newPolygon = new QPolygon(polygonPoints, { + fontSize: polygon.fontSize, + id: polygon.id, + name: 'roof', + selectable: true, + stroke: 'black', + fill: 'transparent', + strokeWidth: 3, + }) + + polygon.canvas.add(newPolygon) + return + } + } else if (connectedRidge.endPoint.x === hipStartPoint.x && connectedRidge.endPoint.y === hipStartPoint.y) { + if (connectedRidge.startPoint.x === hipEndPoint.x && connectedRidge.startPoint.y === hipEndPoint.y) { + polygonPoints.push(connectedRidge.startPoint) + polygonPoints.push(connectedRidge.endPoint) + + const newPolygon = new QPolygon(polygonPoints, { + fontSize: polygon.fontSize, + id: polygon.id, + name: 'roof', + selectable: true, + stroke: 'black', + fill: 'transparent', + strokeWidth: 3, + sort: true, + }) + + polygon.canvas.add(newPolygon) + return + } + } + + // 지붕이 꺾여있는 경우 + + if ( + (restRidgeConnection.startPoint.x === startHip.endPoint.x && restRidgeConnection.startPoint.y === startHip.endPoint.y) || + (restRidgeConnection.endPoint.x === startHip.endPoint.x && restRidgeConnection.endPoint.y === startHip.endPoint.y) + ) { + polygonPoints = [startPoint, startHip.endPoint] + let lastPoint + + if (restRidgeConnection.startPoint.x === startHip.endPoint.x && restRidgeConnection.startPoint.y === startHip.endPoint.y) { + lastPoint = restRidgeConnection.endPoint + polygonPoints.push(restRidgeConnection.endPoint) + } else { + lastPoint = restRidgeConnection.startPoint + polygonPoints.push(restRidgeConnection.startPoint) + } + + connectedRidge = ridges.find( + (ridge) => + (ridge.startPoint.x === lastPoint.x && ridge.startPoint.y === lastPoint.y) || + (ridge.endPoint.x === lastPoint.x && ridge.endPoint.y === lastPoint.y), + ) + + if (connectedRidge.startPoint.x === lastPoint.x && connectedRidge.startPoint.y === lastPoint.y) { + polygonPoints.push(connectedRidge.endPoint) + } else { + polygonPoints.push(connectedRidge.startPoint) + } + + polygonPoints.push(endPoint) + } else { + polygonPoints = [endPoint, endHip.endPoint] + let lastPoint + + if (restRidgeConnection.startPoint.x === endHip.endPoint.x && restRidgeConnection.startPoint.y === endHip.endPoint.y) { + lastPoint = restRidgeConnection.endPoint + polygonPoints.push(restRidgeConnection.endPoint) + } else { + lastPoint = restRidgeConnection.startPoint + polygonPoints.push(restRidgeConnection.startPoint) + } + + connectedRidge = ridges.find( + (ridge) => + (ridge.startPoint.x === lastPoint.x && ridge.startPoint.y === lastPoint.y) || + (ridge.endPoint.x === lastPoint.x && ridge.endPoint.y === lastPoint.y), + ) + + if (connectedRidge.startPoint.x === startHip.endPoint.x && connectedRidge.startPoint.y === startHip.endPoint.y) { + lastPoint = connectedRidge.startPoint + polygonPoints.push(connectedRidge.startPoint) + } else { + lastPoint = connectedRidge.endPoint + polygonPoints.push(connectedRidge.endPoint) + } + + polygonPoints.push(startPoint) + } + + const newPolygon = new QPolygon(polygonPoints, { + fontSize: polygon.fontSize, + id: polygon.id, + name: 'roof', + selectable: true, + stroke: 'black', + fill: 'transparent', + strokeWidth: 3, + }) + + polygon.canvas.add(newPolygon) + }) +} + +const getOneSideLine = (line) => { + // left, top 방향의 line은 right, bottom 방향의 line으로 변경한다. + const newLine = { ...line } + let newX1, newY1, newX2, newY2 + if (newLine.direction === 'top') { + newX1 = newLine.x2 + newY1 = newLine.y2 + newX2 = newLine.x1 + newY2 = newLine.y1 + + newLine.x1 = newX1 + newLine.y1 = newY1 + newLine.x2 = newX2 + newLine.y2 = newY2 + newLine.direction = 'bottom' + newLine.startPoint = { x: newX1, y: newY1 } + newLine.endPoint = { x: newX2, y: newY2 } + } else if (line.direction === 'left') { + newX1 = newLine.x2 + newY1 = newLine.y2 + newX2 = newLine.x1 + newY2 = newLine.y1 + + newLine.x1 = newX1 + newLine.y1 = newY1 + newLine.x2 = newX2 + newLine.y2 = newY2 + newLine.direction = 'right' + newLine.startPoint = { x: newX1, y: newY1 } + newLine.endPoint = { x: newX2, y: newY2 } + } + + return newLine +}