템플릿A,B 중간 저장
This commit is contained in:
parent
eb5bb77f1f
commit
d7bdfa4892
@ -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) {
|
||||
</>
|
||||
)}
|
||||
<ThumbnailList {...thumbnailProps} />
|
||||
<div className={'flex'}>
|
||||
{/* <div className={'flex'}>
|
||||
<p className={'m-1 p-3'}>각도 입력(0~360) 후 방향설정 클릭</p>
|
||||
<Input
|
||||
className="m-1 p-3"
|
||||
@ -1039,14 +1048,14 @@ export default function Roof2(props) {
|
||||
<Button className="m-1 p-3" onClick={setDirectionStringToArrow}>
|
||||
방향 설정
|
||||
</Button>
|
||||
</div>
|
||||
<div className="relative w-48 h-48 flex justify-center items-center border-2 border-gray-300 rounded-full">
|
||||
{/* Compass Circle */}
|
||||
</div>*/}
|
||||
{/* <div className="relative w-48 h-48 flex justify-center items-center border-2 border-gray-300 rounded-full">
|
||||
Compass Circle
|
||||
<div
|
||||
className="absolute w-full h-full border-2 border-gray-300 rounded-full flex justify-center items-center"
|
||||
style={{ rotate: `${globalCampass}deg` }}
|
||||
>
|
||||
{/* N, S, E, W Labels */}
|
||||
N, S, E, W Labels
|
||||
<div className="absolute top-2 text-lg font-bold">N</div>
|
||||
<div className="absolute bottom-2 text-lg font-bold">S</div>
|
||||
<div className="absolute right-2 text-lg font-bold" style={{ rotate: '90deg' }}>
|
||||
@ -1057,9 +1066,9 @@ export default function Roof2(props) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Compass Pointer */}
|
||||
Compass Pointer
|
||||
<div className="relative w-10 h-10">
|
||||
{/* Red Upper Triangle */}
|
||||
Red Upper Triangle
|
||||
<div
|
||||
className="absolute top-0"
|
||||
style={{
|
||||
@ -1072,7 +1081,7 @@ export default function Roof2(props) {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>*/}
|
||||
<div className="flex justify-start my-8 mx-2 w-full">
|
||||
<canvas ref={canvasRef} id="canvas" style={{ border: '1px solid black' }} />
|
||||
{!canvas ? null : mode === Mode.DRAW_LINE ? (
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) //지붕 그리기
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user