From bf8986b509f83a216fff118984509e290c04f14a Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 14:38:05 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=8B=9C=20=EA=B8=B8=EC=9D=B4,=20innerlines=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 212 +++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 114 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e9d12a9b..16a73098 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1807,6 +1807,9 @@ const drawRidge = (roof, canvas) => { attributes: { roofId: roof.id }, }, ) + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + canvas.add(ridge) roof.ridges.push(ridge) roof.innerLines.push(ridge) @@ -1847,6 +1850,8 @@ const drawRidge = (roof, canvas) => { 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)) + newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 canvas.add(newRidge) roof.ridges.push(newRidge) roof.innerLines.push(newRidge) @@ -1922,7 +1927,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoof: currentRoof.id }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip1) const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 @@ -1939,10 +1944,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoof: currentRoof.id, - }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip2) const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 @@ -2013,12 +2015,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, - }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip) const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10 @@ -2076,92 +2073,6 @@ const checkValley = (polygon, line1, line2) => { return isValley } -const getPointInPolygon = (polygon, point, isInclude = false) => { - let inside = false - let minX = Math.min(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x), - maxX = Math.max(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x), - minY = Math.min(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y), - maxY = Math.max(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y) - if (!isInclude && minX < point.x && point.x < maxX && minY < point.y && point.y < maxY) { - inside = true - } - if (isInclude && minX <= point.x && point.x <= maxX && minY <= point.y && point.y <= maxY) { - inside = true - } - return inside -} - -/** - * 라인과 마주하는 다른 라인과의 가장 가까운 거리를 구한다. - * @param polygon - * @param currentLine 현재 라인 - * @param dVector 현재 라인의 방향 - * @returns {*[]|null} - */ -const getAcrossLine = (polygon, currentLine, dVector) => { - let acrossLine - switch (dVector) { - case 45: - acrossLine = polygon.lines - .filter((line) => line.x1 > currentLine.x1 && line.y1 <= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 135: - acrossLine = polygon.lines - .filter((line) => line.x1 > currentLine.x1 && line.y1 >= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 225: - acrossLine = polygon.lines - .filter((line) => line.x1 < currentLine.x1 && line.y1 >= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 315: - acrossLine = polygon.lines - .filter((line) => line.x1 < currentLine.x1 && line.y1 <= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - } - return acrossLine -} - -/* - 추녀마루(hip) 중복방지를 위해 마루와 함께 그려진 추녀마루를 확인한다 - */ -const isAlreadyHip = (polygon, line) => { - let isAlreadyHip = false - polygon.hips.forEach((hip) => { - if (line.x1 === hip.x1 && line.y1 === hip.y1) { - isAlreadyHip = true - } - }) - return isAlreadyHip -} - /* 3개 이상 이어지지 않은 라인 포인트 계산 모임지붕에서 point는 3개 이상의 라인과 접해야 함. @@ -2252,6 +2163,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2308,6 +2221,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2612,6 +2527,8 @@ const changeEavesRoof = (currentRoof, canvas) => { hipX2 = midX - addHipX2 hipY2 = midY - addHipY2 } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } hipLines.forEach((hip) => { @@ -2789,6 +2706,8 @@ const changeGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], { fontSize: roof.fontSize, @@ -2850,6 +2769,14 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { if (wallLine.length > 0) { wallLine = wallLine[0] } + let prevRoof, nextRoof + roof.lines.forEach((r, index) => { + if (r.id === currentRoof.id) { + currentRoof = r + prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] + nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1] + } + }) const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 @@ -2963,6 +2890,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], { @@ -2973,10 +2902,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, }, }) + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) roof.innerLines.push(hip1) @@ -2992,6 +2926,10 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { actualSize: currentRoof.length, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) @@ -3010,7 +2948,7 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) }) - hipLines.forEach((hip) => { + hipLines.forEach((hip, i) => { const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], { fontSize: roof.fontSize, stroke: 'red', @@ -3019,10 +2957,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gableDegree = i === 0 ? prevDegree : nextDegree + const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10 + const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gableLine.attributes.planeSize = + Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10 + gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2))) canvas?.add(gableLine) roof.innerLines.push(gableLine) }) @@ -3052,6 +2995,18 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { wallLine = wallLine[0] } + let prevRoof, nextRoof + roof.lines.forEach((r, index) => { + if (r.id === currentRoof.id) { + currentRoof = r + prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] + 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 nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심 @@ -3173,6 +3128,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { hipX2 = midX - xWidth hipY2 = midY - yWidth } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2 @@ -3186,10 +3143,14 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch) + const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10 + const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10 + gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2))) canvas?.add(gable1) roof.innerLines.push(gable1) @@ -3204,10 +3165,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10 + const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10 + gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2))) canvas?.add(gable2) roof.innerLines.push(gable2) @@ -3219,10 +3183,11 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 + gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 canvas?.add(gable3) roof.innerLines.push(gable3) @@ -3234,10 +3199,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) roof.innerLines.push(hip1) @@ -3249,10 +3217,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) } @@ -3348,6 +3319,9 @@ const changeWallRoof = (currentRoof, canvas) => { canvas?.remove(line) }) + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + if (currentRoof.attributes.sleeve && currentRoof.attributes.width > 0 && prevRoof.attributes.offset > 0 && nextRoof.attributes.offset > 0) { const prevSignX = Math.sign(prevRoof.x1 - prevRoof.x2) const prevSignY = Math.sign(prevRoof.y1 - prevRoof.y2) @@ -3453,6 +3427,8 @@ const changeWallRoof = (currentRoof, canvas) => { y2: ridge.y2 - diffY, }) } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], { fontSize: roof.fontSize, @@ -3462,10 +3438,14 @@ const changeWallRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX, wallMidY], { fontSize: roof.fontSize, stroke: 'red', @@ -3478,6 +3458,10 @@ const changeWallRoof = (currentRoof, canvas) => { actualSize: currentRoof.length, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip1) canvas?.add(hip2) roof.innerLines.push(hip1)