From 2a8d373f6718ecbd07f51f8b4c5dba041a5d579b Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Wed, 21 May 2025 13:43:01 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A7=88=EB=A3=A8=EC=A7=80=EB=B6=95,=20?= =?UTF-8?q?=EC=BC=80=EB=9D=BC=EB=B0=94=EC=A7=80=EB=B6=95=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=EC=B2=AB=EB=B2=88=EC=A7=B8=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=20=EC=9E=91=EC=97=85=EB=B3=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 2653 ++++++++++++++++-------------------- 1 file changed, 1208 insertions(+), 1445 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e27b49d6..b780cdd9 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -719,7 +719,16 @@ export const drawShedRoof = (roofId, canvas, textMode) => { } gables.forEach( - (gable) => (gable.attributes.actualSize = calcLineActualSize({ x1: gable.x1, y1: gable.y1, x2: gable.x2, y2: gable.y2 }, shedDegree)), + (gable) => + (gable.attributes.actualSize = calcLineActualSize( + { + x1: gable.x1, + y1: gable.y1, + x2: gable.x2, + y2: gable.y2, + }, + shedDegree, + )), ) const pitchSizeLines = [] @@ -789,20 +798,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) - console.log('wall :', wall) - console.log('roof.lines :', roof.lines) - //Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1 const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1)) if (hasNonParallelLines.length > 0) { - // alert('대각선이 존재합니다.') return } const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE] const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD] - // - // const eaves = roof.lines.filter((line) => eavesType.includes(line.attributes?.type)) - // const gables = roof.lines.filter((line) => gableType.includes(line.attributes?.type)) /** 외벽선 */ const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0) @@ -840,8 +842,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) - console.log('drawBaseLines : ', drawBaseLines) - /** baseLine을 기준으로 확인용 polygon 작성 */ const checkWallPolygon = new QPolygon(baseLinePoints, {}) @@ -865,17 +865,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const drawEavesSecondLines = [] const drawGableRidgeFirst = [] const drawGableRidgeSecond = [] - const drawGableFirstLines = [] - const drawGableSecondLines = [] const drawGablePolygonFirst = [] const drawGablePolygonSecond = [] /** 모양을 판단한다. */ drawBaseLines.forEach((currentBaseLine, index) => { let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] let nextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length] - // console.log('currentLine :', currentBaseLine) - // console.log('prevLine :', prevBaseLine) - // console.log('nextLine :', nextBaseLine) const currentLine = currentBaseLine.line const prevLine = prevBaseLine.line const nextLine = nextBaseLine.line @@ -894,7 +889,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { y: currentMidY.plus(checkScale.times(Math.sign(yVector.toNumber()))).toNumber(), } - // console.log('prevAngle :', prevAngle, 'nextAngle :', nextAngle) /** 현재 라인이 처마유형일 경우 */ if (eavesType.includes(currentLine.attributes?.type)) { if (eavesType.includes(nextLine.attributes?.type)) { @@ -950,12 +944,9 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { ) { if (checkWallPolygon.inPolygon(checkPoints)) { drawGableRidgeFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - drawGableFirstLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) } else { drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) } - } else { - drawGableSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) } } } @@ -979,12 +970,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { // console.log('drawGableFirstLines :', drawGableFirstLines) // console.log('drawGableSecondLines :', drawGableSecondLines) - console.log('drawEavesFirstLines :', drawEavesFirstLines) - console.log('drawEavesSecondLines :', drawEavesSecondLines) - console.log('drawGableRidgeFirst : ', drawGableRidgeFirst) - console.log('drawGableRidgeSecond : ', drawGableRidgeSecond) - console.log('drawGablePolygonFirst :', drawGablePolygonFirst) - console.log('drawGablePolygonSecond :', drawGablePolygonSecond) + // console.log('drawEavesFirstLines :', drawEavesFirstLines) + // console.log('drawEavesSecondLines :', drawEavesSecondLines) + // console.log('drawGableRidgeFirst : ', drawGableRidgeFirst) + // console.log('drawGableRidgeSecond : ', drawGableRidgeSecond) + // console.log('drawGablePolygonFirst :', drawGablePolygonFirst) + // console.log('drawGablePolygonSecond :', drawGablePolygonSecond) /** 박공지붕에서 파생되는 마루를 그린다. ㄷ 형태*/ drawGableRidgeFirst.forEach((current) => { @@ -1100,7 +1091,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { }) } - const prevHipEdge = { vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, vertex2: { x: prevLine.x1, y: prevLine.y1 } } + 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 = [] @@ -1136,10 +1130,19 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { prevDegree, prevDegree, ) - baseHipLines.push({ x1: prevLine.x1, y1: prevLine.y1, x2: oppositeMidX.toNumber(), y2: oppositeMidY.toNumber(), line: prevHipLine }) + 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 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 = [] @@ -1175,7 +1178,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { nextDegree, nextDegree, ) - baseHipLines.push({ x1: nextLine.x2, y1: nextLine.y2, x2: oppositeMidX.toNumber(), y2: oppositeMidY.toNumber(), line: nextHipLine }) + baseHipLines.push({ + x1: nextLine.x2, + y1: nextLine.y2, + x2: oppositeMidX.toNumber(), + y2: oppositeMidY.toNumber(), + line: nextHipLine, + }) } if (baseRidgeCount < getMaxRidge(baseLines.length)) { @@ -1188,7 +1197,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseGableRidgeLines.push(ridgeLine) baseRidgeCount++ } - console.log('지붕선 분할 : end') } else { if (beforePrevBaseLine === afterNextBaseLine) { const afterNextMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2) @@ -1245,8 +1253,14 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { 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 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 @@ -1296,6 +1310,76 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY)) if (vectorMidX === vectorOppositeX && vectorMidY === vectorOppositeY && baseRidgeCount < getMaxRidge(baseLines.length)) { + if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) { + const checkEdge = { + vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, + } + const intersectionPoints = [] + + 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 intersection = edgesIntersection(checkEdge, lineEdge) + if ( + intersection && + ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || + (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) + ) { + const size = Big(intersection.x) + .minus(currentMidX) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) + .sqrt() + .toNumber() + intersectionPoints.push({ intersection, size }) + } + }) + + if (intersectionPoints.length > 0) { + const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection + currentMidX = Big(intersection.x) + currentMidY = Big(intersection.y) + } + } + + if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidX.toNumber() })) { + const checkEdge = { + vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, + vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + } + const intersectionPoints = [] + + 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 intersection = edgesIntersection(checkEdge, lineEdge) + if ( + intersection && + ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || + (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) + ) { + const size = Big(intersection.x) + .minus(oppositeMidX) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)) + .sqrt() + .toNumber() + intersectionPoints.push({ intersection, size }) + } + }) + + if (intersectionPoints.length > 0) { + const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection + oppositeMidX = Big(intersection.x) + oppositeMidY = Big(intersection.y) + } + } + const ridge = drawRidgeLine( [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], canvas, @@ -1436,7 +1520,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { 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) @@ -1479,7 +1562,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { 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 checkEdge = { + vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + vertex2: { x: oppositePoint.x, y: oppositePoint.y }, + } const oppositeRoofPoints = [] roof.lines .filter((line) => { @@ -1686,6 +1772,77 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } } if (baseRidgeCount < getMaxRidge(baseLines.length)) { + /** 포인트가 지붕 밖에 있는 경우 조정 */ + if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) { + const checkEdge = { + vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, + } + const intersectionPoints = [] + + 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 intersection = edgesIntersection(checkEdge, lineEdge) + if ( + intersection && + ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || + (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) + ) { + const size = Big(intersection.x) + .minus(currentMidX) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) + .sqrt() + .toNumber() + intersectionPoints.push({ intersection, size }) + } + }) + + if (intersectionPoints.length > 0) { + const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection + currentMidX = Big(intersection.x) + currentMidY = Big(intersection.y) + } + } + + if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) { + const checkEdge = { + vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, + vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + } + const intersectionPoints = [] + + 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 intersection = edgesIntersection(checkEdge, lineEdge) + if ( + intersection && + ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || + (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) + ) { + const size = Big(intersection.x) + .minus(oppositeMidX) + .abs() + .pow(2) + .plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)) + .sqrt() + .toNumber() + intersectionPoints.push({ intersection, size }) + } + }) + + if (intersectionPoints.length > 0) { + const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection + oppositeMidX = Big(intersection.x) + oppositeMidY = Big(intersection.y) + } + } + /** 마루가 맞은편 외벽선에 닿는 경우 해당 부분까지로 한정한다. */ const ridgeEdge = { vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, @@ -1714,7 +1871,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } } }) - const ridgeLine = drawRidgeLine([currentMidX, currentMidY, oppositeMidX, oppositeMidY], canvas, roof, textMode) + const ridgeLine = drawRidgeLine( + [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], + canvas, + roof, + textMode, + ) baseGableRidgeLines.push(ridgeLine) baseRidgeCount++ } @@ -1728,9 +1890,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { 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 /** 다음 라인의 경사 */ @@ -1923,7 +2082,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { x2: ridgeEndPoint.x.toNumber(), y2: ridgeEndPoint.y.toNumber(), } - const ridgeIntersection = findRoofIntersection(roof, ridgePoints, { x: Big(ridgePoints.x2), y: Big(ridgePoints.y2) }) + const ridgeIntersection = findRoofIntersection(roof, ridgePoints, { + x: Big(ridgePoints.x2), + y: Big(ridgePoints.y2), + }) if (ridgeIntersection) { points = [ridgeIntersection.intersection.x, ridgeIntersection.intersection.y, ridgeEndPoint.x, ridgeEndPoint.y] } @@ -1941,12 +2103,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseGableRidgeLines.push(ridgeLine) baseRidgeCount++ } - - canvas - .getObjects() - .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkPoint') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() } else { const oppositeLines = baseLines.filter((line) => { const lineAngle = calculateAngle(line.startPoint, line.endPoint) @@ -2002,11 +2158,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseRidgeCount++ } } - canvas - .getObjects() - .filter((obj) => obj.name === 'checkLine' || obj.name === 'checkPoint') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() }) const uniqueRidgeLines = [] @@ -2028,8 +2179,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseGableRidgeLines = uniqueRidgeLines - console.log('baseGableRidgeLines : ', baseGableRidgeLines) - /** 박공지붕 polygon 생성 */ drawGablePolygonFirst.forEach((current) => { const { currentBaseLine, prevBaseLine, nextBaseLine } = current @@ -2042,59 +2191,127 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) - const prevVectorX = Math.sign(prevLine.x2 - prevLine.x1) - const prevVectorY = Math.sign(prevLine.y2 - prevLine.y1) const nextVectorX = Math.sign(nextLine.x1 - nextLine.x2) const nextVectorY = Math.sign(nextLine.y1 - nextLine.y2) const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree - const currentOffset = currentLine.attributes.offset - const prevOffset = prevLine.attributes.offset - const nextOffset = nextLine.attributes.offset let roofX1, roofY1, roofX2, roofY2 + const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) + const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) + const intersectionRoofs = [] if (currentVectorX === 0) { - roofX1 = Big(x1).plus(Big(currentLine.attributes.offset).times(prevVectorX)) - roofX2 = roofX1 - roofY1 = Big(y1).plus(Big(prevLine.attributes.offset).times(currentVectorY * -1)) - roofY2 = Big(y2).plus(Big(nextLine.attributes.offset).times(currentVectorY)) + const checkEdge = { + vertex1: { x: prevLine.x1, y: currentMidY.toNumber() }, + vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + } + roof.lines + .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) + .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) { + intersection.x = Math.round(intersection.x) + intersection.y = Math.round(intersection.y) + if ( + (line.x1 <= intersection.x && intersection.x <= line.x2 && line.y1 <= intersection.y && intersection.y <= line.y2) || + (line.x2 <= intersection.x && intersection.x <= line.x1 && line.y2 <= intersection.y && intersection.y <= line.y1) + ) { + intersectionRoofs.push({ + line, + intersection, + size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), + }) + } + } + }) } else { - roofX1 = Big(x1).plus(Big(prevLine.attributes.offset).times(currentVectorX * -1)) - roofX2 = Big(x2).plus(Big(nextLine.attributes.offset).times(currentVectorX)) - roofY1 = Big(y1).plus(Big(currentLine.attributes.offset).times(prevVectorY)) - roofY2 = roofY1 + const checkEdge = { + vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 }, + vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, + } + roof.lines + .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) + .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) { + intersection.x = Math.round(intersection.x) + intersection.y = Math.round(intersection.y) + if ( + (line.x1 <= intersection.x && intersection.x <= line.x2 && line.y1 <= intersection.y && intersection.y <= line.y2) || + (line.x2 <= intersection.x && intersection.x <= line.x1 && line.y2 <= intersection.y && intersection.y <= line.y1) + ) { + intersectionRoofs.push({ + line, + intersection, + size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), + }) + } + } + }) + } + if (intersectionRoofs.length > 0) { + const currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line + roofX1 = Big(currentRoof.x1) + roofY1 = Big(currentRoof.y1) + roofX2 = Big(currentRoof.x2) + roofY2 = Big(currentRoof.y2) } let prevRoofLine, nextRoofLine - const roofEdge = { vertex1: { x: roofX1.toNumber(), y: roofY1.toNumber() }, vertex2: { x: roofX2.toNumber(), y: roofY2.toNumber() } } + 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 + intersection.x = Math.round(intersection.x) + intersection.y = Math.round(intersection.y) + if ( + (line.x1 <= intersection.x && intersection.x <= line.x2 && line.y1 <= intersection.y && intersection.y <= line.y2) || + (line.x2 <= intersection.x && intersection.x <= line.x1 && line.y2 <= intersection.y && intersection.y <= line.y1) + ) { + 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.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 } } + 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) => { const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } const prevIs = edgesIntersection(prevRoofEdge, ridgeEdge) const nextIs = edgesIntersection(nextRoofEdge, ridgeEdge) - if (prevIs) { + if ( + prevIs && + ((ridgeEdge.vertex1.x === prevIs.x && ridgeEdge.vertex1.y === prevIs.y) || + (ridgeEdge.vertex2.x === prevIs.x && ridgeEdge.vertex2.y === prevIs.y)) + ) { prevLineRidges.push({ ridge, size: calcLinePlaneSize({ x1: roofX1, y1: roofY1, x2: prevIs.x, y2: prevIs.y }), }) } - if (nextIs) { + if ( + nextIs && + ((ridgeEdge.vertex1.x === nextIs.x && ridgeEdge.vertex1.y === nextIs.y) || + (ridgeEdge.vertex2.x === nextIs.x && ridgeEdge.vertex2.y === nextIs.y)) + ) { nextLineRidges.push({ ridge, size: calcLinePlaneSize({ x1: roofX2, y1: roofY2, x2: nextIs.x, y2: nextIs.y }), @@ -2131,308 +2348,466 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { .sort((a, b) => a.size - b.size) nextLineRidge = nextLineRidges[0].ridge } + const ridgeLine = prevLineRidge === undefined ? nextLineRidge : prevLineRidge - /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/ - 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) + /** 마루선이 한쪽만 존재 연결될 경우 다각형을 그린다.*/ + if (prevLineRidge === undefined || nextLineRidge === undefined) { + const points = [ + { x: roofX1.toNumber(), y: roofY1.toNumber() }, + { x: roofX2.toNumber(), y: roofY2.toNumber() }, + { x: ridgeLine.x1, y: ridgeLine.y1 }, + { x: ridgeLine.x2, y: ridgeLine.y2 }, + ] + const minX = Math.min(ridgeLine.x1, ridgeLine.x2, roofX1.toNumber(), roofX2.toNumber()) + const minY = Math.min(ridgeLine.y1, ridgeLine.y2, roofY1.toNumber(), roofY2.toNumber()) + + let polygonPoints = [] + + polygonPoints.push(points.find((point) => point.x === minX && point.y === minY)) + + let i = 0 + let length = points.length + while (i < length - 1) { + const currentPoint = polygonPoints[i] + if (i === 0) { + polygonPoints.push(points.find((point) => point.x === currentPoint.x && point.y > currentPoint.y)) + i++ + } else { + const prevPoint = polygonPoints[(i - 1 + polygonPoints.length) % polygonPoints.length] + const vectorX = Math.sign(prevPoint.x - currentPoint.x) + const vectorY = Math.sign(prevPoint.y - currentPoint.y) + if (i % 2 === 1) { + /** 가로선 찾기 */ + const nextPoint = points.find((point) => point.y === currentPoint.y && point.x !== currentPoint.x) + if (nextPoint === undefined) { + const connectLine = roof.lines.find((line) => line.y1 === line.y2 && line.x1 === currentPoint.x && line.y1 === currentPoint.y) + if (connectLine) { + polygonPoints.push( + connectLine.x1 === currentPoint.x && connectLine.y1 === currentPoint.y + ? { x: connectLine.x2, y: connectLine.y2 } + : { x: connectLine.x1, y: connectLine.y1 }, + ) + } else { + const intersectLine = roof.lines.find( + (line) => + line.y1 === currentPoint.y && + line.y2 === currentPoint.y && + ((line.x1 <= currentPoint.x && line.x2 >= currentPoint.x) || (line.x2 <= currentPoint.x && line.x1 >= currentPoint.x)), + ) + /** 이전 라인이 위에서 아래로 항하면 오른쪽 포인트 찾기*/ + if (vectorY === 1) { + polygonPoints.push({ x: intersectLine.x1, y: intersectLine.y1 }) + } + /** 이전 라인이 아래에서 위로 항하면 왼쪽 포인트 찾기*/ + if (vectorY === -1) { + polygonPoints.push({ x: intersectLine.x2, y: intersectLine.y2 }) + } + } + length = length + 1 + } else { + polygonPoints.push(nextPoint) + } + i++ + } else { + /** 세로선 찾기*/ + const nextPoint = points.find((point) => point.x === currentPoint.x && point.y !== currentPoint.y) + if (nextPoint === undefined) { + const connectLine = roof.lines.find((line) => line.x1 === line.x2 && line.x1 === currentPoint.x && line.y1 === currentPoint.y) + if (connectLine) { + polygonPoints.push( + connectLine.x1 === currentPoint.x && connectLine.y1 === currentPoint.y + ? { x: connectLine.x2, y: connectLine.y2 } + : { x: connectLine.x1, y: connectLine.y1 }, + ) + } else { + const intersectLine = roof.lines.find( + (line) => + line.x1 === currentPoint.x && + line.x2 === currentPoint.x && + ((line.y1 <= currentPoint.y && line.y2 >= currentPoint.y) || (line.y2 <= currentPoint.y && line.y1 >= currentPoint.y)), + ) + /** 이전 라인이 왼쪽에서 오른쪽로 항하면 위쪽 포인트 찾기*/ + if (vectorX === -1) { + polygonPoints.push({ x: intersectLine.x1, y: intersectLine.y1 }) + } + /** 이전 라인이 오른에서 왼쪽으로 항하면 아래쪽 포인트 찾기*/ + if (vectorX === 1) { + polygonPoints.push({ x: intersectLine.x2, y: intersectLine.y2 }) + } + } + length = length + 1 + } else { + polygonPoints.push(nextPoint) + } + i++ } } - }) - 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 }) - } + } + polygonPoints = getSortedPoint(polygonPoints) + polygonPoints.forEach((currentPoint, index) => { + const nextPoint = polygonPoints[(index + 1) % polygonPoints.length] + const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y] + const isParallel = ridgeLine.x1 === ridgeLine.x2 ? currentPoint.x === nextPoint.x : currentPoint.y === nextPoint.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) || - (prevLineRidge.y1 >= nextLineRidge.y1 && prevLineRidge.y2 <= nextLineRidge.y1) || - (prevLineRidge.y1 <= nextLineRidge.y2 && prevLineRidge.y2 >= nextLineRidge.y2) || - (prevLineRidge.y1 >= nextLineRidge.y2 && prevLineRidge.y2 <= nextLineRidge.y2) - : (prevLineRidge.x1 <= nextLineRidge.x1 && prevLineRidge.x2 >= nextLineRidge.x1) || - (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) || - (prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) || - (prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2) - 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) { - console.log('prevDistance === nextDistance') - } else if (prevDistance < nextDistance) { - polygonPoints.push({ x: nextLineRidge.x1, y: nextLineRidge.y1 }, { x: nextLineRidge.x2, y: nextLineRidge.y2 }) - /** 이전라인과 교차한 마루의 포인트*/ - const prevRidgePoint1 = - currentVectorX === 0 - ? roofY1.toNumber() === prevLineRidge.y1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - : roofX1.toNumber() === prevLineRidge.x1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - - polygonPoints.push(prevRidgePoint1) - - /** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ - const checkRidgePoint = - currentVectorX === 0 - ? roofY2.toNumber() !== nextLineRidge.y1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - : roofX2.toNumber() !== nextLineRidge.x1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - - const prevRidgePoint2 = - currentVectorX === 0 ? { x: prevRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: prevRidgePoint1.y } - polygonPoints.push(prevRidgePoint2) + let line + if (isParallel) { + line = drawRoofLine(points, canvas, roof, textMode) + baseGableLines.push(line) } else { - polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 }) - - /** 다음라인과 교차한 마루의 포인트*/ - const nextRidgePoint1 = - currentVectorX === 0 - ? roofY2.toNumber() === nextLineRidge.y1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - : roofX2.toNumber() === nextLineRidge.x1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - polygonPoints.push(nextRidgePoint1) - - /** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ - const checkRidgePoint = - currentVectorX === 0 - ? roofY1.toNumber() !== prevLineRidge.y1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - : roofX1.toNumber() !== prevLineRidge.x1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - const nextRidgePoint2 = - currentVectorX === 0 ? { x: nextRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: nextRidgePoint1.y } - polygonPoints.push(nextRidgePoint2) + line = drawHipLine(points, canvas, roof, textMode, null, currentDegree, currentDegree) + baseHipLines.push({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2, line }) + } + }) + } else { + /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/ + let checkEdge + if (currentVectorX === 0) { + checkEdge = { + vertex1: { x: ridgeLine.x1, y: roofY1.toNumber() }, + vertex2: { x: roofX1.toNumber(), y: roofY1.toNumber() }, } } else { - /** 마루가 겹치지 않을때 */ - const otherRidgeLines = [] + checkEdge = { + vertex1: { x: roofX1.toNumber(), y: ridgeLine.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) + } + } + }) - 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) + 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 (isInside) { + 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) || + (prevLineRidge.y1 >= nextLineRidge.y1 && prevLineRidge.y2 <= nextLineRidge.y1) || + (prevLineRidge.y1 <= nextLineRidge.y2 && prevLineRidge.y2 >= nextLineRidge.y2) || + (prevLineRidge.y1 >= nextLineRidge.y2 && prevLineRidge.y2 <= nextLineRidge.y2) + : (prevLineRidge.x1 <= nextLineRidge.x1 && prevLineRidge.x2 >= nextLineRidge.x1) || + (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) || + (prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) || + (prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2) + 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) { + polygonPoints.push( + { x: nextLineRidge.x1, y: nextLineRidge.y1 }, + { + x: nextLineRidge.x2, + y: nextLineRidge.y2, + }, + ) + /** 이전라인과 교차한 마루의 포인트*/ + const prevRidgePoint1 = + currentVectorX === 0 + ? roofY1.toNumber() === prevLineRidge.y1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + : roofX1.toNumber() === prevLineRidge.x1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + + polygonPoints.push(prevRidgePoint1) + + /** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ + const checkRidgePoint = + currentVectorX === 0 + ? roofY2.toNumber() !== nextLineRidge.y1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + : roofX2.toNumber() !== nextLineRidge.x1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + + const prevRidgePoint2 = + currentVectorX === 0 + ? { x: prevRidgePoint1.x, y: checkRidgePoint.y } + : { + x: checkRidgePoint.x, + y: prevRidgePoint1.y, + } + polygonPoints.push(prevRidgePoint2) + } else { 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 }, + { + x: prevLineRidge.x2, + y: prevLineRidge.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 + /** 다음라인과 교차한 마루의 포인트*/ + const nextRidgePoint1 = + currentVectorX === 0 + ? roofY2.toNumber() === nextLineRidge.y1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + : roofX2.toNumber() === nextLineRidge.x1 + ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } + : { x: nextLineRidge.x2, y: nextLineRidge.y2 } + polygonPoints.push(nextRidgePoint1) + + /** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ + const checkRidgePoint = + currentVectorX === 0 + ? roofY1.toNumber() !== prevLineRidge.y1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + : roofX1.toNumber() !== prevLineRidge.x1 + ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } + : { x: prevLineRidge.x2, y: prevLineRidge.y2 } + const nextRidgePoint2 = + currentVectorX === 0 + ? { x: nextRidgePoint1.x, y: checkRidgePoint.y } + : { + x: checkRidgePoint.x, + y: nextRidgePoint1.y, + } + 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 (!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, + }, + ) + } } - }) - if (ridgePoints.length === 2) { + } 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) { - polygonPoints.push({ x: otherRidge.x1, y: ridgePoints[0].y }, { x: otherRidge.x1, y: ridgePoints[1].y }) + 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 { - polygonPoints.push({ x: ridgePoints[0].x, y: otherRidge.y1 }, { x: ridgePoints[1].x, y: otherRidge.y1 }) + 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 }) } } - } else { - polygonPoints.push({ x: otherRidge.x1, y: otherRidge.y1 }, { x: otherRidge.x2, y: otherRidge.y2 }) + } + } + } + const sortedPolygonPoints = getSortedPoint(polygonPoints) - 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 }, - ] + /** 외벽선 밖으로 나가있는 포인트*/ + 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 + }) - 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 (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 (isOnLine) { - polygonPoints.push(point) + 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 } - }) - - 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 + sortedPolygonPoints.forEach((startPoint, index) => { + let endPoint + if (index === sortedPolygonPoints.length - 1) { + endPoint = sortedPolygonPoints[0] + } else { + endPoint = sortedPolygonPoints[index + 1] } - }) - 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 - } + 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 }) }) } - - 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 }) - }) }) drawGablePolygonSecond.forEach((current) => { @@ -2441,28 +2816,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const prevLine = prevBaseLine.line const nextLine = nextBaseLine.line let { x1, x2, y1, y2 } = currentBaseLine - 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) - const prevVectorY = Math.sign(prevLine.y2 - prevLine.y1) - const nextVectorX = Math.sign(nextLine.x1 - nextLine.x2) - const nextVectorY = Math.sign(nextLine.y1 - nextLine.y2) const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree - const currentOffset = currentLine.attributes.offset - const prevOffset = prevLine.attributes.offset - const nextOffset = nextLine.attributes.offset const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) @@ -2480,9 +2837,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { let checkEdge if (currentVectorX === 0) { - checkEdge = { vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, vertex2: { x: currentLine.x1, y: currentRidge.y1 } } + 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 } } + checkEdge = { + vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, + vertex2: { x: currentRidge.x1, y: currentLine.y1 }, + } } const isRoofLines = [] roof.lines @@ -2642,6 +3005,274 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { }) }) + /** 케라바 지붕에 연결된 마루 중 처마라인이 그려지지 않은 경우 확*/ + baseGableRidgeLines.forEach((ridge) => { + const ridgeVectorX = Math.sign(ridge.x1 - ridge.x2) + const ridgeVectorY = Math.sign(ridge.y1 - ridge.y2) + + const firstGableLines = [] + const secondGableLines = [] + + baseGableLines + .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) + .filter((line) => (line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1)) + .forEach((line) => firstGableLines.push(line)) + baseGableLines + .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) + .filter((line) => (line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2)) + .forEach((line) => secondGableLines.push(line)) + + baseHipLines + .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) + .filter((line) => (line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1)) + .forEach((line) => firstGableLines.push(line)) + baseHipLines + .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) + .filter((line) => (line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2)) + .forEach((line) => secondGableLines.push(line)) + + let degree1, degree2 + if (firstGableLines.length < 2 || secondGableLines.length < 2) { + drawBaseLines.forEach((currentBaseLine, index) => { + let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] + let nextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length] + const currentLine = currentBaseLine.line + const prevLine = prevBaseLine.line + const nextLine = nextBaseLine.line + const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) + const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) + + if ( + gableType.includes(currentLine.attributes?.type) && + eavesType.includes(prevLine.attributes?.type) && + eavesType.includes(nextLine.attributes?.type) && + Big(prevAngle).minus(Big(nextAngle)).abs().eq(180) + ) { + if ( + ridgeVectorX === 0 && + currentLine.x1 !== currentLine.x2 && + ((currentLine.x1 <= ridge.x1 && ridge.x1 <= currentLine.x2) || (currentLine.x2 <= ridge.x1 && ridge.x1 <= currentLine.x1)) + ) { + degree1 = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree + degree2 = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree + } + + if ( + ridgeVectorY === 0 && + currentLine.y1 !== currentLine.y2 && + ((currentLine.y1 <= ridge.y1 && ridge.y1 <= currentLine.y2) || (currentLine.y2 <= ridge.y1 && ridge.y1 <= currentLine.y1)) + ) { + degree1 = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree + degree2 = nextLine.attributes.pitch > 0 ? getDegreeByChon(nextLine.attributes.pitch) : nextLine.attributes.degree + } + } + }) + } + + if (firstGableLines.length < 2) { + const connectRoof = roof.lines.find( + (line) => + (line.x1 <= ridge.x1 && line.x2 >= ridge.x1 && line.y1 <= ridge.y1 && line.y2 >= ridge.y1) || + (line.x2 <= ridge.x1 && line.x1 >= ridge.x1 && line.y2 <= ridge.y1 && line.y1 >= ridge.y1), + ) + if (connectRoof) { + let hipPoint1 = [connectRoof.x1, connectRoof.y1, ridge.x1, ridge.y1] + let hipPoint2 = [connectRoof.x2, connectRoof.y2, ridge.x1, ridge.y1] + let intersectPoints1 + let intersectPoints2 + baseHipLines + .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) + .forEach((hip) => { + const line = hip.line + if ( + (hipPoint1[0] <= line.x1 && line.x1 <= hipPoint1[2] && hipPoint1[1] <= line.y1 && line.y1 <= hipPoint1[3]) || + (hipPoint1[2] <= line.x1 && line.x1 <= hipPoint1[0] && hipPoint1[3] <= line.y1 && line.y1 <= hipPoint1[1]) + ) { + intersectPoints1 = { x: line.x1, y: line.y1 } + } + if ( + (hipPoint1[0] <= line.x2 && line.x2 <= hipPoint1[2] && hipPoint1[1] <= line.y2 && line.y2 <= hipPoint1[3]) || + (hipPoint1[2] <= line.x2 && line.x2 <= hipPoint1[0] && hipPoint1[3] <= line.y2 && line.y2 <= hipPoint1[1]) + ) { + intersectPoints1 = { x: line.x2, y: line.y2 } + } + if ( + (hipPoint2[0] <= line.x1 && line.x1 <= hipPoint2[2] && hipPoint2[1] <= line.y1 && line.y1 <= hipPoint2[3]) || + (hipPoint2[2] <= line.x1 && line.x1 <= hipPoint2[0] && hipPoint2[3] <= line.y1 && line.y1 <= hipPoint2[1]) + ) { + intersectPoints2 = { x: line.x1, y: line.y1 } + } + if ( + (hipPoint2[0] <= line.x2 && line.x2 <= hipPoint2[2] && hipPoint2[1] <= line.y2 && line.y2 <= hipPoint2[3]) || + (hipPoint2[2] <= line.x2 && line.x2 <= hipPoint2[0] && hipPoint2[3] <= line.y2 && line.y2 <= hipPoint2[1]) + ) { + intersectPoints2 = { x: line.x2, y: line.y2 } + } + }) + if (intersectPoints1) { + hipPoint1 = [intersectPoints1.x, intersectPoints1.y, ridge.x1, ridge.y1] + } + if (intersectPoints2) { + hipPoint2 = [intersectPoints2.x, intersectPoints2.y, ridge.x1, ridge.y1] + } + + if (hipPoint1) { + let alreadyHip = false + baseHipLines + .filter( + (line) => + (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) || + (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + baseGableLines + .filter( + (line) => + (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) || + (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + + if (!alreadyHip) { + const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, null, degree1, degree1) + baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 }) + } + } + if (hipPoint2) { + let alreadyHip = false + baseHipLines + .filter( + (line) => + (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) || + (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + baseGableLines + .filter( + (line) => + (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) || + (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + if (!alreadyHip) { + const hipLine2 = drawHipLine(hipPoint2, canvas, roof, textMode, null, degree2, degree2) + baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 }) + } + } + } + } + if (secondGableLines.length < 2) { + const connectRoof = roof.lines.find( + (line) => + (line.x1 <= ridge.x2 && line.x2 >= ridge.x2 && line.y1 <= ridge.y2 && line.y2 >= ridge.y2) || + (line.x2 <= ridge.x2 && line.x1 >= ridge.x2 && line.y2 <= ridge.y2 && line.y1 >= ridge.y2), + ) + if (connectRoof) { + let hipPoint1 = [connectRoof.x1, connectRoof.y1, ridge.x2, ridge.y2] + let hipPoint2 = [connectRoof.x2, connectRoof.y2, ridge.x2, ridge.y2] + let intersectPoints1 + let intersectPoints2 + + baseHipLines + .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) + .forEach((hip) => { + const line = hip.line + if ( + (hipPoint1[0] <= line.x1 && line.x1 <= hipPoint1[2] && hipPoint1[1] <= line.y1 && line.y1 <= hipPoint1[3]) || + (hipPoint1[2] <= line.x1 && line.x1 <= hipPoint1[0] && hipPoint1[3] <= line.y1 && line.y1 <= hipPoint1[1]) + ) { + intersectPoints1 = { x: line.x1, y: line.y1 } + } + if ( + (hipPoint1[0] <= line.x2 && line.x2 <= hipPoint1[2] && hipPoint1[1] <= line.y2 && line.y2 <= hipPoint1[3]) || + (hipPoint1[2] <= line.x2 && line.x2 <= hipPoint1[0] && hipPoint1[3] <= line.y2 && line.y2 <= hipPoint1[1]) + ) { + intersectPoints1 = { x: line.x2, y: line.y2 } + } + if ( + (hipPoint2[0] <= line.x1 && line.x1 <= hipPoint2[2] && hipPoint2[1] <= line.y1 && line.y1 <= hipPoint2[3]) || + (hipPoint2[2] <= line.x1 && line.x1 <= hipPoint2[0] && hipPoint2[3] <= line.y1 && line.y1 <= hipPoint2[1]) + ) { + intersectPoints2 = { x: line.x1, y: line.y1 } + } + if ( + (hipPoint2[0] <= line.x2 && line.x2 <= hipPoint2[2] && hipPoint2[1] <= line.y2 && line.y2 <= hipPoint2[3]) || + (hipPoint2[2] <= line.x2 && line.x2 <= hipPoint2[0] && hipPoint2[3] <= line.y2 && line.y2 <= hipPoint2[1]) + ) { + intersectPoints2 = { x: line.x2, y: line.y2 } + } + }) + + if (intersectPoints1) { + hipPoint1 = [intersectPoints1.x, intersectPoints1.y, ridge.x2, ridge.y2] + } + if (intersectPoints2) { + hipPoint2 = [intersectPoints2.x, intersectPoints2.y, ridge.x2, ridge.y2] + } + + if (hipPoint1) { + let alreadyHip = false + baseHipLines + .filter( + (line) => + (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) || + (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + baseGableLines + .filter( + (line) => + (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) || + (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + + if (!alreadyHip) { + const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, null, degree1, degree1) + baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 }) + } + } + if (hipPoint2) { + let alreadyHip = false + baseHipLines + .filter( + (line) => + (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) || + (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + baseGableLines + .filter( + (line) => + (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) || + (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]), + ) + .forEach((line) => { + alreadyHip = true + }) + if (!alreadyHip) { + const hipLine2 = drawHipLine(hipPoint2, canvas, roof, textMode, null, degree2, degree2) + baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 }) + } + } + } + } + }) + /** ⨆ 모양 처마에 추녀마루를 그린다. */ drawEavesFirstLines.forEach((current) => { // 확인용 라인, 포인트 제거 @@ -2743,7 +3374,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { hipLength = currentSize.div(2).pow(2).plus(currentSize.div(2).pow(2)).sqrt() } else { if (currentAngle !== beforePrevAngle && currentAngle !== afterNextAngle && beforePrevLine !== afterNextLine) { - console.log('4각 아님') const beforePrevX1 = beforePrevLine.x1, beforePrevY1 = beforePrevLine.y1, beforePrevX2 = beforePrevLine.x2, @@ -2899,7 +3529,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const intersectPoints = [] rightAngleLine.forEach((line) => { const intersection = edgesIntersection( - { vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] }, vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] } }, + { + vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] }, + vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] }, + }, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, ) if (intersection) { @@ -2916,7 +3549,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { oppositeCurrentLine.forEach((line) => { const intersection = edgesIntersection( - { vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] }, vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] } }, + { + vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] }, + vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] }, + }, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, ) if (intersection) { @@ -3014,12 +3650,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { return prev.size < current.size ? prev : current }, intersectPoints[0]) - // console.log('intersectPoints', intersectPoints) - /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/ if (intersectPoints && intersectPoints.intersection) { - console.log('prevDegree', prevDegree, 'currentDegree', currentDegree) - prevHipLine = drawHipLine( [intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()], canvas, @@ -3112,30 +3744,28 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { prevDegree, currentDegree, ) - baseHipLines.push({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber(), line: nextHipLine }) + baseHipLines.push({ + x1: x2, + y1: y2, + x2: nextEndPoint.x.toNumber(), + y2: nextEndPoint.y.toNumber(), + line: nextHipLine, + }) } } - console.log('prevHipLine : ', prevHipLine) - console.log('nextHipLine : ', nextHipLine) /** 두 선이 교차하면 해당 포인트까지로 선 조정*/ if (prevHipLine !== undefined && nextHipLine !== undefined) { - const prevEdge = { vertex1: { x: prevHipLine.x1, y: prevHipLine.y1 }, vertex2: { x: prevHipLine.x2, y: prevHipLine.y2 } } - const nextEdge = { vertex1: { x: nextHipLine.x1, y: nextHipLine.y1 }, vertex2: { x: nextHipLine.x2, y: nextHipLine.y2 } } + const prevEdge = { + vertex1: { x: prevHipLine.x1, y: prevHipLine.y1 }, + vertex2: { x: prevHipLine.x2, y: prevHipLine.y2 }, + } + const nextEdge = { + vertex1: { x: nextHipLine.x1, y: nextHipLine.y1 }, + vertex2: { x: nextHipLine.x2, y: nextHipLine.y2 }, + } const intersection = edgesIntersection(prevEdge, nextEdge) - console.log('intersection : ', intersection) if (intersection) { - const checkPoint = new fabric.Circle({ - left: intersection.x, - top: intersection.y, - radius: 4, - fill: 'yellow', - parentId: roofId, - name: 'checkPoint', - }) - canvas.add(checkPoint) - canvas.renderAll() - /** 포인트 조정*/ baseHipLines .filter((line) => line.line === prevHipLine || line.line === nextHipLine) @@ -3179,12 +3809,9 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const xVector = Big(currentMidX).minus(Big(startPoint.x)).round(0, Big.roundDown) const yVector = Big(currentMidY).minus(Big(startPoint.y)).round(0, Big.roundDown) - console.log('beforePrevLine', beforePrevLine) if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) { - console.log('박공지붕 확인 후 마루 작성 ') const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line const oppositeAngle = calculateAngle(oppositeLine.startPoint, oppositeLine.endPoint) - console.log('currentAngle', currentAngle, 'oppositeAngle', oppositeAngle) let checkEdge if (Math.sign(oppositeLine.x1 - oppositeLine.x2) === 0) { checkEdge = { vertex1: startPoint, vertex2: { x: oppositeLine.x1, y: startPoint.y } } @@ -3192,9 +3819,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { checkEdge = { vertex1: startPoint, vertex2: { x: startPoint.x, y: oppositeLine.y1 } } } if (currentAngle === oppositeAngle) { - const oppositeEdge = { vertex1: { x: oppositeLine.x1, y: oppositeLine.y1 }, vertex2: { x: oppositeLine.x2, y: oppositeLine.y2 } } + const oppositeEdge = { + vertex1: { x: oppositeLine.x1, y: oppositeLine.y1 }, + vertex2: { x: oppositeLine.x2, y: oppositeLine.y2 }, + } const intersection = edgesIntersection(oppositeEdge, checkEdge) - console.log('intersection', intersection) if (intersection) { ridgeSize = Big(intersection.x) .minus(Big(startPoint.x)) @@ -3202,7 +3831,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { .plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2)) .sqrt() } - console.log('aaa') } else { const intersectPoints = [] roof.lines @@ -3214,18 +3842,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { .forEach((line) => { const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const intersection = edgesIntersection(lineEdge, checkEdge) - console.log('intersection', intersection) if (intersection) { - const checkPoint = new fabric.Circle({ - left: intersection.x, - top: intersection.y, - radius: 4, - fill: 'red', - parentId: roofId, - name: 'checkPoint', - }) - canvas.add(checkPoint) - canvas.renderAll() const size = Big(startPoint.x) .minus(Big(intersection.x)) .pow(2) @@ -3236,15 +3853,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) intersectPoints.sort((a, b) => a.size - b.size) - console.log('intersectPoints', intersectPoints) if (intersectPoints.length > 0) { ridgeSize = Big(intersectPoints[0].size) } - console.log('bbb') } } else { - console.log('마루 작성') - // baseLines에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산 + /** baseLines에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산*/ let minX = Infinity let maxX = -Infinity let minY = Infinity @@ -3363,7 +3977,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { ridgeSize = Big(Math.min(oppositeSize, lineMinSize)) } - console.log('ridgeSize', ridgeSize) if (ridgeSize.gt(0) && baseRidgeCount < getMaxRidge(baseLines.length)) { const points = [ startPoint.x, @@ -3508,7 +4121,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const intersectRidge = intersections[0].ridge const oppositeRoofPoints = [ridgeLine.x2, ridgeLine.y2, intersection.x, intersection.y] const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, null, secondDegree, secondDegree) - baseHipLines.push({ x1: oppositeLine.x1, y1: oppositeLine.y1, x2: oppositeLine.x2, y2: oppositeLine.y2, line: oppositeRoofLine }) + baseHipLines.push({ + x1: oppositeLine.x1, + y1: oppositeLine.y1, + x2: oppositeLine.x2, + y2: oppositeLine.y2, + line: oppositeRoofLine, + }) const ridgeVector = Math.sign(ridgeLine.y1 - ridgeLine.y2) const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2] @@ -3611,7 +4230,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const intersectRidge = intersections[0].ridge const oppositeRoofPoints = [ridgeLine.x2, ridgeLine.y2, intersection.x, intersection.y] const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, null, secondDegree, secondDegree) - baseHipLines.push({ x1: oppositeLine.x1, y1: oppositeLine.y1, x2: oppositeLine.x2, y2: oppositeLine.y2, line: oppositeRoofLine }) + baseHipLines.push({ + x1: oppositeLine.x1, + y1: oppositeLine.y1, + x2: oppositeLine.x2, + y2: oppositeLine.y2, + line: oppositeRoofLine, + }) const ridgeVector = Math.sign(ridgeLine.x1 - ridgeLine.x2) const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2] @@ -3634,12 +4259,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } } } - - canvas - .getObjects() - .filter((obj) => obj.name === 'checkPoint' || obj.name === 'checkLine') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() }) /** 중복제거 */ @@ -3667,7 +4286,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { }) }) - // console.log('drawEavesSecondLines : ', drawEavesSecondLines) /** ㄴ 모양 처마에 추녀마루를 그린다. */ drawEavesSecondLines.forEach((current) => { const { currentBaseLine, prevBaseLine, nextBaseLine } = current @@ -3676,31 +4294,11 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const nextLine = nextBaseLine.line let { x1, x2, y1, y2, size } = currentBaseLine - // const checkLine = new fabric.Line([x1, y1, x2, y2], { - // stroke: 'yellow', - // strokeWidth: 4, - // parentId: roof.id, - // name: 'checkLine', - // }) - // canvas.add(checkLine) - // canvas.renderAll() - // checkLine.bringToFront() - /** 이전 라인의 경사 */ const prevDegree = prevLine.attributes.pitch > 0 ? getDegreeByChon(prevLine.attributes.pitch) : prevLine.attributes.degree /** 다음 라인의 경사 */ const currentDegree = currentLine.attributes.pitch > 0 ? getDegreeByChon(currentLine.attributes.pitch) : currentLine.attributes.degree - //라인 확인용 - /*const checkCurrentLine = new fabric.Line([x1, y1, x2, y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roof.id, - }) - canvas.add(checkCurrentLine) - canvas.renderAll()*/ - // console.log('currentLine : ', currentLine.attributes.planeSize) - /** 이전, 다음라인의 사잇각의 vector를 구한다. */ let prevVector = getHalfAngleVector(prevLine, currentLine) let nextVector = getHalfAngleVector(currentLine, nextLine) @@ -3710,8 +4308,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { /** 각 라인의 흐름 방향을 확인한다. */ const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - /*const beforePrevAngle = calculateAngle(beforePrevLine.startPoint, beforePrevLine.endPoint) - const afterNextAngle = calculateAngle(afterNextLine.startPoint, afterNextLine.endPoint)*/ /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */ let hipLength = Big(x2) @@ -3719,8 +4315,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { .plus(Big(y2).minus(Big(y1))) .abs() - // console.log('currentLine : ', currentLine.attributes.planeSize) - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ const prevCheckPoint = { x: Big(x1).plus(Big(prevHipVector.x).times(10)), @@ -3741,7 +4335,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { let prevHipLine, nextHipLine /** 이전라인과의 연결지점에 추녀마루를 그린다. */ - // console.log('이전라인 : ', baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0 && eavesType.includes(prevLine.attributes.type)) { let prevEndPoint = { x: Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2), @@ -3750,8 +4343,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const prevEndEdge = { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint } - // console.log('prevHipVector : ', prevHipVector.x.toNumber(), prevHipVector.x.s, prevHipVector.y.toNumber(), prevHipVector.y.s) - const intersectBaseLine = [] baseLines .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine) @@ -3763,20 +4354,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) .forEach((line) => { - // console.log('line : ', line.attributes.planeSize) const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const intersection = edgesIntersection(prevEndEdge, lineEdge) if (intersection && Big(intersection.x - x1).s === nextHipVector.x.s && Big(intersection.y - y1).s === nextHipVector.y.s) { - /* const circle = new fabric.Circle({ - left: intersection.x - 2, - top: intersection.y - 2, - radius: 4, - fill: 'red', - parentId: roof.id, - }) - canvas.add(circle) - canvas.renderAll()*/ const size = Big(intersection.x - x1) .abs() .pow(2) @@ -3816,27 +4397,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint }, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, ) - /*const checkLine = new fabric.Line([x1, y1, prevEndPoint.x, prevEndPoint.y], { - stroke: 'red', - strokeWidth: 2, - parentId: roof.id, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll()*/ - - /* if (intersection) { - const intersectCircle = new fabric.Circle({ - left: intersection.x - 2, - top: intersection.y - 2, - radius: 4, - fill: 'red', - parentId: roof.id, - name: 'checkPoint', - }) - canvas.add(intersectCircle) - canvas.renderAll() - }*/ if (intersection && !intersection.isIntersectionOutside) { intersectRidgeLine.push({ intersection, @@ -3869,15 +4429,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { vertex2: prevEndPoint, } - /* const checkLine = new fabric.Line([hipEdge.vertex1.x, hipEdge.vertex1.y, hipEdge.vertex2.x, hipEdge.vertex2.y], { - stroke: 'yellow', - strokeWidth: 2, - parentId: roof.id, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll()*/ - let intersectPoints = [] /** 외벽선에서 추녀 마루가 겹치는 경우에 대한 확인*/ roof.lines.forEach((line) => { @@ -3889,16 +4440,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { Math.sign(prevEndPoint.x - x1) === Math.sign(prevEndPoint.x - intersection.x) && Math.sign(prevEndPoint.y - y1) === Math.sign(prevEndPoint.y - intersection.y) ) { - /*const intersectPoint = new fabric.Circle({ - left: intersection.x - 2, - top: intersection.y - 2, - radius: 4, - fill: 'cyan', - parentId: roof.id, - }) - canvas.add(intersectPoint) - canvas.renderAll()*/ - const intersectSize = prevEndPoint.x .minus(Big(intersection.x)) .abs() @@ -3918,8 +4459,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { return prev.size < current.size ? prev : current }, intersectPoints[0]) - // console.log('intersectPoints', intersectPoints) - /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/ if (intersectPoints && intersectPoints.intersection) { prevHipLine = drawHipLine( @@ -3935,21 +4474,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } } /** 다음라인과의 연결지점에 추녀마루를 그린다. */ - // console.log('다음라인 : ', baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0 && eavesType.includes(nextLine.attributes.type)) { let nextEndPoint = { x: Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2), y: Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2), } - /*const nextEndLine = new fabric.Line([x2, y2, nextEndPoint.x, nextEndPoint.y], { - stroke: 'red', - strokeWidth: 2, - parentId: roof.id, - }) - canvas.add(nextEndLine) - canvas.renderAll()*/ - const nextEndEdge = { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint, @@ -3966,21 +4496,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) .forEach((line) => { - // console.log('line : ', line.attributes.planeSize) const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const intersection = edgesIntersection(nextEndEdge, lineEdge) if (intersection && Big(intersection.x - x2).s === nextHipVector.x.s && Big(intersection.y - y2).s === nextHipVector.y.s) { - /*console.log('next intersection ============') - const circle = new fabric.Circle({ - left: intersection.x - 2, - top: intersection.y - 2, - radius: 4, - fill: 'red', - parentId: roof.id, - }) - canvas.add(circle) - canvas.renderAll()*/ const size = Big(intersection.x - x2) .abs() .pow(2) @@ -4016,8 +4535,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const intersectRidgeLine = [] baseRidgeLines.forEach((line) => { - // console.log('nextEndPoint : ', nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()) - // console.log('intersection : ', 'x : ', line.x1, 'y : ', line.y1, 'x : ', line.x2, 'y : ', line.y2) const intersection = edgesIntersection( { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint }, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, @@ -4035,7 +4552,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0]) - // console.log('intersectRidge : ', intersectRidge) if (intersectRidge) { nextEndPoint.x = Big(intersectRidge.intersection.x).round(1) @@ -4052,38 +4568,16 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { vertex2: nextEndPoint, } - /* const checkLine = new fabric.Line([hipEdge.vertex1.x, hipEdge.vertex1.y, hipEdge.vertex2.x, hipEdge.vertex2.y], { - stroke: 'yellow', - strokeWidth: 2, - parentId: roof.id, - }) - canvas.add(checkLine) - canvas.renderAll()*/ - let intersectPoints = [] 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) - // console.log('intersection', intersection) if ( intersection && !intersection.isIntersectionOutside && Math.sign(nextEndPoint.x - x2) === Math.sign(nextEndPoint.x - intersection.x) && Math.sign(nextEndPoint.y - y2) === Math.sign(nextEndPoint.y - intersection.y) ) { - /*const intersectPoint = new fabric.Circle({ - left: intersection.x - 2, - top: intersection.y - 2, - radius: 4, - fill: 'blue', - parentId: roof.id, - }) - canvas.add(intersectPoint) - canvas.renderAll()*/ - - // console.log('nextEndPoint', nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()) - // console.log('intersection', intersection.x, intersection.y) - const intersectSize = nextEndPoint.x .minus(Big(intersection.x)) .pow(2) @@ -4103,8 +4597,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { return prev.size < current.size ? prev : current }, intersectPoints[0]) - // console.log('intersectPoints : ', intersectPoints) - if (intersectPoints && intersectPoints.intersection) { nextHipLine = drawHipLine( [intersectPoints.intersection.x, intersectPoints.intersection.y, nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()], @@ -4115,7 +4607,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { prevDegree, currentDegree, ) - baseHipLines.push({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber(), line: nextHipLine }) + baseHipLines.push({ + x1: x2, + y1: y2, + x2: nextEndPoint.x.toNumber(), + y2: nextEndPoint.y.toNumber(), + line: nextHipLine, + }) } } }) @@ -4134,7 +4632,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const hipLineEdge = { vertex1: { x: hipLine.x1, y: hipLine.y1 }, vertex2: { x: hipLine.x2, y: hipLine.y2 } } baseRidgeLines.forEach((ridgeLine) => { - const ridgeLineEdge = { vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 }, vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 } } + const ridgeLineEdge = { + vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 }, + vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 }, + } const intersection = edgesIntersection(hipLineEdge, ridgeLineEdge) if (intersection) { @@ -4171,7 +4672,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const theta = Big(Math.acos(Big(oldPlaneSize).div(oldActualSize))) .times(180) .div(Math.PI) - const planeSize = calcLinePlaneSize({ x1: hipLine.line.x1, y1: hipLine.line.y1, x2: hipLine.line.x2, y2: hipLine.line.y2 }) + const planeSize = calcLinePlaneSize({ + x1: hipLine.line.x1, + y1: hipLine.line.y1, + x2: hipLine.line.x2, + y2: hipLine.line.y2, + }) hipLine.x2 = intersectRidgePoints[0].x hipLine.y2 = intersectRidgePoints[0].y hipLine.line.set({ x2: intersectRidgePoints[0].x, y2: intersectRidgePoints[0].y }) @@ -4182,8 +4688,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) - console.log('baseHipLines : ', baseHipLines) - console.log('baseRidgeLines : ', baseRidgeLines) /** 지붕선에 맞닫지 않은 부분을 확인하여 처리 한다.*/ /** 1. 그려진 마루 중 추녀마루가 부재하는 경우를 판단. 부재는 연결된 라인이 홀수인 경우로 판단한다.*/ let unFinishedRidge = [] @@ -4300,8 +4804,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { prevDegree = degreeAllLine[1] } - console.log('unFinishedRidge : ', unFinishedRidge) - console.log('unFinishedPoint : ', unFinishedPoint) /** 라인이 부재한 마루에 라인을 찾아 그린다.*/ unFinishedRidge.forEach((current) => { let checkPoints = [] @@ -4351,7 +4853,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseHipLines.forEach((line) => { const checkAngel1 = calculateAngle({ x: point[0], y: point[1] }, { x: point[2], y: point[3] }) - const checkAngel2 = calculateAngle({ x: line.line.x1, y: line.line.y1 }, { x: line.line.x2, y: line.line.y2 }) + const checkAngel2 = calculateAngle( + { x: line.line.x1, y: line.line.y1 }, + { + x: line.line.x2, + y: line.line.y2, + }, + ) const isConnectLine = ((line.line.x1 === point[0] && line.line.y1 === point[1]) || (line.line.x2 === point[0] && line.line.y2 === point[1])) && @@ -4378,7 +4886,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { .times(180) .div(Math.PI) .round(1) - console.log('theta : ', theta.toNumber()) prevDegree = theta.toNumber() currentDegree = theta.toNumber() canvas.remove(line.line) @@ -4458,15 +4965,25 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { basePoints.sort((a, b) => a.line.attributes.planeSize - b.line.attributes.planeSize) hipSize = Big(basePoints[0].line.attributes.planeSize) } - hipSize = hipSize.pow(2).div(2).sqrt().round().div(10).toNumber() - // console.log('hipSize : ', hipSize.toNumber()) /** 현재 라인을 기준으로 45, 135, 225, 315 방향을 확인하기 위한 좌표, hip은 45도 방향으로만 그린다. */ - const checkEdge45 = { vertex1: { x: current.x, y: current.y }, vertex2: { x: current.x + hipSize, y: current.y - hipSize } } - const checkEdge135 = { vertex1: { x: current.x, y: current.y }, vertex2: { x: current.x + hipSize, y: current.y + hipSize } } - const checkEdge225 = { vertex1: { x: current.x, y: current.y }, vertex2: { x: current.x - hipSize, y: current.y + hipSize } } - const checkEdge315 = { vertex1: { x: current.x, y: current.y }, vertex2: { x: current.x - hipSize, y: current.y - hipSize } } + const checkEdge45 = { + vertex1: { x: current.x, y: current.y }, + vertex2: { x: current.x + hipSize, y: current.y - hipSize }, + } + const checkEdge135 = { + vertex1: { x: current.x, y: current.y }, + vertex2: { x: current.x + hipSize, y: current.y + hipSize }, + } + const checkEdge225 = { + vertex1: { x: current.x, y: current.y }, + vertex2: { x: current.x - hipSize, y: current.y + hipSize }, + } + const checkEdge315 = { + vertex1: { x: current.x, y: current.y }, + vertex2: { x: current.x - hipSize, y: current.y - hipSize }, + } let intersectPoints = [] let notIntersect45 = true, @@ -4590,9 +5107,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) - // canvas.remove(checkPoint) - // canvas.renderAll() - /** 직교 하는 포인트가 존재 할때 마루를 그린다. */ if (orthogonalPoints.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) { baseRidgeCount = baseRidgeCount + 1 @@ -4663,7 +5177,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const yVector = Math.sign(Big(line.y2).minus(Big(line.y1))) let lineIntersectPoints = [] checkEdgeLines.forEach((edge) => { - const intersectEdge = edgesIntersection(edge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersectEdge = edgesIntersection(edge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersectEdge) { const isXVector = Math.sign(Big(intersectEdge.x).minus(Big(line.x1))) === xVector const isYVector = Math.sign(Big(intersectEdge.y).minus(Big(line.y1))) === yVector @@ -4692,18 +5209,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) - console.log('noRidgeHipPoints : ', noRidgeHipPoints) /** 마루를 그릴수 있는지 찾는다. */ noRidgeHipPoints.forEach((hipPoint) => { - const checkLine = new fabric.Line([hipPoint.x2, hipPoint.y2, hipPoint.x1, hipPoint.y1], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll() - const ridgePoints = [] intersectPoints .filter( @@ -4776,7 +5283,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const checkEdge = { vertex1: { x: intersection.x, y: intersection.y }, - vertex2: { x: Big(intersection.x).plus(Big(xVector).times(10)).toNumber(), y: Big(intersection.y).plus(Big(yVector).times(10)).toNumber() }, + vertex2: { + x: Big(intersection.x).plus(Big(xVector).times(10)).toNumber(), + y: Big(intersection.y).plus(Big(yVector).times(10)).toNumber(), + }, } const intersectX = edgesIntersection( { @@ -4825,7 +5335,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) - console.log('linePoints : ', linePoints) const linePoint = linePoints.reduce((prev, current) => { const prevDistance = Big(prev.intersection.x) .minus(Big(hipPoint.x2)) @@ -4848,29 +5357,17 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { if (!linePoint) return const hipStartPoint = [hipPoint.x2, hipPoint.y2, linePoint.intersection.x, linePoint.intersection.y] - // console.log('hipStartPoint : ', hipStartPoint) /** 직선인 경우 마루를 그린다.*/ if ( ((hipStartPoint[0] === hipStartPoint[2] && hipStartPoint[1] !== hipStartPoint[3]) || (hipStartPoint[0] !== hipStartPoint[2] && hipStartPoint[1] === hipStartPoint[3])) && baseRidgeCount < getMaxRidge(baseLines.length) ) { - // console.log('릿지1') const ridgeLine = drawRidgeLine(hipStartPoint, canvas, roof, textMode) baseRidgeCount = baseRidgeCount + 1 baseRidgeLines.push(ridgeLine) noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint) } - // console.log( - // Big(hipStartPoint[0]).minus(Big(hipStartPoint[2])).abs().toNumber(), - // Big(hipStartPoint[1]).minus(Big(hipStartPoint[3])).abs().toNumber(), - // Big(hipStartPoint[0]) - // .minus(Big(hipStartPoint[2])) - // .abs() - // .minus(Big(hipStartPoint[1]).minus(Big(hipStartPoint[3])).abs()) - // .abs() - // .lt(1), - // ) /** 대각선인경우 hip을 그린다. */ if ( Big(hipStartPoint[0]) @@ -4882,7 +5379,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { ) { // console.log('힙1') const hipLine = drawHipLine(hipStartPoint, canvas, roof, textMode, null, prevDegree, currentDegree) - baseHipLines.push({ x1: hipStartPoint[0], y1: hipStartPoint[1], x2: hipStartPoint[2], y2: hipStartPoint[3], line: hipLine }) + baseHipLines.push({ + x1: hipStartPoint[0], + y1: hipStartPoint[1], + x2: hipStartPoint[2], + y2: hipStartPoint[3], + line: hipLine, + }) noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint) } @@ -4901,9 +5404,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseRidgeCount = baseRidgeCount + 1 baseRidgeLines.push(ridgeLine) } - - // console.log('isStartPoint : ', isStartPoint) - // console.log(Big(isStartPoint[0]).minus(Big(isStartPoint[2])).toNumber()) if ( Big(isStartPoint[0]) .minus(Big(isStartPoint[2])) @@ -4913,7 +5413,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { .lt(1) ) { const hipLine = drawHipLine(isStartPoint, canvas, roof, textMode, null, prevDegree, currentDegree) - baseHipLines.push({ x1: isStartPoint[0], y1: isStartPoint[1], x2: isStartPoint[2], y2: isStartPoint[3], line: hipLine }) + baseHipLines.push({ + x1: isStartPoint[0], + y1: isStartPoint[1], + x2: isStartPoint[2], + y2: isStartPoint[3], + line: hipLine, + }) } } }) @@ -4921,9 +5427,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const ridgeAllPoints = [] baseRidgeLines.forEach((line) => ridgeAllPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })) - // console.log('ridge count', baseRidgeCount, getMaxRidge(baseLines.length)) - - console.log('baseLinePoints : ', baseLinePoints) /** hip 중에 지붕의 라인과 만나지 않은 선을 확인.*/ baseHipLines .filter( @@ -4948,15 +5451,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { return !isIntersect }) .forEach((hip) => { - console.log('hip : ', hip) - const checkLine = new fabric.Line([hip.line.x1, hip.line.y1, hip.line.x2, hip.line.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll() const hipLine = hip.line if (hipLine) { const hipVectorX = Big(hipLine.x2).plus(Big(hipLine.attributes.planeSize).times(Big(hipLine.x1).minus(Big(hipLine.x2)).neg().s)) @@ -4969,7 +5463,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const checkLineEdge = { vertex1: { x: minX, y: hipLine.y2 }, vertex2: { x: maxX, y: hipLine.y2 } } let isIntersect = false baseHipLines.forEach((baseHipLine) => { - const edge = { vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 }, vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 } } + const edge = { + vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 }, + vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 }, + } const intersection = edgesIntersection(edge, checkLineEdge) if (intersection && !intersection.isIntersectionOutside) { const isVectorX = Math.sign(Big(intersection.x).minus(Big(baseHipLine.x2))) @@ -4980,7 +5477,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) baseRidgeLines.forEach((baseRidgeLine) => { - const edge = { vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 }, vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 } } + const edge = { + vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 }, + vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 }, + } const intersection = edgesIntersection(edge, checkLineEdge) if (intersection && !intersection.isIntersectionOutside) { const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2))) @@ -5000,7 +5500,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { const checkLineEdge = { vertex1: { x: hipLine.x2, y: minY }, vertex2: { x: hipLine.x2, y: maxY } } let isIntersect = false baseHipLines.forEach((baseHipLine) => { - const edge = { vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 }, vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 } } + const edge = { + vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 }, + vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 }, + } const intersection = edgesIntersection(edge, checkLineEdge) if (intersection && !intersection.isIntersectionOutside) { const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2))) @@ -5011,7 +5514,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } }) baseRidgeLines.forEach((baseRidgeLine) => { - const edge = { vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 }, vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 } } + const edge = { + vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 }, + vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 }, + } const intersection = edgesIntersection(edge, checkLineEdge) if (intersection && !intersection.isIntersectionOutside) { const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2))) @@ -5074,7 +5580,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { } const modifiedBaseLine = baseLines.filter((line) => (hip.x2 === line.x1 && hip.y2 === line.y1) || (hip.x2 === line.x2 && hip.y2 === line.y2)) - console.log('modifiedBaseLine : ', modifiedBaseLine) if (modifiedBaseLine.length === 0) return const verticalLine = modifiedBaseLine.find( (line) => @@ -5083,8 +5588,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { ) const horizonLine = modifiedBaseLine.find((line) => line !== verticalLine) - console.log('verticalLine', verticalLine) - console.log('horizonLine : ', horizonLine) const horizonRoof = roof.lines.find((line) => { const originPoint = horizonLine.attributes.originPoint if (originPoint.y1 === originPoint.y2) { @@ -5118,10 +5621,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { (hipLine) => hipLine.x1 === horizonPoint[0] && hipLine.y1 === horizonPoint[1] && hipLine.x2 === horizonPoint[2] && hipLine.y2 === horizonPoint[3], ) - console.log('alreadyHorizonLines : ', alreadyHorizonLines) if (!alreadyHorizonLines) { addLine = drawHipLine(horizonPoint, canvas, roof, textMode, null, prevDegree, currentDegree) - baseHipLines.push({ x1: horizonPoint[0], y1: horizonPoint[1], x2: horizonPoint[2], y2: horizonPoint[3], line: addLine }) + baseHipLines.push({ + x1: horizonPoint[0], + y1: horizonPoint[1], + x2: horizonPoint[2], + y2: horizonPoint[3], + line: addLine, + }) } else { addLine = alreadyHorizonLines } @@ -5138,7 +5646,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { ) if (!alreadyVerticalLine) { addLine = drawHipLine(verticalPoint, canvas, roof, textMode, null, prevDegree, currentDegree) - baseHipLines.push({ x1: verticalPoint[0], y1: verticalPoint[1], x2: verticalPoint[2], y2: verticalPoint[3], line: addLine }) + baseHipLines.push({ + x1: verticalPoint[0], + y1: verticalPoint[1], + x2: verticalPoint[2], + y2: verticalPoint[3], + line: addLine, + }) } } }) @@ -5167,21 +5681,33 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { let baseIntersection = false const ridgeInterSection = [] - const ridgeEdge = { vertex1: { x: ridgePoints[0], y: ridgePoints[1] }, vertex2: { x: ridgePoints[2], y: ridgePoints[3] } } + const ridgeEdge = { + vertex1: { x: ridgePoints[0], y: ridgePoints[1] }, + vertex2: { x: ridgePoints[2], y: ridgePoints[3] }, + } baseLines.forEach((line) => { - const intersection = edgesIntersection(ridgeEdge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersection = edgesIntersection(ridgeEdge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersection && !intersection.isIntersectionOutside) { ridgeInterSection.push(intersection) } }) baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection(ridgeEdge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersection = edgesIntersection(ridgeEdge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersection && !intersection.isIntersectionOutside) { ridgeInterSection.push(intersection) } }) baseHipLines.forEach((line) => { - const intersection = edgesIntersection(ridgeEdge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersection = edgesIntersection(ridgeEdge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersection && !intersection.isIntersectionOutside) { ridgeInterSection.push(intersection) } @@ -5215,21 +5741,33 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { let baseIntersection = false let hipInterSection = [] - const hipEdge = { vertex1: { x: hipPoints[0], y: hipPoints[1] }, vertex2: { x: hipPoints[2], y: hipPoints[3] } } + const hipEdge = { + vertex1: { x: hipPoints[0], y: hipPoints[1] }, + vertex2: { x: hipPoints[2], y: hipPoints[3] }, + } baseLines.forEach((line) => { - const intersection = edgesIntersection(hipEdge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersection = edgesIntersection(hipEdge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersection && !intersection.isIntersectionOutside && eavesType.includes(line.attributes.type)) { baseIntersection = true } }) baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection(hipEdge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersection = edgesIntersection(hipEdge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersection && !intersection.isIntersectionOutside) { hipInterSection.push(intersection) } }) baseHipLines.forEach((line) => { - const intersection = edgesIntersection(hipEdge, { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }) + const intersection = edgesIntersection(hipEdge, { + vertex1: { x: line.x1, y: line.y1 }, + vertex2: { x: line.x2, y: line.y2 }, + }) if (intersection && !intersection.isIntersectionOutside) { hipInterSection.push(intersection) } @@ -5260,33 +5798,29 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => { baseHipLines.filter((hipLine2) => hipLine !== hipLine2).forEach((hipLine2) => {}) }) - const innerLines = [...baseRidgeLines, ...baseGableRidgeLines, ...baseHipLines.map((line) => line.line)] - roof.innerLines = innerLines - /*const uniqueInnerLines = [] + const innerLines = [...baseRidgeLines, ...baseGableRidgeLines, ...baseGableLines, ...baseHipLines.map((line) => line.line)] + const uniqueInnerLines = [] innerLines.forEach((currentLine) => { - const sameLines = uniqueInnerLines.filter( - (line) => - line !== currentLine && - ((line.x1 === currentLine.x1 && line.y1 === currentLine.y1 && line.x2 === currentLine.x2 && line.y2 === currentLine.y2) || - (line.x1 === currentLine.x2 && line.y1 === currentLine.y2 && line.x2 === currentLine.x1 && line.y2 === currentLine.y1)), - ) - - if (sameLines.length === 0) { - uniqueInnerLines.push(currentLine) + if (currentLine.length === 0) { + canvas.remove(currentLine) } else { - sameLines.forEach((line) => canvas.remove(line)) + const sameLines = uniqueInnerLines.filter( + (line) => + line !== currentLine && + ((line.x1 === currentLine.x1 && line.y1 === currentLine.y1 && line.x2 === currentLine.x2 && line.y2 === currentLine.y2) || + (line.x1 === currentLine.x2 && line.y1 === currentLine.y2 && line.x2 === currentLine.x1 && line.y2 === currentLine.y1)), + ) + + if (sameLines.length === 0) { + uniqueInnerLines.push(currentLine) + } else { + canvas.remove(currentLine) + } } }) canvas.renderAll() - roof.innerLines = uniqueInnerLines*/ - - /** 확인용 라인, 포인트 제거 */ - canvas - .getObjects() - .filter((obj) => obj.name === 'checkPoint' || obj.name === 'checkLine') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() + roof.innerLines = uniqueInnerLines /*drawRidge(roof, canvas, textMode) drawHips(roof, canvas, textMode) @@ -5500,367 +6034,15 @@ const getHalfAngleVector = (line1, line2) => { * 두 벡터를 더합니다 * @type {{x: *, y: *}} */ - const summedVector = { x: Big(unitV1.x).plus(Big(unitV2.x)).toNumber(), y: Big(unitV1.y).plus(Big(unitV2.y)).toNumber() } + const summedVector = { + x: Big(unitV1.x).plus(Big(unitV2.x)).toNumber(), + y: Big(unitV1.y).plus(Big(unitV2.y)).toNumber(), + } /** 결과 벡터를 정규화하여 사잇각 벡터를 반환합니다 */ return normalizeVector(summedVector) } -/** - * 마루가 존재하면 그린다. 마루는 지붕의 중간에 위치한다. - * - * @param roof - * @param canvas - * @param textMode - */ -const drawRidges = (roof, canvas, textMode) => { - console.log('roof.lines : ', roof.lines) - const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines // 외벽의 라인 - const roofLines = roof.lines // 지붕의 라인 - let ridgeRoof = [] - - roofLines.forEach((currentRoof, index) => { - let prevRoof, - nextRoof, - currentWall = wallLines[index] - - prevRoof = index === 0 ? wallLines[wallLines.length - 1] : wallLines[index - 1] - nextRoof = index === wallLines.length - 1 ? wallLines[0] : index === wallLines.length ? wallLines[1] : wallLines[index + 1] - - const angle1 = Big(calculateAngle(prevRoof.startPoint, prevRoof.endPoint)) - const angle2 = Big(calculateAngle(nextRoof.startPoint, nextRoof.endPoint)) - if ( - angle1.minus(angle2).abs().round(Big.roundHalfUp).toNumber() === 180 && - currentWall.attributes.planeSize <= currentRoof.attributes.planeSize - ) { - ridgeRoof.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize }) - } - }) - - // 지붕의 길이가 짧은 순으로 정렬 - ridgeRoof.sort((a, b) => a.length - b.length) - - ridgeRoof.forEach((item) => { - if (getMaxRidge(roofLines.length) > roof.ridges.length) { - const index = item.index, - currentRoof = item.roof - const prevRoof = index === 0 ? roofLines[wallLines.length - 1] : roofLines[index - 1] - const nextRoof = index === roofLines.length - 1 ? roofLines[0] : index === roofLines.length ? roofLines[1] : roofLines[index + 1] - let startXPoint, startYPoint, endXPoint, endYPoint - - let wallLine = wallLines.filter((w) => w.id === currentRoof.attributes.wallLine) - if (wallLine.length > 0) { - wallLine = wallLine[0] - } - - const anotherRoof = roofLines.filter((roof) => roof !== currentRoof && roof !== prevRoof && roof !== nextRoof) - - let currentX1 = Big(currentRoof.x1), - currentY1 = Big(currentRoof.y1), - currentX2 = Big(currentRoof.x2), - currentY2 = Big(currentRoof.y2) - let ridgeMaxLength = Big(Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize)).div(10) - let ridgeMinLength = Big(Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize)).div(10) - - const currentAngle = Math.atan2(currentY2.minus(currentY1).toNumber(), currentX2.minus(currentX1).toNumber()) * (180 / Math.PI) - anotherRoof - .filter((roof) => isInnerLine(prevRoof, currentRoof, nextRoof, roof)) - .forEach((innerRoof) => { - const vector1 = { x: currentX2.minus(currentX1), y: currentY2.minus(currentY1) } - const vector2 = { - x: Big(innerRoof.x2).minus(Big(innerRoof.x1)), - y: Big(innerRoof.y2).minus(Big(innerRoof.y1)), - } - - const dotProduct = vector1.x.times(vector2.x).plus(vector1.y.times(vector2.y)) - const magnitude1 = vector1.x.pow(2).plus(vector1.y.pow(2)).sqrt() - const magnitude2 = vector2.x.pow(2).plus(vector2.y.pow(2)).sqrt() - const angle = (Math.acos(dotProduct.div(magnitude1.times(magnitude2).toNumber())) * 180) / Math.PI - - // 현재 지붕선과 직각인 선 - if (Math.abs(angle) === 90) { - const innerBefore = roofLines.find((line) => innerRoof.x1 === line.x2 && innerRoof.y1 === line.y2) - const ibAngle = - Math.atan2(Big(innerBefore.y2).minus(Big(innerBefore.y1)).toNumber(), Big(innerBefore.x2).minus(Big(innerBefore.x1)).toNumber()) * - (180 / Math.PI) - if (Math.abs(Big(currentAngle).minus(Big(ibAngle))) === 180) { - if (currentAngle === 0 || currentAngle === 180) { - currentX2 = innerRoof.x1 - ridgeMinLength = Big(nextRoof.x1) - .minus(Big(nextRoof.x2)) - .times(10) - .round() - .pow(2) - .plus(Big(nextRoof.y1).minus(Big(nextRoof.y2)).times(10).round().pow(2)) - .sqrt() - .div(10) - } - if (currentAngle === 90 || currentAngle === 270) { - currentY2 = innerRoof.y1 - ridgeMinLength = Big(nextRoof.x1) - .minus(Big(innerRoof.x2)) - .times(10) - .round() - .pow(2) - .plus(Big(nextRoof.y1).minus(Big(nextRoof.y2)).times(10).round().pow(2)) - .sqrt() - .div(10) - } - } - if (Math.abs(currentAngle - ibAngle) === 0) { - if (currentAngle === 0 || currentAngle === 180) { - currentX1 = innerRoof.x2 - ridgeMinLength = Big(prevRoof.x1) - .minus(Big(prevRoof.x2)) - .times(10) - .round() - .pow(2) - .plus(Big(prevRoof.y1).minus(Big(innerRoof.y1)).times(10).round().pow(2)) - .sqrt() - .div(10) - } - if (currentAngle === 90 || currentAngle === 270) { - currentY1 = innerRoof.y2 - ridgeMinLength = Big(prevRoof.x1) - .minus(innerRoof.x1) - .times(10) - .round() - .pow(2) - .plus(Big(prevRoof.y2).minus(prevRoof.y2).times(10).round().pow(2)) - .sqrt() - .div(10) - } - } - } - // 현재 지붕선과 반대인 선 - if (Math.abs(angle) === 180) { - if (currentAngle === 0 || currentAngle === 180) { - } - if (currentAngle === 90 || currentAngle === 270) { - } - } - }) - - // 지붕선의 X 중심 - const midX = currentX1.plus(currentX2).div(2) - // 지붕선의 Y 중심 - const midY = currentY1.plus(currentY2).div(2) - - // 외선벽과 지붕선의 X 거리 - const alpha = Big(currentRoof.x1) - .plus(Big(currentRoof.x2)) - .div(2) - .minus(Big(wallLine.x1).plus(Big(wallLine.x2)).div(2)) - // 외벽벽과 지붕선의 Y 거리 - const beta = Big(currentRoof.y1) - .plus(Big(currentRoof.y2)) - .div(2) - .minus(Big(wallLine.y1).plus(Big(wallLine.y2)).div(2)) - // 외벽벽과 지붕선의 거리 - const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() - - // 지붕선의 평면길이 - const currentPlaneSize = Big(calcLinePlaneSize({ x1: currentX1, y1: currentY1, x2: currentX2, y2: currentY2 })) - // 용마루의 기반길이(지붕선에서 떨어진 정도) - let ridgeBaseLength = currentPlaneSize.div(2).round().div(10) - - // 시작점은 현재 지붕선을 대각선으로 한 직각이등변삼각형으로 판단하고 현재 지붕선의 가운데에서 지붕에서 90도방향으로 지붕선의 절반만큼 떨어진 방향으로 설정한다. - startXPoint = midX.plus(alpha.div(hypotenuse).times(currentPlaneSize.div(2)).neg().div(10)) - startYPoint = midY.plus(beta.div(hypotenuse).times(currentPlaneSize.div(2)).neg().div(10)) - - // 종료점은 시작점에서 용마루의 최대길이 + 기반길이 만큼 그려진것으로 판단하여 늘린다. - const checkEndXPoint = startXPoint.plus(Big(Math.sign(alpha.toNumber())).times(ridgeMaxLength.plus(ridgeBaseLength)).neg()) - const checkEndYPoint = startYPoint.plus(Big(Math.sign(beta.toNumber())).times(ridgeMaxLength.plus(ridgeBaseLength)).neg()) - - // 맞은편 외벽선을 확인하기 위한 라인을 생성 - const checkLine = new QLine([startXPoint.toNumber(), startYPoint.toNumber(), checkEndXPoint.toNumber(), checkEndYPoint.toNumber()], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: 'red', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoofId: currentRoof.id, actualSize: 0 }, - }) - // 디버그시 주석제거해서 라인 확인 - // canvas.add(checkLine) - // canvas.renderAll() - - // checkLine 과 마주치는 지붕선을 모두 찾아낸다. - const intersectLines = [] - roofLines.forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: checkLine.x1, y: checkLine.y1 }, vertex2: { x: checkLine.x2, y: checkLine.y2 } }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection && !intersection.isIntersectionOutside) { - intersectLines.push({ x: intersection.x, y: intersection.y, line: line }) - } - }) - // intersectLines 중 현재 지붕선과 가장 가까운 지붕선을 찾는다. - if (intersectLines.length > 0) { - intersectLines.reduce((prev, current) => { - if (prev !== undefined) { - const prevDistance = Big(prev.x).minus(startXPoint).pow(2).plus(Big(prev.y).minus(startYPoint).pow(2)).sqrt() - const currentDistance = Big(current.x).minus(startXPoint).pow(2).plus(Big(current.y).minus(startYPoint).pow(2)).sqrt() - return prevDistance > currentDistance ? current : prev - } else { - return current - } - }, undefined) - } - // 현재 지붕선과 마주하는 지붕선이 있는 경우 - if (intersectLines.length > 0) { - // 마주하는 지붕선 - const intersectLine = intersectLines[0] - - //지붕선에서 마주하는 지붕선까지의 x,y 좌표의 차이 - - const diffX = Big(intersectLine.x).minus(startXPoint).round(1).abs().lt(1) ? Big(0) : Big(intersectLine.x).minus(startXPoint).round(1) - const diffY = Big(intersectLine.y).minus(startYPoint).round(1).abs().lt(1) ? Big(0) : Big(intersectLine.y).minus(startYPoint).round(1) - // 시작점에서 ridgeBaseLength 만큼 떨어진 지점까지 용마루 길이로 본다. - endXPoint = startXPoint.plus(Big(Math.sign(diffX.toNumber())).times(diffX.abs().minus(ridgeBaseLength))) - endYPoint = startYPoint.plus(Big(Math.sign(diffY.toNumber())).times(diffY.abs().minus(ridgeBaseLength))) - - // 시작점에서 종료점까지의 평면길이 - //startXPoint.minus(endXPoint).abs().pow(2).plus(startYPoint.minus(endYPoint).abs().pow(2)).sqrt() - const hypo = Big( - calcLinePlaneSize({ - x1: startXPoint.toNumber(), - y1: startYPoint.toNumber(), - x2: endXPoint.toNumber(), - y2: endYPoint.toNumber(), - }), - ).div(10) - // 현재 지붕선과 마주하는 지붕선을 잇는 선분의 교차점까지의 길이 - const intersectLength = Big( - calcLinePlaneSize({ - x1: midX.toNumber(), - y1: midY.toNumber(), - x2: intersectLine.x, - y2: intersectLine.y, - }), - ).div(10) - //마주하는 지붕선까지의 길이가 현재 지붕선의 이전, 다음 지붕선의 길이보다 작을때 - if (intersectLength.lt(Big(prevRoof.attributes.planeSize).div(10)) && intersectLength.lt(Big(nextRoof.attributes.planeSize).div(10))) { - endXPoint = startXPoint - endYPoint = startYPoint - } else { - if (ridgeMinLength.lt(hypo)) { - endXPoint = startXPoint.plus(Big(Math.sign(diffX.toNumber())).times(ridgeMinLength)) - endYPoint = startYPoint.plus(Big(Math.sign(diffY.toNumber())).times(ridgeMinLength)) - } - } - } else { - endXPoint = startXPoint.plus(Big(Math.sign(alpha.toNumber())).times(ridgeMinLength).neg()) - endYPoint = startYPoint.plus(Big(Math.sign(beta.toNumber())).times(ridgeMinLength).neg()) - } - - // 용마루 선을 그린다. - const ridge = new QLine([startXPoint.toNumber(), startYPoint.toNumber(), endXPoint.toNumber(), endYPoint.toNumber()], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.RIDGE, - textMode: textMode, - attributes: { - roofId: roof.id, - planeSize: calcLinePlaneSize({ - x1: startXPoint.toNumber(), - y1: startYPoint.toNumber(), - x2: endXPoint.toNumber(), - y2: endYPoint.toNumber(), - }), - actualSize: calcLinePlaneSize({ - x1: startXPoint.toNumber(), - y1: startYPoint.toNumber(), - x2: endXPoint.toNumber(), - y2: endYPoint.toNumber(), - }), - }, - }) - - // 용마루의 길이가 0보다 클때만 canvas 에 추가 한다. - if (ridge.attributes.planeSize > 0) { - canvas.add(ridge) - roof.ridges.push(ridge) - roof.innerLines.push(ridge) - - const distance = (x1, y1, x2, y2) => x2.minus(x1).pow(2).plus(y2.minus(y1).pow(2)).sqrt() - const dist1 = distance(startXPoint, startYPoint, Big(currentRoof.x1), Big(currentRoof.y1)) - const dist2 = distance(endXPoint, endYPoint, Big(currentRoof.x1), Big(currentRoof.y1)) - - currentRoof.attributes.ridgeCoordinate = { - x1: dist1 < dist2 ? startXPoint : endXPoint, - y1: dist1 < dist2 ? startYPoint : endYPoint, - } - } - } - }) - - //겹쳐지는 마루는 하나로 합침 - roof.ridges.forEach((ridge) => { - roof.ridges - .filter((ridge2) => !(ridge.x1 === ridge2.x1 && ridge.y1 === ridge2.y1 && ridge.x2 === ridge2.x2 && ridge.y2 === ridge2.y2)) - .forEach((ridge2) => { - let overlap = segmentsOverlap(ridge, ridge2) - if (overlap) { - let x1 = Math.min(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2) - let x2 = Math.max(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2) - let y1 = Math.min(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2) - let y2 = Math.max(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2) - //겹치는 용마루의 좌표를 합친다. - const newRidge = new QLine([x1, y1, x2, y2], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.RIDGE, - textMode: textMode, - attributes: { - roofId: roof.id, - planeSize: calcLinePlaneSize({ x1, y1, x2, y2 }), - actualSize: calcLinePlaneSize({ x1, y1, x2, y2 }), - }, - }) - //겹치는 용마루를 제거한다. - roof.canvas.remove(ridge) - roof.canvas.remove(ridge2) - - roof.ridges = roof.ridges.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) - roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) - roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) - roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) - canvas.add(newRidge) - roof.ridges.push(newRidge) - roof.innerLines.push(newRidge) - } - }) - }) - canvas?.renderAll() -} - -/** - * line 이 세 라인 사이에 존재하는지 확인한다. - * @param prevLine - * @param currentLine - * @param nextLine - * @param line - */ -const isInnerLine = (prevLine, currentLine, nextLine, line) => { - let inside = false - let minX = Math.min(currentLine.x1, currentLine.x2, prevLine.x1, nextLine.x2) - let maxX = Math.max(currentLine.x1, currentLine.x2, prevLine.x1, nextLine.x2) - let minY = Math.min(currentLine.y1, currentLine.y2, prevLine.y1, nextLine.y2) - let maxY = Math.max(currentLine.y1, currentLine.y2, prevLine.y1, nextLine.y2) - - if (minX < line.x1 && line.x1 < maxX && minY < line.y1 && line.y1 < maxY && minX < line.x2 && line.x2 < maxX && minY < line.y2 && line.y2 < maxY) { - inside = true - } - - return inside -} - /** * 두 선분이 겹치는지 확인 * @param line1 @@ -5881,446 +6063,6 @@ export const segmentsOverlap = (line1, line2) => { return false } -/** - * 추녀마루를 그린다. - * @param roof - * @param canvas - * @param textMode - */ -const drawHips = (roof, canvas, textMode) => { - const roofLines = roof.lines - const ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roof.id) - - //마루에서 시작되는 hip 을 먼저 그립니다. - roofLines - .filter((roof) => roof.attributes.type === LINE_TYPE.WALLLINE.EAVES && roof.attributes.ridgeCoordinate !== undefined) - .forEach((currentRoof, index) => { - const prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] - const nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1] - const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree - const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree - const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree - - //용마루 작성시 입력된 용마루 좌표가 있는 경우 처리 - const ridgeCoordinate = currentRoof.attributes.ridgeCoordinate - - const vectorX1 = Big(ridgeCoordinate.x1).minus(Big(currentRoof.x1)) - const vectorY1 = Big(ridgeCoordinate.y1).minus(Big(currentRoof.y1)) - //현재 지붕선의 좌표와 용마루 좌표의 각도를 구한다. - const angle1 = Big(Math.atan2(vectorY1.toNumber(), vectorX1.toNumber())).times(Big(180).div(Math.PI)) - - // 용마루 까지의 각도가 45도 인 경우 작성. - if (Big(angle1.abs().toNumber()).mod(45).eq(0)) { - const hip1 = new QLine([currentRoof.x1, currentRoof.y1, ridgeCoordinate.x1, ridgeCoordinate.y1], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: ridgeCoordinate.x1, - y2: ridgeCoordinate.y1, - }), - actualSize: - prevDegree === currentDegree - ? calcLineActualSize( - { - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: ridgeCoordinate.x1, - y2: ridgeCoordinate.y1, - }, - currentDegree, - ) - : 0, - }, - }) - canvas.add(hip1) - roof.hips.push(hip1) - roof.innerLines.push(hip1) - } - - const vectorX2 = Big(ridgeCoordinate.x1).minus(Big(currentRoof.x2)) - const vectorY2 = Big(ridgeCoordinate.y1).minus(Big(currentRoof.y2)) - const angle2 = Big(Math.atan2(vectorY2.toNumber(), vectorX2.toNumber())).times(Big(180).div(Math.PI)) - if (Big(angle2.abs().toNumber()).mod(45).eq(0)) { - const hip2 = new QLine([currentRoof.x2, currentRoof.y2, ridgeCoordinate.x1, ridgeCoordinate.y1], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ - x1: currentRoof.x2, - y1: currentRoof.y2, - x2: ridgeCoordinate.x1, - y2: ridgeCoordinate.y1, - }), - actualSize: - prevDegree === currentDegree - ? calcLineActualSize( - { - x1: currentRoof.x2, - y1: currentRoof.y2, - x2: ridgeCoordinate.x1, - y2: ridgeCoordinate.y1, - }, - currentDegree, - ) - : 0, - }, - }) - canvas.add(hip2) - roof.hips.push(hip2) - roof.innerLines.push(hip2) - } - }) - - const hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roof.id) - - //마루에서 시작되지 않는 hip 을 그립니다. - roofLines - .filter((roof) => { - let isHip = false - if (hipLines.some((hip) => hip.x1 === roof.x1 && hip.y1 === roof.y1)) { - isHip = true - } - return !isHip - }) - .forEach((currentRoof) => { - let prevRoof - roofLines.forEach((roof, index) => { - if (roof === currentRoof) { - prevRoof = index === 0 ? roofLines[roofLines.length - 1] : roofLines[index - 1] - } - }) - const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree - const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree - - let ridgePoints = [] - ridgeLines.forEach((ridge) => { - const deltaX1 = Big(ridge.x1).minus(Big(currentRoof.x1)) - const deltaY1 = Big(ridge.y1).minus(Big(currentRoof.y1)) - const deltaX2 = Big(ridge.x2).minus(Big(currentRoof.x1)) - const deltaY2 = Big(ridge.y2).minus(Big(currentRoof.y1)) - - if (deltaY1.div(deltaX1).abs().round(1).eq(1)) { - ridgePoints.push({ x: ridge.x1, y: ridge.y1 }) - } - if (deltaY2.div(deltaX2).abs().round(1).eq(1)) { - ridgePoints.push({ x: ridge.x2, y: ridge.y2 }) - } - }) - - ridgePoints = ridgePoints.reduce((prev, current) => { - if (prev !== undefined) { - // Math.abs(prev.x - currentRoof.x1) - const deltaPrevX = Big(prev.x).minus(Big(currentRoof.x1)).abs() - const deltaPrevY = Big(prev.y).minus(Big(currentRoof.y1)).abs() - const deltaCurrentX = Big(current.x).minus(Big(currentRoof.x1)).abs() - const deltaCurrentY = Big(current.y).minus(Big(currentRoof.y1)).abs() - if (deltaPrevX.lt(deltaCurrentX) && deltaPrevY.lt(deltaCurrentY)) { - return prev - } else { - return current - } - } else { - return current - } - }, undefined) - - if (ridgePoints !== undefined) { - const hip = new QLine([currentRoof.x1, currentRoof.y1, ridgePoints.x, ridgePoints.y], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: ridgePoints.x, - y2: ridgePoints.y, - }), - actualSize: - prevDegree === currentDegree - ? calcLineActualSize( - { - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: ridgePoints.x, - y2: ridgePoints.y, - }, - currentDegree, - ) - : 0, - }, - }) - canvas.add(hip) - roof.hips.push(hip) - roof.innerLines.push(hip) - } - }) - canvas?.renderAll() -} - -/** - * 3개 이상 이어지지 않은 라인 포인트 계산 - * 모임지붕에서 point 는 3개 이상의 라인과 접해야 함. - * @param polygon - * @param canvas - * @param textMode - */ -const connectLinePoint = (polygon, canvas, textMode) => { - // 연결되지 않은 모든 라인의 포인트를 구한다. - let missedPoints = [] - - const lineDegrees = [ - ...new Set(polygon.lines.map((line) => (line.attributes.pitch > 0 ? getDegreeByChon(line.attributes.pitch) : line.attributes.degree))), - ] - - //마루 - polygon.ridges.forEach((ridge) => { - if (ridge.x1 === ridge.x2) { - if ( - polygon.lines - .filter((roof) => roof.y1 === roof.y2) - .filter((roof) => roof.y1 === ridge.y1 || roof.y1 === ridge.y2 || roof.y2 === ridge.y1 || roof.y2 === ridge.y2).length > 0 - ) { - return - } - } - if (ridge.y1 === ridge.y2) { - if ( - polygon.lines - .filter((roof) => roof.x1 === roof.x2) - .filter((roof) => roof.x1 === ridge.x1 || roof.x1 === ridge.x2 || roof.x2 === ridge.x1 || roof.x2 === ridge.x2).length > 0 - ) { - return - } - } - if (polygon.hips.filter((hip) => hip.x2 === ridge.x1 && hip.y2 === ridge.y1).length < 2) { - missedPoints.push({ x: ridge.x1, y: ridge.y1 }) - } - if (polygon.hips.filter((hip) => hip.x2 === ridge.x2 && hip.y2 === ridge.y2).length < 2) { - missedPoints.push({ x: ridge.x2, y: ridge.y2 }) - } - }) - - //추녀마루 - polygon.hips.forEach((hip) => { - let count = 0 - count += polygon.ridges.filter((ridge) => (ridge.x1 === hip.x2 && ridge.y1 === hip.y2) || (ridge.x2 === hip.x2 && ridge.y2 === hip.y2)).length - - count += polygon.hips.filter((hip2) => (hip2.x1 === hip.x2 && hip2.y1 === hip.y2) || (hip2.x2 === hip.x2 && hip2.y2 === hip.y2)).length - if (count < 3) { - missedPoints.push({ x: hip.x2, y: hip.y2 }) - } - }) - - let missedLine = [] - - //중복포인트제거 - missedPoints = [...new Set(missedPoints.map((line) => JSON.stringify(line)))].map((line) => JSON.parse(line)) - - missedPoints.forEach((p1) => { - let p2 = missedPoints - .filter((p) => p.x !== p1.x && p.y !== p1.y) - .reduce((prev, current) => { - if (prev !== undefined) { - return Math.sqrt(Math.pow(Math.abs(current.x - p1.x), 2) + Math.pow(Math.abs(current.y - p1.y), 2)) < - Math.sqrt(Math.pow(Math.abs(prev.x - p1.x), 2) + Math.pow(Math.abs(prev.y - p1.y), 2)) - ? current - : prev - } else { - return current - } - }, undefined) - if (p2 !== undefined) { - if (p1.x < p2.x && p1.y < p2.y) { - missedLine.push({ x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y }) - } - if (p1.x > p2.x && p1.y < p2.y) { - missedLine.push({ x1: p2.x, y1: p2.y, x2: p1.x, y2: p1.y }) - } - if (p1.x > p2.x && p1.y > p2.y) { - missedLine.push({ x1: p2.x, y1: p2.y, x2: p1.x, y2: p1.y }) - } - if (p1.x < p2.x && p1.y > p2.y) { - missedLine.push({ x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y }) - } - } - }) - - //중복라인제거 - missedLine = [...new Set(missedLine.map((line) => JSON.stringify(line)))].map((line) => JSON.parse(line)) - - missedLine.forEach((p) => { - const line = new QLine([p.x1, p.y1, p.x2, p.y2], { - parentId: polygon.id, - attributes: { - roofId: polygon.id, - planeSize: calcLinePlaneSize(p), - actualSize: lineDegrees.length === 0 ? 0 : calcLineActualSize(p, lineDegrees[0]), - }, - fontSize: polygon.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - textMode: textMode, - }) - polygon.canvas.add(line) - polygon.innerLines.push(line) - }) - - missedPoints = [] - missedLine = [] - - polygon.innerLines.forEach((line) => { - if ( - polygon.innerLines.filter( - (innerLine) => (line.x2 === innerLine.x1 && line.y2 === innerLine.y1) || (line.x2 === innerLine.x2 && line.y2 === innerLine.y2), - ).length < 3 - ) { - missedPoints.push({ x: line.x2, y: line.y2 }) - } - }) - - missedPoints = [...new Set(missedPoints.map((line) => JSON.stringify(line)))].map((line) => JSON.parse(line)) - - missedPoints.forEach((p1) => { - let p2 = missedPoints - .filter((p) => !(p.x === p1.x && p.y === p1.y)) - .reduce((prev, current) => { - if (prev !== undefined) { - return Math.abs(current.x - p1.x) + Math.abs(current.y - p1.y) < Math.abs(prev.x - p1.x) + Math.abs(prev.y - p1.y) ? current : prev - } else { - return current - } - }, undefined) - - if (p2 !== undefined) { - if (p1.x === p2.x && p1.y < p2.y) { - missedLine.push({ x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y }) - } - if (p1.x === p2.x && p1.y > p2.y) { - missedLine.push({ x1: p1.x, y1: p2.y, x2: p2.x, y2: p1.y }) - } - if (p1.x < p2.x && p1.y === p2.y) { - missedLine.push({ x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y }) - } - if (p1.x > p2.x && p1.y === p2.y) { - missedLine.push({ x1: p2.x, y1: p1.y, x2: p1.x, y2: p2.y }) - } - } - }) - - //중복라인제거 - missedLine = [...new Set(missedLine.map((line) => JSON.stringify(line)))].map((line) => JSON.parse(line)) - - missedLine.forEach((p) => { - const line = new QLine([p.x1, p.y1, p.x2, p.y2], { - attributes: { - roofId: polygon.id, - planeSize: calcLinePlaneSize(p), - actualSize: lineDegrees.length === 0 ? 0 : calcLineActualSize(p, lineDegrees[0]), - }, - fontSize: polygon.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - textMode: textMode, - }) - line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) - line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) - polygon.canvas.add(line) - polygon.innerLines.push(line) - }) - - //마지막으로 연결되지 않고 떨어져있는 마루를 확인한다. - let missedRidge = [] - polygon.ridges.forEach((ridge) => { - let lineCheck1 = polygon.innerLines.filter((line) => { - if ( - !(line.x1 === ridge.x1 && line.y1 === ridge.y1 && line.x2 === ridge.x2 && line.y2 === ridge.y2) && - ((line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1)) - ) { - return line - } - }) - - let lineCheck2 = polygon.innerLines.filter((line) => { - if ( - !(line.x1 === ridge.x1 && line.y1 === ridge.y1 && line.x2 === ridge.x2 && line.y2 === ridge.y2) && - ((line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2)) - ) { - return line - } - }) - if (lineCheck1.length === 0 || lineCheck2.length === 0) { - missedRidge.push(ridge) - } - }) - - missedRidge.forEach((ridge) => { - let missedRidge2 = missedRidge.filter( - (ridge2) => !(ridge.x1 === ridge2.x1 && ridge.y1 === ridge2.y1 && ridge.x2 === ridge2.x2 && ridge.y2 === ridge2.y2), - ) - - missedRidge2.forEach((ridge2) => { - let overlap = false - if (ridge.x1 === ridge.x2 && ridge2.x1 === ridge2.x2 && ridge2.x1 === ridge.x1) { - overlap = true - } - if (ridge.y1 === ridge.y2 && ridge2.y1 === ridge2.y2 && ridge2.y1 === ridge.y1) { - overlap = true - } - if (overlap) { - let x1 = Math.min(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2) - let x2 = Math.max(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2) - let y1 = Math.min(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2) - let y2 = Math.max(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2) - const newRidge = new QLine([x1, y1, x2, y2], { - fontSize: polygon.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.RIDGE, - textMode: textMode, - attributes: { - roofId: polygon.id, - planeSize: calcLinePlaneSize(ridge), - actualSize: lineDegrees.length > 0 ? 0 : calcLineActualSize(ridge, lineDegrees[0]), - }, - }) - if (polygon.ridges.filter((r) => newRidge.x1 === r.x1 && newRidge.y1 === r.y1 && newRidge.x2 === r.x2 && newRidge.y2 === r.y2).length === 0) { - polygon.canvas.remove(ridge) - polygon.canvas.remove(ridge2) - polygon.ridges = polygon.ridges.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) - polygon.ridges = polygon.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) - polygon.innerLines = polygon.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) - polygon.innerLines = polygon.innerLines.filter( - (r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2), - ) - - polygon.canvas.add(newRidge) - polygon.ridges.push(newRidge) - polygon.innerLines.push(newRidge) - } - } - }) - }) - polygon.canvas.renderAll() -} - /** * 외벽선 속성에 따라서 모양을 수정한다. * @param roof @@ -6816,7 +6558,15 @@ const changeGableRoof = (currentRoof, canvas, textMode) => { x2: midX.toNumber(), y2: midY.toNumber(), }), - actualSize: calcLineActualSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.toNumber(), y2: midY.toNumber() }, nextDegree), + actualSize: calcLineActualSize( + { + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: midX.toNumber(), + y2: midY.toNumber(), + }, + nextDegree, + ), }, }) canvas?.add(hip2) @@ -7761,7 +7511,15 @@ const changeWallRoof = (currentRoof, canvas, textMode) => { x2: wallMidX.toNumber(), y2: wallMidY.toNumber(), }), - actualSize: calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }, prevDegree), + actualSize: calcLineActualSize( + { + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: wallMidX.toNumber(), + y2: wallMidY.toNumber(), + }, + prevDegree, + ), }, }) // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 @@ -7784,7 +7542,15 @@ const changeWallRoof = (currentRoof, canvas, textMode) => { x2: wallMidX.toNumber(), y2: wallMidY.toNumber(), }), - actualSize: calcLineActualSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }, nextDegree), + actualSize: calcLineActualSize( + { + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: wallMidX.toNumber(), + y2: wallMidY.toNumber(), + }, + nextDegree, + ), }, }) // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 @@ -7915,9 +7681,6 @@ const reDrawPolygon = (polygon, canvas) => { line.attributes = l.attributes } }) - // const lineLength = Math.sqrt( - // Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), - // ) const lineLength = calcLinePlaneSize({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }) if (line.attributes !== undefined) { line.attributes.planeSize = lineLength