From 2f261cb0c0a9418a13e2e416f04c2493b49ed798 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 8 May 2025 18:05:38 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B0=95=EA=B3=B5=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EB=8F=99=EC=84=A0=EC=9D=B4=EB=8F=99=20=EB=8C=80=EC=9D=91=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC=20(=ED=98=BC=ED=95=A9=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 935 +++++++++++++++++-------------------- 1 file changed, 422 insertions(+), 513 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 9fbfc6a3..677c9a5b 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1,6 +1,6 @@ import { fabric } from 'fabric' import { QLine } from '@/components/fabric/QLine' -import { getDegreeByChon } from '@/util/canvas-util' +import { getDegreeByChon, isPointOnLine } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' import * as turf from '@turf/turf' @@ -878,6 +878,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { if (checkWallPolygon.inPolygon(checkPoints)) { drawGablePolygonFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine }) + } else { + drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) } // if (!checkWallPolygon.inPolygon(checkPoints)) { drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) @@ -1655,410 +1657,27 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { canvas.renderAll() }) - /** 케라바 지붕으로 생성된 마루의 지붕선을 그린다.*/ - baseGableRidgeLines.forEach((ridge) => { - return - const { x1, x2, y1, y2 } = ridge - const checkLine = new fabric.Line([x1, y1, x2, y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll() - - const ridgeVectorX = Math.sign(Big(x1).minus(x2).toNumber()) - const ridgeVectorY = Math.sign(Big(y1).minus(y2).toNumber()) - const firstPoint = { x: x1, y: y1 } - const secondPoint = { x: x2, y: y2 } - let firstRoofLine, secondRoofLine - roof.lines - .filter((line) => { - if (ridgeVectorX === 0) { - return line.x1 !== line.x2 - } else { - return line.y1 !== line.y2 - } - }) - .forEach((line) => { - if (ridgeVectorX === 0) { - if (line.y1 === firstPoint.y) { - firstRoofLine = line - } - if (line.y1 === secondPoint.y) { - secondRoofLine = line - } - } else { - if (line.x1 === firstPoint.x) { - firstRoofLine = line - } - if (line.x1 === secondPoint.x) { - secondRoofLine = line - } - } - }) - /** 마루 1개에 (위,아래), (좌,우) 로 두가지의 지붕면이 생길 수 있다.*/ - let firstCheckPoints = [] - let secondCheckPoints = [] - - /** - * @param startPoint - * @param nextPoint - * @param endPoint - */ - const findPointToPolygon = (startPoint, nextPoint, endPoint) => { - let findPoint = nextPoint - const points = [startPoint, nextPoint] - let index = 1 - while (!(points[points.length - 1].x === endPoint.x && points[points.length - 1].y === endPoint.y)) { - const prevVector = { x: Math.sign(points[index - 1].x - points[index].x), y: Math.sign(points[index - 1].y - points[index].y) } - const currentPoint = points[index] - - const hipLine = baseHipLines.find( - (line) => - (line.line.x1 === currentPoint.x && line.line.y1 === currentPoint.y) || - (line.line.x2 === currentPoint.x && line.line.y2 === currentPoint.y), - ) - if (hipLine) { - if (hipLine.line.x1 === currentPoint.x && hipLine.line.y1 === currentPoint.y) { - points.push({ x: hipLine.line.x2, y: hipLine.line.y2 }) - } else { - points.push({ x: hipLine.line.x1, y: hipLine.line.y1 }) - } - } else { - const nextRoofLine = roof.lines.find((line) => { - if (prevVector.x !== 0) { - return ( - line.y1 !== line.y2 && - ((line.x1 <= currentPoint.x && currentPoint.x <= line.x2) || (line.x2 <= currentPoint.x && currentPoint.x <= line.x1)) - ) - } else { - return ( - line.x1 !== line.x2 && - ((line.y1 <= currentPoint.y && currentPoint.y <= line.y2) || (line.y2 <= currentPoint.y && currentPoint.y <= line.y1)) - ) - } - }) - const checkLine = new fabric.Line([nextRoofLine.x1, nextRoofLine.y1, nextRoofLine.x2, nextRoofLine.y2], { - stroke: 'yellow', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll() - - const lineEdge = { vertex1: { x: nextRoofLine.x1, y: nextRoofLine.y1 }, vertex2: { x: nextRoofLine.x2, y: nextRoofLine.y2 } } - let ridgeIntersection - baseGableRidgeLines.forEach((ridgeLine) => { - const ridgeEdge = { vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 }, vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 } } - const intersection = edgesIntersection(lineEdge, ridgeEdge) - console.log('intersection', intersection) - if (intersection && !intersection.isIntersectionOutside) { - ridgeIntersection = { x: intersection.x, y: intersection.y } - } - }) - if (ridgeIntersection) { - points.push(ridgeIntersection) - } else { - if (nextRoofLine.x1 === currentPoint.x && nextRoofLine.y1 === currentPoint.y) { - points.push({ x: nextRoofLine.x2, y: nextRoofLine.y2 }) - } else { - points.push({ x: nextRoofLine.x1, y: nextRoofLine.y1 }) - } - } - } - console.log('points', points, points[points.length - 1], endPoint) - index = index + 1 - } - - canvas - .getObjects() - .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkPoint') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() - return points - } - - let startVector - console.log('!firstRoofLine && !secondRoofLine', !firstRoofLine && !secondRoofLine) - let firstPoints, secondPoints - if (!firstRoofLine && !secondRoofLine) { + const uniqueRidgeLines = [] + /** 중복제거 */ + baseGableRidgeLines.forEach((currentLine, index) => { + if (index === 0) { + uniqueRidgeLines.push(currentLine) } else { - if (firstRoofLine) { - firstPoints = findPointToPolygon(firstPoint, { x: firstRoofLine.x1, y: firstRoofLine.y1 }, secondPoint) - secondPoints = findPointToPolygon(firstPoint, { x: firstRoofLine.x2, y: firstRoofLine.y2 }, secondPoint) - } else { - firstPoints = findPointToPolygon(secondPoint, { x: secondRoofLine.x1, y: secondRoofLine.y1 }, firstPoint) - secondPoints = findPointToPolygon(secondPoint, { x: secondRoofLine.x2, y: secondRoofLine.y2 }, firstPoint) - } - } - const firstPolygonPoints = getSortedPoint(firstPoints) - const secondPolygonPoints = getSortedPoint(secondPoints) - - firstPolygonPoints.forEach((point, index) => { - let endPoint - if (index === firstPolygonPoints.length - 1) { - endPoint = firstPolygonPoints[0] - } else { - endPoint = firstPolygonPoints[index + 1] - } - const hipLine = drawHipLine([point.x, point.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree) - baseHipLines.push({ x1: point.x, y1: point.y, x2: endPoint.x, y2: endPoint.y, line: hipLine }) - - const checkLine = new fabric.Line([point.x, point.y, endPoint.x, endPoint.y], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll() - }) - secondPolygonPoints.forEach((point, index) => { - let endPoint - if (index === secondPolygonPoints.length - 1) { - endPoint = secondPolygonPoints[0] - } else { - endPoint = secondPolygonPoints[index + 1] - } - const hipLine = drawHipLine([point.x, point.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree) - baseHipLines.push({ x1: point.x, y1: point.y, x2: endPoint.x, y2: endPoint.y, line: hipLine }) - - const checkLine = new fabric.Line([point.x, point.y, endPoint.x, endPoint.y], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll() - }) - }) - - drawGableFirstLines.forEach((current) => { - return - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - let { x1, x2, y1, y2, size } = currentBaseLine - let beforePrevBaseLine, afterNextBaseLine - - /** 이전 라인의 경사 */ - const prevDegree = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree - /** 다음 라인의 경사 */ - const nextDegree = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree - /** 현재 라인의 경사 */ - const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree - - /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */ - drawBaseLines.forEach((line, index) => { - if (line === prevBaseLine) { - beforePrevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - } - if (line === nextBaseLine) { - afterNextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length] - } - }) - - const beforePrevLine = beforePrevBaseLine?.line - const afterNextLine = afterNextBaseLine?.line - - /** 각 라인의 흐름 방향을 확인한다. */ - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - const beforePrevAngle = calculateAngle(beforePrevLine.startPoint, beforePrevLine.endPoint) - const afterNextAngle = calculateAngle(afterNextLine.startPoint, afterNextLine.endPoint) - - /** 이전라인의 vector*/ - const prevVectorX = Math.sign(Big(prevLine.x2).minus(Big(prevLine.x1))) - const prevVectorY = Math.sign(Big(prevLine.y2).minus(Big(prevLine.y1))) - - /** 현재라인의 기준점*/ - const currentMidX = Big(x1).plus(Big(x2)).div(2).plus(Big(prevVectorX).times(currentLine.attributes.offset)) - const currentMidY = Big(y1).plus(Big(y2)).div(2).plus(Big(prevVectorY).times(currentLine.attributes.offset)) - - if (beforePrevBaseLine === afterNextBaseLine) { - console.log('박공지붕 사각') - - const afterNextMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2) - const afterNextMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2) - const vectorMidX = Math.sign(currentMidX.minus(afterNextMidX)) - const vectorMidY = Math.sign(currentMidY.minus(afterNextMidY)) - - let oppositeMidX, oppositeMidY - if (eavesType.includes(afterNextLine.attributes?.type)) { - const checkSize = currentMidX - .minus(afterNextMidX) - .pow(2) - .plus(currentMidY.minus(afterNextMidY).pow(2)) - .sqrt() - .minus(Big(afterNextLine.attributes.planeSize).div(20)) - .round(1) - oppositeMidX = currentMidX.plus(checkSize.times(vectorMidX).neg()) - oppositeMidY = currentMidY.plus(checkSize.times(vectorMidY).neg()) - - const xVector1 = Math.sign(Big(oppositeMidX).minus(Big(afterNextLine.x1)).neg().toNumber()) - const yVector1 = Math.sign(Big(oppositeMidY).minus(Big(afterNextLine.y1)).neg().toNumber()) - const xVector2 = Math.sign(Big(oppositeMidX).minus(Big(afterNextLine.x2)).neg().toNumber()) - const yVector2 = Math.sign(Big(oppositeMidY).minus(Big(afterNextLine.y2)).neg().toNumber()) - - let addOppositeX1 = 0, - addOppositeY1 = 0, - addOppositeX2 = 0, - addOppositeY2 = 0 - - if (!checkWallPolygon.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) { - const checkScale = currentMidX.minus(oppositeMidX).pow(2).plus(currentMidY.minus(oppositeMidY).pow(2)).sqrt() - addOppositeX1 = checkScale.times(xVector1).toNumber() - addOppositeY1 = checkScale.times(yVector1).toNumber() - addOppositeX2 = checkScale.times(xVector2).toNumber() - addOppositeY2 = checkScale.times(yVector2).toNumber() - } - - let scale1 = Big(afterNextLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt() - scale1 = scale1.eq(0) ? Big(1) : scale1 - let scale2 = Big(afterNextLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt() - scale2 = scale2.eq(0) ? Big(1) : scale2 - - const checkHip1 = { - x1: Big(afterNextLine.x1).plus(scale1.times(xVector1)).toNumber(), - y1: Big(afterNextLine.y1).plus(scale1.times(yVector1)).toNumber(), - x2: oppositeMidX.plus(addOppositeX1).toNumber(), - y2: oppositeMidY.plus(addOppositeY1).toNumber(), - } - - const checkHip2 = { - x1: Big(afterNextLine.x2).plus(scale2.times(xVector2)).toNumber(), - y1: Big(afterNextLine.y2).plus(scale2.times(yVector2)).toNumber(), - x2: oppositeMidX.plus(addOppositeX2).toNumber(), - y2: oppositeMidY.plus(addOppositeY2).toNumber(), - } - - const intersection1 = findRoofIntersection(roof, checkHip1, { x: oppositeMidX.plus(addOppositeX1), y: oppositeMidY.plus(addOppositeY1) }) - const intersection2 = findRoofIntersection(roof, checkHip2, { x: oppositeMidX.plus(addOppositeX2), y: oppositeMidY.plus(addOppositeY2) }) - - const afterNextDegree = afterNextLine.attributes.pitch > 0 ? getDegreeByChon(afterNextLine.attributes.pitch) : afterNextLine.attributes.degree - - if (intersection1) { - const hipLine = drawHipLine( - [intersection1.intersection.x, intersection1.intersection.y, oppositeMidX.plus(addOppositeX1), oppositeMidY.plus(addOppositeY1)], - canvas, - roof, - textMode, - null, - nextDegree, - afterNextDegree, - ) - baseHipLines.push({ - x1: afterNextLine.x1, - y1: afterNextLine.y1, - x2: oppositeMidX.plus(addOppositeX1).toNumber(), - y2: oppositeMidY.plus(addOppositeY1).toNumber(), - line: hipLine, - }) - } - if (intersection2) { - const hipLine = drawHipLine( - [intersection2.intersection.x, intersection2.intersection.y, oppositeMidX.plus(addOppositeX2), oppositeMidY.plus(addOppositeY2)], - canvas, - roof, - textMode, - null, - prevDegree, - afterNextDegree, - ) - baseHipLines.push({ - x1: afterNextLine.x2, - y1: afterNextLine.y2, - x2: oppositeMidX.plus(addOppositeX2).toNumber(), - y2: oppositeMidY.plus(addOppositeY2).toNumber(), - line: hipLine, - }) - } - } else { - oppositeMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2).plus(Big(prevVectorX).neg().times(afterNextLine.attributes.offset)) - oppositeMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2).plus(Big(prevVectorY).neg().times(afterNextLine.attributes.offset)) - } - - const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX)) - const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY)) - - if (vectorMidX === vectorOppositeX && vectorMidY === vectorOppositeY && baseRidgeCount < getMaxRidge(baseLines.length)) { - const ridge = drawRidgeLine( - [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], - canvas, - roof, - textMode, - ) - baseRidgeLines.push(ridge) - baseRidgeCount++ - } - } else { - console.log('4각 아님') - const vectorMidX = Math.sign(Big(nextLine.x2).minus(nextLine.x1)) - const vectorMidY = Math.sign(Big(nextLine.y2).minus(nextLine.y1)) - let oppositeMidX = currentMidX, - oppositeMidY = currentMidY - let prevOppositeMidX, prevOppositeMidY, nextOppositeMidX, nextOppositeMidY - const beforePrevOffset = - currentAngle === beforePrevAngle - ? Big(beforePrevLine.attributes.offset) - : Big(beforePrevLine.attributes.offset).plus(currentLine.attributes.offset) - const afterNextOffset = - currentAngle === afterNextAngle - ? Big(afterNextLine.attributes.offset) - : Big(afterNextLine.attributes.offset).plus(currentLine.attributes.offset) - const prevSize = Big(prevLine.attributes.planeSize).div(10) - const nextSize = Big(nextLine.attributes.planeSize).div(10) - - /** 다음 라인이 그 다음 라인과의 사이에 추녀마루가 존재 하는지 확인. 처마-처마 인 경우 추녀마루*/ - if (eavesType.includes(afterNextLine.attributes?.type)) { - } else { - if (vectorMidX === 0) { - prevOppositeMidY = currentMidY.plus(prevSize.plus(beforePrevOffset).times(vectorMidY)) - prevOppositeMidX = currentMidX - } else { - prevOppositeMidX = currentMidX.plus(prevSize.plus(beforePrevOffset).times(vectorMidX)) - prevOppositeMidY = currentMidY - } - } - - /** 이전 라인이 그 이전 라인과의 사이에 추녀마루가 존재 하는지 확인. 처마-처마 인 경우 추녀마루*/ - if (eavesType.includes(beforePrevLine.attributes?.type)) { - } else { - if (vectorMidX === 0) { - nextOppositeMidY = currentMidY.plus(nextSize.plus(afterNextOffset).times(vectorMidY)) - nextOppositeMidX = currentMidX - } else { - nextOppositeMidX = currentMidX.plus(nextSize.plus(afterNextOffset).times(vectorMidX)) - nextOppositeMidY = currentMidY - } - } - - const checkPrevSize = currentMidX.minus(prevOppositeMidX).pow(2).plus(currentMidY.minus(prevOppositeMidY).pow(2)).sqrt() - const checkNextSize = currentMidX.minus(nextOppositeMidX).pow(2).plus(currentMidY.minus(nextOppositeMidY).pow(2)).sqrt() - - /** 두 포인트 중에 current와 가까운 포인트를 사용*/ - if (checkPrevSize.gt(checkNextSize)) { - oppositeMidY = nextOppositeMidY - oppositeMidX = nextOppositeMidX - } else { - oppositeMidY = prevOppositeMidY - oppositeMidX = prevOppositeMidX - } - - if (baseRidgeCount < getMaxRidge(baseLines.length)) { - const ridgeLine = drawRidgeLine([currentMidX, currentMidY, oppositeMidX, oppositeMidY], canvas, roof, textMode) - baseRidgeLines.push(ridgeLine) - baseRidgeCount++ + const duplicateLines = uniqueRidgeLines.filter( + (line) => + (currentLine.x1 === line.x1 && currentLine.y1 === line.y1 && currentLine.x2 === line.x2 && currentLine.y2 === line.y2) || + (currentLine.x1 === line.x2 && currentLine.y1 === line.y2 && currentLine.x2 === line.x1 && currentLine.y2 === line.y1), + ) + if (duplicateLines.length === 0) { + uniqueRidgeLines.push(currentLine) } } }) + baseGableRidgeLines = uniqueRidgeLines + + console.log('baseGableRidgeLines : ', baseGableRidgeLines) + /** 박공지붕 polygon 생성 */ drawGablePolygonFirst.forEach((current) => { const { currentBaseLine, prevBaseLine, nextBaseLine } = current @@ -2093,14 +1712,24 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { roofY2 = roofY1 } - const prevRoofLine = roof.lines.find( - (line) => currentVectorX !== Math.sign(line.x2 - line.x1) && line.x2 === roofX1.toNumber() && line.y2 === roofY1.toNumber(), - ) - const nextRoofLine = roof.lines.find( - (line) => currentVectorX !== Math.sign(line.x2 - line.x1) && line.x1 === roofX2.toNumber() && line.y1 === roofY2.toNumber(), - ) + let prevRoofLine, nextRoofLine + const roofEdge = { vertex1: { x: roofX1.toNumber(), y: roofY1.toNumber() }, vertex2: { x: roofX2.toNumber(), y: roofY2.toNumber() } } + roof.lines + .filter((line) => (currentVectorX === 0 ? line.y1 === line.y2 : line.x1 === line.x2)) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const intersection = edgesIntersection(roofEdge, lineEdge) + if (intersection) { + if (roofX1.eq(intersection.x) && roofY1.eq(intersection.y)) { + prevRoofLine = line + } + if (roofX2.eq(intersection.x) && roofY2.eq(intersection.y)) { + nextRoofLine = line + } + } + }) - const prevRoofEdge = { vertex1: { x: prevRoofLine.x1, y: prevRoofLine.y1 }, vertex2: { x: prevRoofLine.x2, y: prevRoofLine.y2 } } + const prevRoofEdge = { vertex1: { x: prevRoofLine.x2, y: prevRoofLine.y2 }, vertex2: { x: prevRoofLine.x1, y: prevRoofLine.y1 } } const nextRoofEdge = { vertex1: { x: nextRoofLine.x1, y: nextRoofLine.y1 }, vertex2: { x: nextRoofLine.x2, y: nextRoofLine.y2 } } baseGableRidgeLines.forEach((ridge) => { @@ -2110,21 +1739,18 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { if (prevIs) { prevLineRidges.push({ ridge, - size: calcLinePlaneSize({ x1: ridgeEdge.vertex1.x, y1: ridgeEdge.vertex1.y, x2: prevIs.x, y2: prevIs.y }), + size: calcLinePlaneSize({ x1: roofX1, y1: roofY1, x2: prevIs.x, y2: prevIs.y }), }) } if (nextIs) { nextLineRidges.push({ ridge, - size: calcLinePlaneSize({ x1: ridgeEdge.vertex1.x, y1: ridgeEdge.vertex1.y, x2: nextIs.x, y2: nextIs.y }), + size: calcLinePlaneSize({ x1: roofX2, y1: roofY2, x2: nextIs.x, y2: nextIs.y }), }) } }) - const polygonPoints = [ - { x: roofX1.toNumber(), y: roofY1.toNumber() }, - { x: roofX2.toNumber(), y: roofY2.toNumber() }, - ] + const polygonPoints = [] let prevLineRidge, nextLineRidge if (prevLineRidges.length > 0) { @@ -2154,9 +1780,44 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { nextLineRidge = nextLineRidges[0].ridge } + /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/ + let checkEdge + if (currentVectorX === 0) { + checkEdge = { vertex1: { x: prevLineRidge.x1, y: roofY1.toNumber() }, vertex2: { x: roofX1.toNumber(), y: roofY1.toNumber() } } + } else { + checkEdge = { vertex1: { x: roofX1.toNumber(), y: prevLineRidge.y1 }, vertex2: { x: roofX1.toNumber(), y: roofY1.toNumber() } } + } + const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) + const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) + const intersectPoints = [] + roof.lines + .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const is = edgesIntersection(checkEdge, lineEdge) + if (is) { + const isVectorX = Math.sign(checkEdge.vertex1.x - is.x) + const isVectorY = Math.sign(checkEdge.vertex1.y - is.y) + const isLineOtherPoint = is.x === line.x1 && is.y === line.y1 ? { x: line.x2, y: line.y2 } : { x: line.x1, y: line.y1 } + const lineVectorX = Math.sign(isLineOtherPoint.x - is.x) + const lineVectorY = Math.sign(isLineOtherPoint.y - is.y) + if (checkVectorX === isVectorX && checkVectorY === isVectorY && lineVectorX === currentVectorX && lineVectorY === currentVectorY) { + intersectPoints.push(is) + } + } + }) + let intersect = intersectPoints[0] + if (currentVectorX === 0) { + polygonPoints.push({ x: intersect.x, y: roofY1.toNumber() }, { x: intersect.x, y: roofY2.toNumber() }) + } else { + polygonPoints.push({ x: roofX1.toNumber(), y: intersect.y }, { x: roofX2.toNumber(), y: intersect.y }) + } + if (prevLineRidge === nextLineRidge) { + /** 4각*/ polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 }) } else { + /** 6각이상*/ let isOverLap = currentVectorX === 0 ? (prevLineRidge.y1 <= nextLineRidge.y1 && prevLineRidge.y2 >= nextLineRidge.y1) || @@ -2167,12 +1828,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) || (prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) || (prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2) - console.log('isOverLap : ', isOverLap) if (isOverLap) { const prevDistance = currentVectorX === 0 ? Math.abs(prevLineRidge.x1 - roofX1.toNumber()) : Math.abs(prevLineRidge.y1 - roofY1.toNumber()) const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - roofX1.toNumber()) : Math.abs(nextLineRidge.y1 - roofY1.toNumber()) /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */ - if (prevDistance < nextDistance) { + if (prevDistance === nextDistance) { + console.log('prevDistance === nextDistance') + } else if (prevDistance < nextDistance) { polygonPoints.push({ x: nextLineRidge.x1, y: nextLineRidge.y1 }, { x: nextLineRidge.x2, y: nextLineRidge.y2 }) /** 이전라인과 교차한 마루의 포인트*/ const prevRidgePoint1 = @@ -2227,11 +1889,178 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { polygonPoints.push(nextRidgePoint2) } } else { + /** 마루가 겹치지 않을때 */ + const otherRidgeLines = [] + + baseGableRidgeLines + .filter((ridge) => ridge !== prevLineRidge && ridge !== nextLineRidge) + .filter((ridge) => (currentVectorX === 0 ? ridge.x1 === ridge.x2 : ridge.y1 === ridge.y2)) + .filter((ridge) => + currentVectorX === 0 ? nextVectorX === Math.sign(nextLine.x1 - ridge.x1) : nextVectorY === Math.sign(nextLine.y1 - ridge.y1), + ) + .forEach((ridge) => { + const size = currentVectorX === 0 ? Math.abs(nextLine.x1 - ridge.x1) : Math.abs(nextLine.y1 - ridge.y1) + otherRidgeLines.push({ ridge, size }) + }) + if (otherRidgeLines.length > 0) { + const otherRidge = otherRidgeLines.sort((a, b) => a.size - b.size)[0].ridge + /** + * otherRidge이 prevRidgeLine, nextRidgeLine 과 currentLine의 사이에 있는지 확인해서 분할하여 작업 + * 지붕의 덮힘이 다르기 때문 + */ + const isInside = + currentVectorX === 0 + ? Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - prevLineRidge.x1) && + Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - nextLineRidge.x1) + : Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - prevLineRidge.y1) && + Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - nextLineRidge.y1) + + if (isInside) { + polygonPoints.push( + { x: prevLineRidge.x1, y: prevLineRidge.y1 }, + { x: prevLineRidge.x2, y: prevLineRidge.y2 }, + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { x: nextLineRidge.x2, y: nextLineRidge.y2 }, + ) + + let ridgeAllPoints = [ + { x: prevLineRidge.x1, y: prevLineRidge.y1 }, + { x: prevLineRidge.x2, y: prevLineRidge.y2 }, + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { x: nextLineRidge.x2, y: nextLineRidge.y2 }, + ] + let ridgePoints = [] + ridgeAllPoints.forEach((point) => { + let isOnLine = false + roof.lines.forEach((line) => { + if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { + isOnLine = true + } + }) + if (!isOnLine) { + ridgePoints.push(point) + } + }) + if (ridgePoints.length === 2) { + if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { + polygonPoints.push({ x: otherRidge.x1, y: ridgePoints[0].y }, { x: otherRidge.x1, y: ridgePoints[1].y }) + } else { + polygonPoints.push({ x: ridgePoints[0].x, y: otherRidge.y1 }, { x: ridgePoints[1].x, y: otherRidge.y1 }) + } + } + } else { + polygonPoints.push({ x: otherRidge.x1, y: otherRidge.y1 }, { x: otherRidge.x2, y: otherRidge.y2 }) + + let ridgePoints = [ + { x: prevLineRidge.x1, y: prevLineRidge.y1 }, + { x: prevLineRidge.x2, y: prevLineRidge.y2 }, + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { x: nextLineRidge.x2, y: nextLineRidge.y2 }, + ] + + ridgePoints.forEach((point) => { + let isOnLine = false + roof.lines.forEach((line) => { + if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { + isOnLine = true + } + }) + if (isOnLine) { + polygonPoints.push(point) + } + }) + + if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { + const prevY = + (prevLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= prevLineRidge.y2) || + (prevLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= prevLineRidge.y2) + ? otherRidge.y1 + : otherRidge.y2 + const nextY = + (nextLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= nextLineRidge.y2) || + (nextLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= nextLineRidge.y2) + ? otherRidge.y1 + : otherRidge.y2 + polygonPoints.push({ x: prevLineRidge.x1, y: prevY }, { x: nextLineRidge.x1, y: nextY }) + } else { + const prevX = + (prevLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= prevLineRidge.x2) || + (prevLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= prevLineRidge.x2) + ? otherRidge.x1 + : otherRidge.x2 + const nextX = + (nextLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= nextLineRidge.x2) || + (nextLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= nextLineRidge.x2) + ? otherRidge.x1 + : otherRidge.x2 + polygonPoints.push({ x: prevX, y: prevLineRidge.y1 }, { x: nextX, y: nextLineRidge.y1 }) + } + } + } } } const sortedPolygonPoints = getSortedPoint(polygonPoints) + /** 외벽선 밖으로 나가있는 포인트*/ + const outsidePoints = polygonPoints.filter((point) => { + let isOutside = true + roof.lines.forEach((line) => { + if ( + (line.x1 <= point.x && line.x2 >= point.x && line.y1 <= point.y && line.y2 >= point.y) || + (line.x1 >= point.x && line.x2 <= point.x && line.y1 >= point.y && line.y2 <= point.y) + ) { + isOutside = false + } + }) + baseGableRidgeLines.forEach((line) => { + if ( + (line.x1 <= point.x && line.x2 >= point.x && line.y1 <= point.y && line.y2 >= point.y) || + (line.x1 >= point.x && line.x2 <= point.x && line.y1 >= point.y && line.y2 <= point.y) + ) { + isOutside = false + } + }) + return isOutside + }) + + if (outsidePoints.length > 0) { + sortedPolygonPoints.forEach((currentPoint, index) => { + if (outsidePoints.includes(currentPoint)) { + const prevPoint = sortedPolygonPoints[(index - 1 + sortedPolygonPoints.length) % sortedPolygonPoints.length] + const nextPoint = sortedPolygonPoints[(index + 1) % sortedPolygonPoints.length] + const vectorX = Math.sign(currentPoint.x - prevPoint.x) + const vectorY = Math.sign(currentPoint.y - prevPoint.y) + + const checkEdge = { vertex1: { x: prevPoint.x, y: prevPoint.y }, vertex2: { x: currentPoint.x, y: currentPoint.y } } + const intersectPoints = [] + roof.lines + .filter((line) => (vectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const is = edgesIntersection(checkEdge, lineEdge) + if (is && !is.isIntersectionOutside) { + const isVectorX = Math.sign(is.x - prevPoint.x) + const isVectorY = Math.sign(is.y - prevPoint.y) + if ((vectorX === 0 && vectorY === isVectorY) || (vectorY === 0 && vectorX === isVectorX)) { + intersectPoints.push(is) + } + } + }) + if (intersectPoints.length > 0) { + const intersection = intersectPoints[0] + if (vectorX === 0) { + currentPoint.y = intersection.y + nextPoint.y = intersection.y + } else { + currentPoint.x = intersection.x + nextPoint.x = intersection.x + } + } + } + }) + } + sortedPolygonPoints.forEach((startPoint, index) => { let endPoint if (index === sortedPolygonPoints.length - 1) { @@ -2239,6 +2068,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } else { endPoint = sortedPolygonPoints[index + 1] } + const hipLine = drawHipLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree) if (currentVectorX === 0) { if (Math.sign(startPoint.x - endPoint.x) === 0) { @@ -2251,12 +2081,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } baseHipLines.push({ x1: hipLine.x1, y1: hipLine.y1, x2: hipLine.x2, y2: hipLine.y2, line: hipLine }) }) - - canvas - .getObjects() - .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkRoofLine') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() }) drawGablePolygonSecond.forEach((current) => { @@ -2279,100 +2103,182 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const prevOffset = prevLine.attributes.offset const nextOffset = nextLine.attributes.offset - const prevEdge = { vertex1: { x: prevLine.x1, y: prevLine.y1 }, vertex2: { x: prevLine.x2, y: prevLine.y2 } } - const prevRidge = baseGableRidgeLines.find((ridge) => { - const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } - const is = edgesIntersection(prevEdge, ridgeEdge) - if (is && !is.isIntersectionOutside) { - return ridge - } - }) + const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) + const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - const nextEdge = { vertex1: { x: nextLine.x1, y: nextLine.y1 }, vertex2: { x: nextLine.x2, y: nextLine.y2 } } - const nextRidge = baseGableRidgeLines.find((ridge) => { - const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } - const is = edgesIntersection(nextEdge, ridgeEdge) - if (is && !is.isIntersectionOutside) { - return ridge - } - }) + const polygonPoints = [] + if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) { + const currentRidge = baseGableRidgeLines.find((line) => + currentVectorX === 0 + ? (line.y1 === y1 && line.y2 === y2) || (line.y1 === y2 && line.y2 === y1) + : (line.x1 === x1 && line.x2 === x2) || (line.x1 === x2 && line.x2 === x1), + ) + if (currentRidge) { + const ridgeVectorX = Math.sign(currentRidge.x1 - currentRidge.x2) + const ridgeVectorY = Math.sign(currentRidge.y1 - currentRidge.y2) - let currentRidge - - if (prevRidge) { - if ( - currentVectorX === 0 && - ((prevRidge.y1 <= currentLine.y1 && prevRidge.y2 >= currentLine.y1 && prevRidge.y1 <= currentLine.y2 && prevRidge.y2 >= currentLine.y2) || - (prevRidge.y1 >= currentLine.y1 && prevRidge.y2 <= currentLine.y1 && prevRidge.y1 >= currentLine.y2 && prevRidge.y2 <= currentLine.y2)) - ) { - currentRidge = prevRidge - } - if ( - currentVectorY === 0 && - ((prevRidge.x1 <= currentLine.x1 && prevRidge.x2 >= currentLine.x1 && prevRidge.x1 <= currentLine.x2 && prevRidge.x2 >= currentLine.x2) || - (prevRidge.x1 >= currentLine.x1 && prevRidge.x2 <= currentLine.x1 && prevRidge.x1 >= currentLine.x2 && prevRidge.x2 <= currentLine.x2)) - ) { - currentRidge = prevRidge - } - } - if (nextRidge) { - if ( - currentVectorX === 0 && - ((nextRidge.y1 <= currentLine.y1 && nextRidge.y2 >= currentLine.y1 && nextRidge.y1 <= currentLine.y2 && nextRidge.y2 >= currentLine.y2) || - (nextRidge.y1 >= currentLine.y1 && nextRidge.y2 <= currentLine.y1 && nextRidge.y1 >= currentLine.y2 && nextRidge.y2 <= currentLine.y2)) - ) { - currentRidge = nextRidge - } - if ( - currentVectorY === 0 && - ((nextRidge.x1 <= currentLine.x1 && nextRidge.x2 >= currentLine.x1 && nextRidge.x1 <= currentLine.x2 && nextRidge.x2 >= currentLine.x2) || - (nextRidge.x1 >= currentLine.x1 && nextRidge.x2 <= currentLine.x1 && nextRidge.x1 >= currentLine.x2 && nextRidge.x2 <= currentLine.x2)) - ) { - currentRidge = nextRidge - } - } - if (currentRidge) { - const vectorX = currentVectorX === 0 ? Math.sign(currentLine.x1 - currentRidge.x1) : 0 - const vectorY = currentVectorY === 0 ? Math.sign(currentLine.y1 - currentRidge.y1) : 0 - - const polygonPoints = [ - { x: currentRidge.x1, y: currentRidge.y1 }, - { x: currentRidge.x2, y: currentRidge.y2 }, - ] - if (currentVectorX === 0) { - polygonPoints.push( - { x: Big(currentLine.x1).plus(Big(currentOffset).times(vectorX)).toNumber(), y: currentRidge.y1 }, - { x: Big(currentLine.x2).plus(Big(currentOffset).times(vectorX)).toNumber(), y: currentRidge.y2 }, - ) - } else { - polygonPoints.push( - { x: currentRidge.x1, y: Big(currentLine.y1).plus(Big(currentOffset).times(vectorY)).toNumber() }, - { x: currentRidge.x2, y: Big(currentLine.y2).plus(Big(currentOffset).times(vectorY)).toNumber() }, - ) - } - - const sortedPolygonPoints = getSortedPoint(polygonPoints) - - sortedPolygonPoints.forEach((startPoint, index) => { - let endPoint - if (index === sortedPolygonPoints.length - 1) { - endPoint = sortedPolygonPoints[0] - } else { - endPoint = sortedPolygonPoints[index + 1] - } - const hipLine = drawHipLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree) + let checkEdge if (currentVectorX === 0) { - if (Math.sign(startPoint.x - endPoint.x) === 0) { - hipLine.attributes.actualSize = hipLine.attributes.planeSize + checkEdge = { vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, vertex2: { x: currentLine.x1, y: currentRidge.y1 } } + } else { + checkEdge = { vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, vertex2: { x: currentRidge.x1, y: currentLine.y1 } } + } + const isRoofLines = [] + roof.lines + .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const is = edgesIntersection(checkEdge, lineEdge) + if (is) { + const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) + const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) + const isVectorX = Math.sign(checkEdge.vertex1.x - is.x) + const isVectorY = Math.sign(checkEdge.vertex1.y - is.y) + if ((ridgeVectorX === 0 && checkVectorX === isVectorX) || (ridgeVectorY === 0 && checkVectorY === isVectorY)) { + const size = ridgeVectorX === 0 ? Math.abs(checkEdge.vertex1.x - is.x) : Math.abs(checkEdge.vertex1.y - is.y) + isRoofLines.push({ line, size }) + } + } + }) + isRoofLines.sort((a, b) => a.size - b.size) + const roofLine = isRoofLines[0].line + polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 }) + if (ridgeVectorX === 0) { + polygonPoints.push({ x: roofLine.x1, y: currentRidge.y1 }, { x: roofLine.x1, y: currentRidge.y2 }) + } else { + polygonPoints.push({ x: currentRidge.x1, y: roofLine.y1 }, { x: currentRidge.x2, y: roofLine.y1 }) + } + } + } else { + const prevEdge = { vertex1: { x: prevLine.x1, y: prevLine.y1 }, vertex2: { x: prevLine.x2, y: prevLine.y2 } } + const prevRidge = baseGableRidgeLines.find((ridge) => { + const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } + const is = edgesIntersection(prevEdge, ridgeEdge) + if (is && !is.isIntersectionOutside) { + return ridge + } + }) + + const nextEdge = { vertex1: { x: nextLine.x1, y: nextLine.y1 }, vertex2: { x: nextLine.x2, y: nextLine.y2 } } + const nextRidge = baseGableRidgeLines.find((ridge) => { + const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } + const is = edgesIntersection(nextEdge, ridgeEdge) + if (is && !is.isIntersectionOutside) { + return ridge + } + }) + + let currentRidge + + if (prevRidge) { + if ( + currentVectorX === 0 && + ((prevRidge.y1 <= currentLine.y1 && prevRidge.y2 >= currentLine.y1 && prevRidge.y1 <= currentLine.y2 && prevRidge.y2 >= currentLine.y2) || + (prevRidge.y1 >= currentLine.y1 && prevRidge.y2 <= currentLine.y1 && prevRidge.y1 >= currentLine.y2 && prevRidge.y2 <= currentLine.y2)) + ) { + currentRidge = prevRidge + } + if ( + currentVectorY === 0 && + ((prevRidge.x1 <= currentLine.x1 && prevRidge.x2 >= currentLine.x1 && prevRidge.x1 <= currentLine.x2 && prevRidge.x2 >= currentLine.x2) || + (prevRidge.x1 >= currentLine.x1 && prevRidge.x2 <= currentLine.x1 && prevRidge.x1 >= currentLine.x2 && prevRidge.x2 <= currentLine.x2)) + ) { + currentRidge = prevRidge + } + } + if (nextRidge) { + if ( + currentVectorX === 0 && + ((nextRidge.y1 <= currentLine.y1 && nextRidge.y2 >= currentLine.y1 && nextRidge.y1 <= currentLine.y2 && nextRidge.y2 >= currentLine.y2) || + (nextRidge.y1 >= currentLine.y1 && nextRidge.y2 <= currentLine.y1 && nextRidge.y1 >= currentLine.y2 && nextRidge.y2 <= currentLine.y2)) + ) { + currentRidge = nextRidge + } + if ( + currentVectorY === 0 && + ((nextRidge.x1 <= currentLine.x1 && nextRidge.x2 >= currentLine.x1 && nextRidge.x1 <= currentLine.x2 && nextRidge.x2 >= currentLine.x2) || + (nextRidge.x1 >= currentLine.x1 && nextRidge.x2 <= currentLine.x1 && nextRidge.x1 >= currentLine.x2 && nextRidge.x2 <= currentLine.x2)) + ) { + currentRidge = nextRidge + } + } + if (currentRidge) { + polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 }) + + /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/ + let checkEdge + if (currentVectorX === 0) { + checkEdge = { + vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, + vertex2: { x: currentLine.x1, y: currentRidge.y1 }, } } else { - if (Math.sign(startPoint.y - endPoint.y) === 0) { - hipLine.attributes.actualSize = hipLine.attributes.planeSize + checkEdge = { + vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, + vertex2: { x: currentRidge.x1, y: currentLine.y1 }, } } - baseHipLines.push({ x1: hipLine.x1, y1: hipLine.y1, x2: hipLine.x2, y2: hipLine.y2, line: hipLine }) - }) + + const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) + const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) + const intersectPoints = [] + roof.lines + .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const is = edgesIntersection(checkEdge, lineEdge) + if (is) { + const isVectorX = Math.sign(checkEdge.vertex1.x - is.x) + const isVectorY = Math.sign(checkEdge.vertex1.y - is.y) + const isLineOtherPoint = + is.x === line.x1 && is.y === line.y1 + ? { x: line.x2, y: line.y2 } + : { + x: line.x1, + y: line.y1, + } + const isInPoint = + checkVectorX === 0 + ? (currentRidge.x1 <= isLineOtherPoint.x && isLineOtherPoint.x <= currentRidge.x2) || + (currentRidge.x1 >= isLineOtherPoint.x && isLineOtherPoint.x >= currentRidge.x2) + : (currentRidge.y1 <= isLineOtherPoint.y && isLineOtherPoint.y <= currentRidge.y2) || + (currentRidge.y1 >= isLineOtherPoint.y && isLineOtherPoint.y >= currentRidge.y2) + if (checkVectorX === isVectorX && checkVectorY === isVectorY && isInPoint) { + const size = Big(checkEdge.vertex1.x).minus(is.x).abs().pow(2).plus(Big(checkEdge.vertex1.y).minus(is.y).abs().pow(2)).sqrt() + intersectPoints.push({ is, size }) + } + } + }) + intersectPoints.sort((a, b) => a.size - b.size) + let intersect = intersectPoints[0].is + if (currentVectorX === 0) { + polygonPoints.push({ x: intersect.x, y: currentRidge.y1 }, { x: intersect.x, y: currentRidge.y2 }) + } else { + polygonPoints.push({ x: currentRidge.x1, y: intersect.y }, { x: currentRidge.x2, y: intersect.y }) + } + } } + + const sortedPolygonPoints = getSortedPoint(polygonPoints) + sortedPolygonPoints.forEach((startPoint, index) => { + let endPoint + if (index === sortedPolygonPoints.length - 1) { + endPoint = sortedPolygonPoints[0] + } else { + endPoint = sortedPolygonPoints[index + 1] + } + const hipLine = drawHipLine([startPoint.x, startPoint.y, endPoint.x, endPoint.y], canvas, roof, textMode, null, currentDegree, currentDegree) + if (currentVectorX === 0) { + if (Math.sign(startPoint.x - endPoint.x) === 0) { + hipLine.attributes.actualSize = hipLine.attributes.planeSize + } + } else { + if (Math.sign(startPoint.y - endPoint.y) === 0) { + hipLine.attributes.actualSize = hipLine.attributes.planeSize + } + } + baseHipLines.push({ x1: hipLine.x1, y1: hipLine.y1, x2: hipLine.x2, y2: hipLine.y2, line: hipLine }) + }) }) /** ⨆ 모양 처마에 추녀마루를 그린다. */ @@ -4716,7 +4622,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { }) const innerLines = [...baseRidgeLines, ...baseGableRidgeLines, ...baseHipLines.map((line) => line.line)] - const uniqueInnerLines = [] + roof.innerLines = innerLines + /*const uniqueInnerLines = [] innerLines.forEach((currentLine) => { const sameLines = uniqueInnerLines.filter( @@ -4733,7 +4640,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) canvas.renderAll() - roof.innerLines = uniqueInnerLines + roof.innerLines = uniqueInnerLines*/ /** 확인용 라인, 포인트 제거 */ canvas @@ -7729,18 +7636,20 @@ const getSortedPoint = (points) => { let prevPoint = startPoint for (let i = 0; i < points.length - 1; i++) { + const samePoints = [] points .filter((point) => !sortedPoints.includes(point)) .forEach((point) => { if (i % 2 === 1 && prevPoint.y === point.y) { - sortedPoints.push(point) - prevPoint = point + samePoints.push({ point, size: Math.abs(point.x - prevPoint.x) }) } if (i % 2 === 0 && prevPoint.x === point.x) { - sortedPoints.push(point) - prevPoint = point + samePoints.push({ point, size: Math.abs(point.y - prevPoint.y) }) } }) + const samePoint = samePoints.sort((a, b) => a.size - b.size)[0].point + sortedPoints.push(samePoint) + prevPoint = samePoint } return sortedPoints }