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) {
>
)}
-
+ {/*
-
- {/* 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