From d7bdfa489266613eb6003bd21eca9d4bca3f5d37 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 21 Nov 2024 18:28:39 +0900 Subject: [PATCH] =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BFA,B=20=EC=A4=91?= =?UTF-8?q?=EA=B0=84=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 35 +-- src/components/fabric/QPolygon.js | 13 +- src/hooks/useMode.js | 55 +---- src/util/qpolygon-utils.js | 361 ++++++++++++++++++++++++++++++ 4 files changed, 397 insertions(+), 67 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 721e3543..648c8bf3 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from 'react' import { v4 as uuidv4 } from 'uuid' import { useMode } from '@/hooks/useMode' import { LINE_TYPE, Mode } from '@/common/common' -import { Button, Input } from '@nextui-org/react' +import { Button } from '@nextui-org/react' import RangeSlider from './ui/RangeSlider' import { useRecoilState, useRecoilValue } from 'recoil' import { @@ -410,10 +410,10 @@ export default function Roof2(props) { ] const rectangleType1 = [ - { x: 100, y: 100 }, - { x: 100, y: 600 }, - { x: 300, y: 600 }, - { x: 300, y: 100 }, + { x: 500, y: 100 }, + { x: 500, y: 800 }, + { x: 900, y: 800 }, + { x: 900, y: 100 }, ] const rectangleType2 = [ @@ -460,6 +460,15 @@ export default function Roof2(props) { { x: 200, y: 100 }, ] + const test4 = [ + { x: 100, y: 100 }, + { x: 100, y: 1000 }, + { x: 1100, y: 1000 }, + { x: 1100, y: 550 }, + { x: 500, y: 550 }, + { x: 500, y: 100 }, + ] + const polygon = new QPolygon(eightPoint4, { fill: 'transparent', stroke: 'green', @@ -1021,7 +1030,7 @@ export default function Roof2(props) { )} -
+ {/*

각도 입력(0~360) 후 방향설정 클릭

방향 설정 -
-
- {/* Compass Circle */} +
*/} + {/*
+ Compass Circle
- {/* N, S, E, W Labels */} + N, S, E, W Labels
N
S
@@ -1057,9 +1066,9 @@ export default function Roof2(props) {
- {/* Compass Pointer */} + Compass Pointer
- {/* Red Upper Triangle */} + Red Upper Triangle
-
+
*/}
{!canvas ? null : mode === Mode.DRAW_LINE ? ( diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index c5a08cf1..808f6765 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -1,15 +1,8 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' import { QLine } from '@/components/fabric/QLine' -import { - distanceBetweenPoints, - findTopTwoIndexesByDistance, - getAllRelatedObjects, - getDirectionByPoint, - sortedPointLessEightPoint, - sortedPoints, -} from '@/util/canvas-util' -import { calculateAngle, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' +import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' +import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' @@ -217,7 +210,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { (gableOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableEven.every((type) => gableType.includes(type))) || (gableEven.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableOdd.every((type) => gableType.includes(type))) ) { - console.log('박공 지붕') + drawGabledRoof(this.id, this.canvas) } else if (hasShed) { const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) const areLinesParallel = function (line1, line2) { diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 2ab7de9f..e97621f1 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1508,55 +1508,14 @@ export function useMode() { const handleOuterlinesTest2 = (polygon, offset = 50) => { // TODO [ljyoung] : offset 입력 처리 후 제거 해야함. polygon.lines.forEach((line, index) => { - line.attributes = { + /*line.attributes = { type: LINE_TYPE.WALLLINE.EAVES, offset: 50, width: 50, pitch: 4, sleeve: true, - } - /*if (index === 1) { - line.attributes = { - type: LINE_TYPE.WALLLINE.SHED, - offset: 30, //출폭 - width: 30, //폭 - pitch: 4, //구배 - sleeve: true, //소매 - } - } else if (index === 5 || index === 3) { - line.attributes = { - type: LINE_TYPE.WALLLINE.EAVES, - offset: 50, //출폭 - width: 30, //폭 - pitch: 4, //구배 - sleeve: true, //소매 - } - } else { - line.attributes = { - type: LINE_TYPE.WALLLINE.GABLE, - offset: 20, - width: 50, - pitch: 4, - sleeve: true, - } }*/ - /* if (index === 1) { - line.attributes = { - type: LINE_TYPE.WALLLINE.SHED, - offset: 20, //출폭 - width: 30, //폭 - pitch: 4, //구배 - sleeve: true, //소매 - } - } else if (index === 3) { - line.attributes = { - type: LINE_TYPE.WALLLINE.EAVES, - offset: 50, //출폭 - width: 30, //폭 - pitch: 4, //구배 - sleeve: true, //소매 - } - } else { + if (index % 2 !== 0) { line.attributes = { type: LINE_TYPE.WALLLINE.GABLE, offset: 30, @@ -1564,7 +1523,15 @@ export function useMode() { pitch: 4, sleeve: true, } - }*/ + } else { + line.attributes = { + type: LINE_TYPE.WALLLINE.EAVES, + offset: 50, + width: 50, + pitch: 4, + sleeve: true, + } + } }) const roof = drawRoofPolygon(polygon) //지붕 그리기 diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 3ed8f9a1..d7385305 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1232,6 +1232,367 @@ function calculateAngleBetweenLines(line1, line2) { return (angleInRadians * 180) / Math.PI } +/** + * 박공지붕(templateA, templateB)을 그린다. + * @param roofId + * @param canvas + */ +export const drawGabledRoof = (roofId, canvas) => { + const roof = canvas?.getObjects().find((object) => object.id === roofId) + const roofLines = roof.lines + const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines + const hasNonParallelLines = roofLines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) + if (hasNonParallelLines.length > 0) { + alert('대각선이 존재합니다.') + return + } + + const roofPoints = roof.points + const minX = Math.min(...roofPoints.map((point) => point.x)) + const maxX = Math.max(...roofPoints.map((point) => point.x)) + const minY = Math.min(...roofPoints.map((point) => point.y)) + const maxY = Math.max(...roofPoints.map((point) => point.y)) + + const checkLength = Math.abs(Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2))) + + wallLines + .filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE) + .forEach((gable) => { + const gableLine = new QLine([gable.x1, gable.y1, gable.x2, gable.y2], { + fontSize: roof.fontSize, + stroke: 'cyan', + strokeWidth: 2, + }) + canvas.add(gableLine) + canvas.renderAll() + }) + + const eaves = [] + roofLines.forEach((currentRoof, index) => { + if (currentRoof.attributes !== undefined && currentRoof.attributes.type === LINE_TYPE.WALLLINE.EAVES) { + eaves.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize }) + } + }) + const ridgeCount = eaves.length - 1 + const ridges = [] + eaves.sort((a, b) => a.length - b.length) + + eaves.forEach((eave, index) => { + if (ridges.length < ridgeCount) { + const index = eave.index, + currentRoof = eave.roof + const currentWall = wallLines[index] + 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] + + const midX = Math.round(((currentRoof.x1 + currentRoof.x2) / 2) * 10) / 10 + const midY = Math.round(((currentRoof.y1 + currentRoof.y2) / 2) * 10) / 10 + const deltaX = currentWall.x2 - currentWall.x1 + const deltaY = currentWall.y2 - currentWall.y1 + const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY) + // currentWall과 직각인 기울기 계산 + const perpendicularDeltaX = deltaY / length + const perpendicularDeltaY = -deltaX / length + // midX와 midY를 기준으로 직각 기울기를 사용하여 midWallX와 midWallY 계산 + const midWallX = midX + perpendicularDeltaX * length + const midWallY = midY + perpendicularDeltaY * length + + const signX = Math.sign(midX - midWallX) + const signY = Math.sign(midY - midWallY) + const checkX = Math.round((midX - signX * checkLength) * 10) / 10 + const checkY = Math.round((midY - signY * checkLength) * 10) / 10 + + const intersectLines = [] + roofLines + .filter((line) => line !== currentRoof) + .forEach((line) => { + const intersect = edgesIntersection( + { vertex1: { x: midX, y: midY }, vertex2: { x: checkX, y: checkY } }, + { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, + ) + if (intersect && !intersect.isIntersectionOutside) { + intersectLines.push({ x: intersect.x, y: intersect.y, line: line }) + } + }) + + const intersect = intersectLines.reduce((prev, current) => { + if (prev !== undefined) { + const prevDistance = Math.sqrt(Math.pow(prev.x - midX, 2) + Math.pow(prev.y - midY, 2)) + const currentDistance = Math.sqrt(Math.pow(current.x - midX, 2) + Math.pow(current.y - midY, 2)) + return prevDistance >= currentDistance ? current : prev + } else { + return current + } + }, undefined) + + const linesCenterX = Math.round(((midX + intersect.x) / 2) * 10) / 10 + const linesCenterY = Math.round(((midY + intersect.y) / 2) * 10) / 10 + + let addLength = currentRoof.attributes.planeSize / 2 / 10 + + let centerLineX1 = Math.sign(currentRoof.x1 - currentRoof.x2) * addLength + linesCenterX + let centerLineY1 = Math.sign(currentRoof.y1 - currentRoof.y2) * addLength + linesCenterY + let centerLineX2 = Math.sign(currentRoof.x2 - currentRoof.x1) * addLength + linesCenterX + let centerLineY2 = Math.sign(currentRoof.y2 - currentRoof.y1) * addLength + linesCenterY + + const point1Intersect = [] + const point2Intersect = [] + roofLines.forEach((line) => { + const point1 = edgesIntersection( + { vertex1: { x: linesCenterX, y: linesCenterY }, vertex2: { x: centerLineX1, y: centerLineY1 } }, + { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, + ) + if (point1 && !point1.isIntersectionOutside) { + point1Intersect.push({ x: point1.x, y: point1.y }) + } + const point2 = edgesIntersection( + { vertex1: { x: linesCenterX, y: linesCenterY }, vertex2: { x: centerLineX2, y: centerLineY2 } }, + { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, + ) + if (point2 && !point2.isIntersectionOutside) { + point2Intersect.push({ x: point2.x, y: point2.y }) + } + }) + point1Intersect.reduce((prev, current) => { + if (prev !== undefined) { + const prevDistance = Math.sqrt(Math.pow(prev.x - linesCenterX, 2) + Math.pow(prev.y - linesCenterY, 2)) + const currentDistance = Math.sqrt(Math.pow(current.x - linesCenterX, 2) + Math.pow(current.y - linesCenterY, 2)) + return prevDistance >= currentDistance ? current : prev + } else { + return current + } + }, undefined) + point2Intersect.reduce((prev, current) => { + if (prev !== undefined) { + const prevDistance = Math.sqrt(Math.pow(prev.x - linesCenterX, 2) + Math.pow(prev.y - linesCenterY, 2)) + const currentDistance = Math.sqrt(Math.pow(current.x - linesCenterX, 2) + Math.pow(current.y - linesCenterY, 2)) + return prevDistance >= currentDistance ? current : prev + } else { + return current + } + }, undefined) + + if (point1Intersect.length > 0) { + centerLineX1 = point1Intersect[0].x + centerLineY1 = point1Intersect[0].y + } + if (point2Intersect.length > 0) { + centerLineX2 = point2Intersect[0].x + centerLineY2 = point2Intersect[0].y + } + + const ridge = new QLine([centerLineX1, centerLineY1, centerLineX2, centerLineY2], { + fontSize: roof.fontSize, + stroke: 'blue', + strokeWidth: 1, + name: LINE_TYPE.SUBLINE.RIDGE, + attributes: { roofId: roof.id, currentRoof: currentRoof.id }, + }) + canvas.add(ridge) + canvas.renderAll() + ridges.push(ridge) + } + }) + eaves.forEach((eave) => { + const index = eave.index, + currentRoof = eave.roof + const currentWall = wallLines[index] + 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] + + /*const midX = Math.round(((currentRoof.x1 + currentRoof.x2) / 2) * 10) / 10 + const midY = Math.round(((currentRoof.y1 + currentRoof.y2) / 2) * 10) / 10 + const midWallX = Math.round(((currentWall.x1 + currentWall.x2) / 2) * 10) / 10 + const midWallY = Math.round(((currentWall.y1 + currentWall.y2) / 2) * 10) / 10 + const signX = Math.sign(midX - midWallX) + const signY = Math.sign(midY - midWallY) +*/ + const midX = Math.round(((currentRoof.x1 + currentRoof.x2) / 2) * 10) / 10 + const midY = Math.round(((currentRoof.y1 + currentRoof.y2) / 2) * 10) / 10 + const deltaX = currentWall.x2 - currentWall.x1 + const deltaY = currentWall.y2 - currentWall.y1 + const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY) + // currentWall과 직각인 기울기 계산 + const perpendicularDeltaX = deltaY / length + const perpendicularDeltaY = -deltaX / length + // midX와 midY를 기준으로 직각 기울기를 사용하여 midWallX와 midWallY 계산 + const midWallX = midX + perpendicularDeltaX * length + const midWallY = midY + perpendicularDeltaY * length + const signX = Math.sign(midX - midWallX) + const signY = Math.sign(midY - midWallY) + + let points = [] + const intersectRidge = [] + // 현재 roof가 wall보다 작을때 이전, 다음 지붕의 offset만큼 포인트를 조정한다. + if (currentRoof.attributes.planeSize >= currentWall.attributes.planeSize) { + points.push({ x: currentRoof.x1, y: currentRoof.y1 }, { x: currentRoof.x2, y: currentRoof.y2 }) + } else { + const deltaX = currentRoof.x2 - currentRoof.x1 + const deltaY = currentRoof.y2 - currentRoof.y1 + points.push( + { x: currentRoof.x1 - Math.sign(deltaX) * prevRoof.attributes.offset, y: currentRoof.y1 - Math.sign(deltaY) * prevRoof.attributes.offset }, + { x: currentRoof.x2 + Math.sign(deltaX) * nextRoof.attributes.offset, y: currentRoof.y2 + Math.sign(deltaY) * nextRoof.attributes.offset }, + ) + } + ridges.forEach((ridge) => { + const ridgeMidX = (ridge.x1 + ridge.x2) / 2 + const ridgeMidY = (ridge.y1 + ridge.y2) / 2 + if (midX === ridgeMidX || midY === ridgeMidY) { + const intersection = edgesIntersection( + { vertex1: { x: midX, y: midY }, vertex2: { x: ridgeMidX, y: ridgeMidY } }, + { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }, + ) + if (intersection && !intersection.isIntersectionOutside) { + intersectRidge.push({ line: ridge, name: 'mid' }) + } + } + console.log('signX : ', signX, 'signY : ', signY) + if (Math.sign(midX - ridgeMidX) === signX || Math.sign(midY - ridgeMidY) === signY) { + const prevIntersect = edgesIntersection( + { vertex1: { x: prevRoof.x1, y: prevRoof.y1 }, vertex2: { x: prevRoof.x2, y: prevRoof.y2 } }, + { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }, + ) + const nextIntersect = edgesIntersection( + { vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, vertex2: { x: nextRoof.x2, y: nextRoof.y2 } }, + { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }, + ) + if (prevIntersect && !prevIntersect.isIntersectionOutside) { + intersectRidge.push({ line: ridge, name: 'prev' }) + } + if (nextIntersect && !nextIntersect.isIntersectionOutside) { + intersectRidge.push({ line: ridge, name: 'next' }) + } + } + }) + + intersectRidge.forEach((intersect) => { + const line = intersect.line + if (currentRoof.attributes.planeSize >= currentWall.attributes.planeSize) { + points.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 }) + } else { + if (intersect.name === 'mid') { + let lineX1 = line.x1, + lineY1 = line.y1, + lineX2 = line.x2, + lineY2 = line.y2 + const prevCheck1 = Math.sqrt(Math.pow(Math.round(lineX1 - currentRoof.x1), 2) + Math.pow(Math.round(lineY1 - currentRoof.y1), 2)) + const prevCheck2 = Math.sqrt(Math.pow(Math.round(lineX2 - currentRoof.x1), 2) + Math.pow(Math.round(lineY2 - currentRoof.y1), 2)) + const deltaX = currentRoof.x2 - currentRoof.x1 + const deltaY = currentRoof.y2 - currentRoof.y1 + console.log('deltaX : ', deltaX, 'deltaY : ', deltaY) + if (prevCheck1 < prevCheck2) { + lineX1 = lineX1 - Math.sign(deltaX) * prevRoof.attributes.offset + lineY1 = lineY1 - Math.sign(deltaY) * prevRoof.attributes.offset + lineX2 = lineX2 + Math.sign(deltaX) * nextRoof.attributes.offset + lineY2 = lineY2 + Math.sign(deltaY) * nextRoof.attributes.offset + } else { + lineX1 = lineX1 + Math.sign(deltaX) * prevRoof.attributes.offset + lineY1 = lineY1 + Math.sign(deltaY) * prevRoof.attributes.offset + lineX2 = lineX2 - Math.sign(deltaX) * nextRoof.attributes.offset + lineY2 = lineY2 - Math.sign(deltaY) * nextRoof.attributes.offset + } + points.push({ x: lineX1, y: lineY1 }, { x: lineX2, y: lineY2 }) + } + } + }) + points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y)) + + const startPoint = points + .filter((point) => point.x === Math.min(...points.map((point) => point.x))) + .reduce((prev, current) => { + return prev.y < current.y ? prev : current + }) + const sortedPoints = [startPoint] + points.forEach((p, index) => { + const lastPoint = sortedPoints[sortedPoints.length - 1] + if (index === 0) { + const underStartPoint = points.filter((point) => point.y > startPoint.y) + const nextPoint = underStartPoint + .filter((point) => point.x === startPoint.x) + .reduce((prev, current) => { + return Math.abs(prev.y - startPoint.y) < Math.abs(current.y - startPoint.y) ? prev : current + }) + if (nextPoint) { + sortedPoints.push(nextPoint) + } else { + const nextPoint = underStartPoint.reduce((prev, current) => { + const prevHypos = Math.sqrt(Math.abs(Math.pow(prev.x - startPoint.x, 2)) + Math.abs(Math.pow(prev.y - startPoint.y, 2))) + const currentHypos = Math.sqrt(Math.abs(Math.pow(current.x - startPoint.x, 2)) + Math.abs(Math.pow(current.y - startPoint.y, 2))) + return prevHypos < currentHypos ? prev : current + }) + sortedPoints.push(nextPoint) + } + } else { + const prevPoint = sortedPoints[sortedPoints.length - 2] + const otherPoints = points.filter((point) => sortedPoints.includes(point) === false) + const nextPoint = otherPoints.reduce((prev, current) => { + if (prev === undefined) { + const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2)))) + const adjacent = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2)))) + const hypotenuse = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2)))) + + const angle = Math.round( + Math.acos((Math.pow(adjacent, 2) + Math.pow(height, 2) - Math.pow(hypotenuse, 2)) / (2 * adjacent * height)) * (180 / Math.PI), + ) + if (angle === 90) { + return current + } + } else { + return prev + } + }, undefined) + if (nextPoint) { + sortedPoints.push(nextPoint) + } else { + const nextPoint = otherPoints.reduce((prev, current) => { + if (prev !== undefined) { + const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2)))) + const adjacentC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2)))) + const hypotenuseC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2)))) + + const angleC = Math.round( + Math.acos((Math.pow(adjacentC, 2) + Math.pow(height, 2) - Math.pow(hypotenuseC, 2)) / (2 * adjacentC * height)) * (180 / Math.PI), + ) + + const adjacentP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - lastPoint.x, 2)) + Math.abs(Math.pow(prev.y - lastPoint.y, 2)))) + const hypotenuseP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - prevPoint.x, 2)) + Math.abs(Math.pow(prev.y - prevPoint.y, 2)))) + + const angleP = Math.round( + Math.acos((Math.pow(adjacentP, 2) + Math.pow(height, 2) - Math.pow(hypotenuseP, 2)) / (2 * adjacentP * height)) * (180 / Math.PI), + ) + + if (Math.abs(90 - angleC) < Math.abs(90 - angleP)) { + return current + } else { + return prev + } + } else { + return current + } + }, undefined) + if (nextPoint) { + sortedPoints.push(nextPoint) + } + } + } + }) + console.log('sortedPoints : ', sortedPoints) + if (sortedPoints.length > 0) { + const roofPolygon = new QPolygon(sortedPoints, { + fill: 'transparent', + stroke: 'blue', + strokeWidth: 1, + selectable: false, + fontSize: roof.fontSize, + name: 'roofPolygon', + attributes: { roofId: roof.id, currentRoof: currentRoof.id }, + }) + canvas.add(roofPolygon) + canvas.renderAll() + } + }) +} + /** * 한쪽흐름 지붕 * @param roofId