From 410da6f541032f14b63a8330b755c13bee4b5d65 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 15 May 2025 16:00:40 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=B3=B4=EC=A1=B0?= =?UTF-8?q?=EC=84=A0=20=EC=9E=91=EC=84=B1=20=EC=88=98=EC=A0=95=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 563 +++++++++++++++++++++++++++---------- 1 file changed, 413 insertions(+), 150 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 3082e682..bf5c8b97 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -879,6 +879,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const currentLine = currentBaseLine.line const prevLine = prevBaseLine.line const nextLine = nextBaseLine.line + const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) @@ -918,7 +919,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) } } else if (gableType.includes(nextLine.attributes?.type) && gableType.includes(prevLine.attributes?.type)) { - console.log('currentLine :', currentBaseLine.size, 'prevAngle :', prevAngle, 'nextAngle :', nextAngle) if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) { const checkPoints = { x: currentMidX.plus(checkScale.times(Math.sign(xVector.toNumber()))).toNumber(), @@ -934,7 +934,9 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) // } } else { - drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) + if (currentAngle !== prevAngle && currentAngle !== nextAngle) { + drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) + } } } } @@ -1034,44 +1036,158 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const nextVectorY = Math.sign(Big(nextLine.y2).minus(Big(nextLine.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)) + let currentMidX = Big(x1).plus(Big(x2)).div(2).plus(Big(prevVectorX).times(currentLine.attributes.offset)) + let currentMidY = Big(y1).plus(Big(y2)).div(2).plus(Big(prevVectorY).times(currentLine.attributes.offset)) /** 마루 반대 좌표*/ let oppositeMidX = currentMidX, oppositeMidY = currentMidY + /** 한개의 지붕선을 둘로 나누어서 처리 하는 경우 */ if (prevAngle === beforePrevAngle || nextAngle === afterNextAngle) { - console.log('지붕선 분할 : start') - const checkLine1 = new fabric.Line([prevLine.x1, prevLine.y1, prevLine.x2, prevLine.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - const checkLine2 = new fabric.Line([nextLine.x1, nextLine.y1, nextLine.x2, nextLine.y2], { - stroke: 'blue', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - const checkPoint = new fabric.Circle({ - left: currentMidX.toNumber(), - top: currentMidY.toNumber(), - radius: 5, - fill: 'red', - parentId: roofId, - name: 'checkPoint', - }) - canvas.add(checkLine1) - canvas.add(checkLine2) - canvas.add(checkPoint) - canvas.renderAll() - if (currentVectorX === 0) { + const addLength = Big(currentLine.y1).minus(Big(currentLine.y2)).abs().div(2) + const ridgeVector = Math.sign(prevLine.x1 - currentLine.x1) + oppositeMidX = Big(prevLine.x1).plus(Big(addLength).times(ridgeVector)) + + const ridgeEdge = { + vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, + vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + } + + const ridgeVectorX = Math.sign(ridgeEdge.vertex1.x - ridgeEdge.vertex2.x) + roof.lines + .filter((line) => line.x1 === line.x2) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const is = edgesIntersection(ridgeEdge, lineEdge) + if (is) { + const isVectorX = Math.sign(ridgeEdge.vertex1.x - is.x) + if ( + isVectorX === ridgeVectorX && + ((line.x1 <= currentMidX && line.x2 >= currentMidX) || (line.x2 <= currentMidX && line.x1 >= currentMidX)) + ) { + currentMidX = Big(is.x) + currentMidY = Big(is.y) + } + } + }) } else { + const addLength = Big(currentLine.x1).minus(Big(currentLine.x2)).abs().div(2) + const ridgeVector = Math.sign(prevLine.y1 - currentLine.y1) + oppositeMidY = Big(prevLine.y1).plus(addLength.times(ridgeVector)) + + const ridgeEdge = { + vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, + vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + } + const ridgeVectorY = Math.sign(ridgeEdge.vertex1.y - ridgeEdge.vertex2.y) + roof.lines + .filter((line) => 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(ridgeEdge, lineEdge) + if (is) { + const isVectorY = Math.sign(ridgeEdge.vertex1.y - is.y) + if ( + isVectorY === ridgeVectorY && + ((line.x1 <= currentMidX && line.x2 >= currentMidX) || (line.x2 <= currentMidX && line.x1 >= currentMidX)) + ) { + currentMidX = Big(is.x) + currentMidY = Big(is.y) + } + } + }) } + const prevHipEdge = { vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, vertex2: { x: prevLine.x1, y: prevLine.y1 } } + const prevHipVectorX = Math.sign(prevHipEdge.vertex1.x - prevHipEdge.vertex2.x) + const prevHipVectorY = Math.sign(prevHipEdge.vertex1.y - prevHipEdge.vertex2.y) + const prevIsPoints = [] + roof.lines + .filter((line) => (Math.sign(prevLine.x1 - prevLine.x2) === 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(prevHipEdge, lineEdge) + if (is) { + const isVectorX = Math.sign(prevHipEdge.vertex1.x - is.x) + const isVectorY = Math.sign(prevHipEdge.vertex1.y - is.y) + if (isVectorX === prevHipVectorX && isVectorY === prevHipVectorY) { + const size = Big(prevHipEdge.vertex1.x) + .minus(Big(is.x)) + .abs() + .pow(2) + .plus(Big(prevHipEdge.vertex1.y).minus(Big(is.y)).abs().pow(2)) + .sqrt() + .toNumber() + prevIsPoints.push({ is, size }) + } + } + }) + + if (prevIsPoints.length > 0) { + const prevIs = prevIsPoints.sort((a, b) => a.size - b.size)[0].is + const prevHipLine = drawHipLine( + [prevIs.x, prevIs.y, oppositeMidX.toNumber(), oppositeMidY.toNumber()], + canvas, + roof, + textMode, + null, + prevDegree, + prevDegree, + ) + baseHipLines.push({ x1: prevLine.x1, y1: prevLine.y1, x2: oppositeMidX.toNumber(), y2: oppositeMidY.toNumber(), line: prevHipLine }) + } + + const nextHipEdge = { vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, vertex2: { x: nextLine.x2, y: nextLine.y2 } } + const nextHipVectorX = Math.sign(nextHipEdge.vertex1.x - nextHipEdge.vertex2.x) + const nextHipVectorY = Math.sign(nextHipEdge.vertex1.y - nextHipEdge.vertex2.y) + const nextIsPoints = [] + + roof.lines + .filter((line) => (Math.sign(nextLine.x1 - nextLine.x2) === 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(nextHipEdge, lineEdge) + if (is) { + const isVectorX = Math.sign(nextHipEdge.vertex1.x - is.x) + const isVectorY = Math.sign(nextHipEdge.vertex1.y - is.y) + if (isVectorX === nextHipVectorX && isVectorY === nextHipVectorY) { + const size = Big(nextHipEdge.vertex1.x) + .minus(Big(is.x)) + .abs() + .pow(2) + .plus(Big(nextHipEdge.vertex1.y).minus(Big(is.y)).abs().pow(2)) + .sqrt() + .toNumber() + nextIsPoints.push({ is, size }) + } + } + }) + if (nextIsPoints.length > 0) { + const nextIs = nextIsPoints.sort((a, b) => a.size - b.size)[0].is + const nextHipLine = drawHipLine( + [nextIs.x, nextIs.y, oppositeMidX.toNumber(), oppositeMidY.toNumber()], + canvas, + roof, + textMode, + null, + nextDegree, + nextDegree, + ) + baseHipLines.push({ x1: nextLine.x2, y1: nextLine.y2, x2: oppositeMidX.toNumber(), y2: oppositeMidY.toNumber(), line: nextHipLine }) + } + + if (baseRidgeCount < getMaxRidge(baseLines.length)) { + const ridgeLine = drawRidgeLine( + [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], + canvas, + roof, + textMode, + ) + baseGableRidgeLines.push(ridgeLine) + baseRidgeCount++ + } console.log('지붕선 분할 : end') } else { if (beforePrevBaseLine === afterNextBaseLine) { @@ -1236,7 +1352,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { y: currentMidY.plus(Big(nextVectorY).times(nextBaseLine.size)).toNumber(), }, } - let hipEdge = { vertex1: { x: nextLine.x2, y: nextLine.y2 }, vertex2: { x: nextEndPoint.x, y: nextEndPoint.y } } + let hipEdge = { + vertex1: { x: nextLine.x2, y: nextLine.y2 }, + vertex2: { x: nextEndPoint.x, y: nextEndPoint.y }, + } let intersection = edgesIntersection(ridgeEdge, hipEdge) if (intersection) { nextHipCoords = { x1: nextLine.x2, y1: nextLine.y2, x2: intersection.x, y2: intersection.y } @@ -1283,7 +1402,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { y: currentMidY.plus(Big(prevVectorY).times(prevBaseLine.size)).toNumber(), }, } - let hipEdge = { vertex1: { x: prevLine.x1, y: prevLine.y1 }, vertex2: { x: prevEndPoint.x, y: prevEndPoint.y } } + let hipEdge = { + vertex1: { x: prevLine.x1, y: prevLine.y1 }, + vertex2: { x: prevEndPoint.x, y: prevEndPoint.y }, + } let intersection = edgesIntersection(ridgeEdge, hipEdge) if (intersection) { prevHipCoords = { x1: prevLine.x1, y1: prevLine.y1, x2: intersection.x, y2: intersection.y } @@ -1299,135 +1421,268 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { prevOppositeMidY = 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)) { - if (nextHipCoords) { - let intersectPoints = [] - const hipEdge = { - vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, - vertex2: { x: nextHipCoords.x1, y: nextHipCoords.y1 }, - } + const currentMidEdge = { + vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + vertex2: { + x: currentVectorX === 0 ? nextLine.x2 : currentMidX.toNumber(), + y: currentVectorX === 0 ? currentMidY.toNumber() : nextLine.y2, + }, + } - /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - Math.sign(nextHipCoords.x2 - nextHipCoords.x1) === Math.sign(nextHipCoords.x2 - intersection.x) && - Math.sign(nextHipCoords.y2 - nextHipCoords.y1) === Math.sign(nextHipCoords.y2 - intersection.y) - ) { - const intersectEdge = { - vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, - vertex2: { x: intersection.x, y: intersection.y }, - } - const is = edgesIntersection(intersectEdge, lineEdge) - if (!is.isIntersectionOutside) { - const intersectSize = Big(nextHipCoords.x2) - .minus(Big(intersection.x)) - .pow(2) - .plus(Big(nextHipCoords.y2).minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - line, - }) + let oppositeLines = [] + drawBaseLines + .filter((line, index) => { + const currentLine = line.line + const nextLine = drawBaseLines[(index + 1) % drawBaseLines.length].line + const prevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length].line + console.log('line.startPoint :', currentLine.startPoint, 'line.endPoint :', currentLine.endPoint) + const angle = calculateAngle(currentLine.startPoint, currentLine.endPoint) + const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) + const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) + if (angle === prevAngle || angle === nextAngle) { + const sameAngleLine = angle === prevAngle ? prevLine : nextLine + if (gableType.includes(currentLine.attributes.type) && !gableType.includes(sameAngleLine.attributes.type)) { + switch (currentAngle) { + case 90: + return angle === -90 + case -90: + return angle === 90 + case 0: + return angle === 180 + case 180: + return angle === 0 } } - }) - const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0] - if (intersect) { - const degree = intersect.line.attributes.pitch > 0 ? getDegreeByChon(intersect.line.attributes.pitch) : intersect.line.attributes.degree - const hipLine = drawHipLine( - [intersect.intersection.x, intersect.intersection.y, nextOppositeMidX.toNumber(), nextOppositeMidY.toNumber()], - canvas, - roof, - textMode, - null, - degree, - degree, - ) - baseHipLines.push({ - x1: nextHipCoords.x1, - y1: nextHipCoords.y1, - x2: nextHipCoords.x2, - y2: nextHipCoords.y2, - line: hipLine, - }) } - } - oppositeMidY = nextOppositeMidY - oppositeMidX = nextOppositeMidX + return false + }) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const intersection = edgesIntersection(currentMidEdge, lineEdge) + if (intersection) { + if (line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) { + oppositeLines.push({ + line, + intersection, + size: Big(intersection.x) + .minus(currentMidX) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) + .sqrt() + .toNumber(), + }) + } + } + }) + + if (oppositeLines.length > 0) { + const oppositePoint = oppositeLines.sort((a, b) => a.size - b.size)[0].intersection + const checkEdge = { vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, vertex2: { x: oppositePoint.x, y: oppositePoint.y } } + const oppositeRoofPoints = [] + roof.lines + .filter((line) => { + const angle = calculateAngle(line.startPoint, line.endPoint) + switch (currentAngle) { + case 90: + return angle === -90 + case -90: + return angle === 90 + case 0: + return angle === 180 + case 180: + return angle === 0 + } + }) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const intersection = edgesIntersection(checkEdge, lineEdge) + if ( + intersection && + ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || + (line.x1 >= intersection.x && line.x2 <= intersection.x && line.y1 >= intersection.y && line.y2 <= intersection.y)) + ) { + oppositeRoofPoints.push({ + line, + intersection, + size: Big(intersection.x) + .minus(currentMidX.toNumber()) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(currentMidY.toNumber()).abs().pow(2)) + .sqrt() + .toNumber(), + }) + } + }) + const oppositeRoofPoint = oppositeRoofPoints.sort((a, b) => a.size - b.size)[0].intersection + oppositeMidX = Big(oppositeRoofPoint.x) + oppositeMidY = Big(oppositeRoofPoint.y) + + const currentRoofPoints = [] + roof.lines + .filter((line) => { + const angle = calculateAngle(line.startPoint, line.endPoint) + return currentAngle === angle + }) + .forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const intersection = edgesIntersection(checkEdge, lineEdge) + if ( + intersection && + ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || + (line.x1 >= intersection.x && line.x2 <= intersection.x && line.y1 >= intersection.y && line.y2 <= intersection.y)) + ) { + currentRoofPoints.push({ + line, + intersection, + size: Big(intersection.x) + .minus(currentMidX.toNumber()) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(currentMidY.toNumber()).abs().pow(2)) + .sqrt() + .toNumber(), + }) + } + }) + const currentRoofPoint = currentRoofPoints.sort((a, b) => a.size - b.size)[0].intersection + currentMidX = Big(currentRoofPoint.x) + currentMidY = Big(currentRoofPoint.y) } else { - if (prevHipCoords) { - let intersectPoints = [] - const hipEdge = { - vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, - vertex2: { x: prevHipCoords.x1, y: prevHipCoords.y1 }, - } + 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() - /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - Math.sign(prevHipCoords.x2 - prevHipCoords.x1) === Math.sign(prevHipCoords.x2 - intersection.x) && - Math.sign(prevHipCoords.y2 - prevHipCoords.y1) === Math.sign(prevHipCoords.y2 - intersection.y) - ) { - const intersectEdge = { - vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, - vertex2: { x: intersection.x, y: intersection.y }, - } - const is = edgesIntersection(intersectEdge, lineEdge) - if (!is.isIntersectionOutside) { - const intersectSize = Big(prevHipCoords.x2) - .minus(Big(intersection.x)) - .pow(2) - .plus(Big(prevHipCoords.y2).minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - line, - }) - } + /** 두 포인트 중에 current와 가까운 포인트를 사용*/ + if (checkPrevSize.gt(checkNextSize)) { + if (nextHipCoords) { + let intersectPoints = [] + const hipEdge = { + vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, + vertex2: { x: nextHipCoords.x1, y: nextHipCoords.y1 }, } - }) - const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0] - if (intersect) { - const degree = intersect.line.attributes.pitch > 0 ? getDegreeByChon(intersect.line.attributes.pitch) : intersect.line.attributes.degree - const hipLine = drawHipLine( - [intersect.intersection.x, intersect.intersection.y, prevOppositeMidX.toNumber(), prevOppositeMidY.toNumber()], - canvas, - roof, - textMode, - null, - degree, - degree, - ) - baseHipLines.push({ - x1: prevHipCoords.x1, - y1: prevHipCoords.y1, - x2: prevHipCoords.x2, - y2: prevHipCoords.y2, - line: hipLine, + /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ + roof.lines.forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const intersection = edgesIntersection(hipEdge, lineEdge) + if ( + intersection && + Math.sign(nextHipCoords.x2 - nextHipCoords.x1) === Math.sign(nextHipCoords.x2 - intersection.x) && + Math.sign(nextHipCoords.y2 - nextHipCoords.y1) === Math.sign(nextHipCoords.y2 - intersection.y) + ) { + const intersectEdge = { + vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, + vertex2: { x: intersection.x, y: intersection.y }, + } + const is = edgesIntersection(intersectEdge, lineEdge) + if (!is.isIntersectionOutside) { + const intersectSize = Big(nextHipCoords.x2) + .minus(Big(intersection.x)) + .pow(2) + .plus(Big(nextHipCoords.y2).minus(Big(intersection.y)).pow(2)) + .abs() + .sqrt() + .toNumber() + + intersectPoints.push({ + intersection, + size: intersectSize, + line, + }) + } + } }) + const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0] + if (intersect) { + const degree = + intersect.line.attributes.pitch > 0 ? getDegreeByChon(intersect.line.attributes.pitch) : intersect.line.attributes.degree + const hipLine = drawHipLine( + [intersect.intersection.x, intersect.intersection.y, nextOppositeMidX.toNumber(), nextOppositeMidY.toNumber()], + canvas, + roof, + textMode, + null, + degree, + degree, + ) + baseHipLines.push({ + x1: nextHipCoords.x1, + y1: nextHipCoords.y1, + x2: nextHipCoords.x2, + y2: nextHipCoords.y2, + line: hipLine, + }) + } } + oppositeMidY = nextOppositeMidY + oppositeMidX = nextOppositeMidX + } else { + if (prevHipCoords) { + let intersectPoints = [] + const hipEdge = { + vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, + vertex2: { x: prevHipCoords.x1, y: prevHipCoords.y1 }, + } + + /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ + roof.lines.forEach((line) => { + const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } + const intersection = edgesIntersection(hipEdge, lineEdge) + if ( + intersection && + Math.sign(prevHipCoords.x2 - prevHipCoords.x1) === Math.sign(prevHipCoords.x2 - intersection.x) && + Math.sign(prevHipCoords.y2 - prevHipCoords.y1) === Math.sign(prevHipCoords.y2 - intersection.y) + ) { + const intersectEdge = { + vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, + vertex2: { x: intersection.x, y: intersection.y }, + } + const is = edgesIntersection(intersectEdge, lineEdge) + if (!is.isIntersectionOutside) { + const intersectSize = Big(prevHipCoords.x2) + .minus(Big(intersection.x)) + .pow(2) + .plus(Big(prevHipCoords.y2).minus(Big(intersection.y)).pow(2)) + .abs() + .sqrt() + .toNumber() + + intersectPoints.push({ + intersection, + size: intersectSize, + line, + }) + } + } + }) + const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0] + + if (intersect) { + const degree = + intersect.line.attributes.pitch > 0 ? getDegreeByChon(intersect.line.attributes.pitch) : intersect.line.attributes.degree + const hipLine = drawHipLine( + [intersect.intersection.x, intersect.intersection.y, prevOppositeMidX.toNumber(), prevOppositeMidY.toNumber()], + canvas, + roof, + textMode, + null, + degree, + degree, + ) + baseHipLines.push({ + x1: prevHipCoords.x1, + y1: prevHipCoords.y1, + x2: prevHipCoords.x2, + y2: prevHipCoords.y2, + line: hipLine, + }) + } + } + oppositeMidY = prevOppositeMidY + oppositeMidX = prevOppositeMidX } - oppositeMidY = prevOppositeMidY - oppositeMidX = prevOppositeMidX } } if (baseRidgeCount < getMaxRidge(baseLines.length)) { @@ -1459,7 +1714,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } } }) - const ridgeLine = drawRidgeLine([currentMidX, currentMidY, oppositeMidX, oppositeMidY], canvas, roof, textMode) baseGableRidgeLines.push(ridgeLine) baseRidgeCount++ @@ -2190,6 +2444,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { let prevLineRidges = [], nextLineRidges = [] + const checkLine = new fabric.Line([x1, y1, x2, y2], { + stroke: 'red', + strokeWidth: 4, + parentId: roofId, + name: 'checkLine', + }) + canvas.add(checkLine) + canvas.renderAll() + const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) const prevVectorX = Math.sign(prevLine.x2 - prevLine.x1)