지붕면 할당 오류 수정

This commit is contained in:
hyojun.choi 2024-11-14 15:36:57 +09:00
parent 221a498431
commit 706ad9aed8
5 changed files with 139 additions and 56 deletions

View File

@ -1,7 +1,7 @@
'use client'
import { useMessage } from '@/hooks/useMessage'
import { currentMenuState } from '@/store/canvasAtom'
import { canvasState, currentMenuState } from '@/store/canvasAtom'
import { useRecoilState, useRecoilValue } from 'recoil'
import { menuTypeState, subMenusState } from '@/store/menuAtom'
import useMenu from '@/hooks/common/useMenu'
@ -9,6 +9,7 @@ import { useEffect } from 'react'
export default function MenuDepth01() {
const type = useRecoilValue(menuTypeState)
const canvas = useRecoilValue(canvasState)
const { getMessage } = useMessage()
const { handleMenu } = useMenu()
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
@ -24,6 +25,7 @@ export default function MenuDepth01() {
useEffect(() => {
handleMenu(type)
canvas.discardActiveObject()
}, [currentMenu])
return (
<div className="canvas-depth2-inner">

View File

@ -107,7 +107,7 @@ export function useRoofAllocationSetting(id) {
}
})
})
if (currentObject && currentObject.name && !currentObject.name.toLowerCase().includes('text')) {
if (currentObject && currentObject.name && ['auxiliaryLine', 'ridge', 'hip'].includes(currentObject.name)) {
currentObject.set({
strokeWidth: 4,
stroke: '#EA10AC',

View File

@ -1,7 +1,7 @@
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, fontFamilyState, fontSizeState, pitchTextSelector } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil'
import { fabric } from 'fabric'
import { getDegreeByChon, getDegreeInOrientation, getDirectionByPoint, isPointOnLine } from '@/util/canvas-util'
import { findAndRemoveClosestPoint, getDegreeByChon, getDegreeInOrientation, getDirectionByPoint, isPointOnLine } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils'
import { flowDisplaySelector } from '@/store/settingAtom'
@ -86,8 +86,8 @@ export const usePolygon = () => {
parentDirection: line.direction,
parentDegree: degree,
parentId: polygon.id,
planeSize,
actualSize,
planeSize: planeSize ?? length,
actualSize: actualSize ?? length,
editable: false,
selectable: true,
lockRotation: true,
@ -669,62 +669,107 @@ export const usePolygon = () => {
const splitPolygonWithLines = (polygon) => {
polygon.set({ visible: false })
let innerLines = [...polygon.innerLines]
canvas.renderAll()
let polygonLines = [...polygon.lines]
const roofs = []
let delIndexs = []
let newLines = []
polygonLines.forEach((line, index) => {
line.tempIndex = index
//polygonLines를 순회하며 innerLines와 교차하는 점을 line의 속성에 배열로 저장한다.
polygonLines.forEach((line) => {
const intersections = []
innerLines.forEach((innerLine) => {
let newLine1, newLine2
if (isPointOnLine(line, innerLine.startPoint)) {
// 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다.
newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], {
fontSize: polygon.fontSize,
stroke: 'black',
strokeWidth: 3,
})
newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], {
fontSize: polygon.fontSize,
stroke: 'black',
strokeWidth: 3,
})
delIndexs.push(polygonLines.indexOf(line))
canvas.remove(polygonLines[polygonLines.indexOf(line)])
if (newLine1.length / 10 > 10) {
newLines.push(newLine1)
}
if (newLine2.length / 10 > 10) {
newLines.push(newLine2)
if (isSamePoint(line.startPoint, innerLine.startPoint) || isSamePoint(line.endPoint, innerLine.startPoint)) {
return
}
intersections.push(innerLine.startPoint)
}
if (isPointOnLine(line, innerLine.endPoint)) {
newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], {
fontSize: polygon.fontSize,
stroke: 'black',
strokeWidth: 3,
})
newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], {
fontSize: polygon.fontSize,
stroke: 'black',
strokeWidth: 3,
})
delIndexs.push(polygonLines.indexOf(line))
canvas.remove(polygonLines[polygonLines.indexOf(line)])
if (newLine1.length / 10 > 10) {
newLines.push(newLine1)
}
if (newLine2.length / 10 > 10) {
newLines.push(newLine2)
if (isSamePoint(line.startPoint, innerLine.endPoint) || isSamePoint(line.startPoint, innerLine.endPoint)) {
return
}
intersections.push(innerLine.endPoint)
}
})
line.set({ intersections })
})
polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex))
const divideLines = polygonLines.filter((line) => line.intersections.length > 0)
let newLines = []
divideLines.forEach((line) => {
const { intersections, startPoint, endPoint } = line
if (intersections.length === 1) {
// 한 점만 교차하는 경우
const newLinePoint1 = [line.x1, line.y1, intersections[0].x, intersections[0].y]
const newLinePoint2 = [intersections[0].x, intersections[0].y, line.x2, line.y2]
const newLine1 = new QLine(newLinePoint1, {
stroke: 'blue',
strokeWidth: 3,
fontSize: polygon.fontSize,
attributes: line.attributes,
})
const newLine2 = new QLine(newLinePoint2, {
stroke: 'blue',
strokeWidth: 3,
fontSize: polygon.fontSize,
attributes: line.attributes,
})
newLine1.attributes = {
...line.attributes,
planeSize: Math.round(Math.sqrt(Math.pow(newLine1.x1 - newLine1.x2, 2) + Math.pow(newLine1.y1 - newLine1.y2, 2))) * 10,
actualSize: Math.round(Math.sqrt(Math.pow(newLine1.x1 - newLine1.x2, 2) + Math.pow(newLine1.y1 - newLine1.y2, 2))) * 10,
}
newLine2.attributes = {
...line.attributes,
planeSize: Math.round(Math.sqrt(Math.pow(newLine2.x1 - newLine2.x2, 2) + Math.pow(newLine2.y1 - newLine2.y2, 2))) * 10,
actualSize: Math.round(Math.sqrt(Math.pow(newLine2.x1 - newLine2.x2, 2) + Math.pow(newLine2.y1 - newLine2.y2, 2))) * 10,
}
newLines.push(newLine1)
newLines.push(newLine2)
} else {
// 두 점 이상 교차하는 경우
//1. intersections중에 startPoint와 가장 가까운 점을 찾는다.
//2. 가장 가까운 점을 기준으로 line을 나눈다.
let currentPoint = startPoint
while (intersections.length !== 0) {
const minDistancePoint = findAndRemoveClosestPoint(currentPoint, intersections)
const newLinePoint = [currentPoint.x, currentPoint.y, minDistancePoint.x, minDistancePoint.y]
const newLine = new QLine(newLinePoint, {
stroke: 'blue',
strokeWidth: 3,
fontSize: polygon.fontSize,
attributes: line.attributes,
})
newLine.attributes = {
...line.attributes,
planeSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
actualSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
}
newLines.push(newLine)
currentPoint = minDistancePoint
}
const newLinePoint = [currentPoint.x, currentPoint.y, endPoint.x, endPoint.y]
const newLine = new QLine(newLinePoint, {
stroke: 'blue',
strokeWidth: 3,
fontSize: polygon.fontSize,
attributes: line.attributes,
})
newLine.attributes = {
...line.attributes,
planeSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
actualSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
}
newLines.push(newLine)
}
})
//polygonLines에서 divideLines를 제거하고 newLines를 추가한다.
polygonLines = polygonLines.filter((line) => !divideLines.includes(line))
polygonLines = [...polygonLines, ...newLines]
const allLines = [...polygonLines, ...innerLines]
@ -756,6 +801,9 @@ export const usePolygon = () => {
})
polygonLines.forEach((line) => {
line.set({ strokeWidth: 5, stroke: 'green' })
canvas.add(line)
canvas.renderAll()
const startPoint = line.startPoint // 시작점
let arrivalPoint = line.endPoint // 도착점
@ -819,17 +867,18 @@ export const usePolygon = () => {
roofPoints.push(currentPoint)
cnt++
if (cnt > 100) {
throw new Error('무한루프')
break
}
}
roofs.push(roofPoints)
canvas.remove(line)
canvas.renderAll()
})
const newRoofs = removeDuplicatePolygons(roofs)
const newRoofs = removeDuplicatePolygons(roofs.filter((roof) => roof.length < 100))
newRoofs.forEach((roofPoint, index) => {
let defense, pitch
const polygonLines = [...polygon.lines]
let representLines = []
let representLine
@ -901,7 +950,7 @@ export const usePolygon = () => {
//allLines중 생성된 roof와 관련있는 line을 찾는다.
roof.lines = [...polygon.lines, ...polygon.innerLines].filter((line) => {
roof.lines = [...polygonLines, ...polygon.innerLines].filter((line) => {
let startFlag = false
let endFlag = false
const startPoint = line.startPoint

View File

@ -977,3 +977,27 @@ export const getDegreeInOrientation = (degree) => {
return value * 15
}
export function findAndRemoveClosestPoint(targetPoint, points) {
if (points.length === 0) {
return null
}
let closestPoint = points[0]
let closestDistance = distanceBetweenPoints(targetPoint, points[0])
let closestIndex = 0
for (let i = 1; i < points.length; i++) {
const distance = distanceBetweenPoints(targetPoint, points[i])
if (distance < closestDistance) {
closestDistance = distance
closestPoint = points[i]
closestIndex = i
}
}
// Remove the closest point from the array
points.splice(closestIndex, 1)
return closestPoint
}

View File

@ -2949,7 +2949,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
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)
// roof.innerLines.push(gable3)
const hip1 = new QLine([currentRoof.x1, currentRoof.y1, gable1.x1, gable1.y1], {
fontSize: roof.fontSize,
@ -2967,7 +2968,7 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
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)
// roof.innerLines.push(hip1)
const hip2 = new QLine([currentRoof.x2, currentRoof.y2, gable2.x1, gable2.y1], {
fontSize: roof.fontSize,
@ -2985,7 +2986,14 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
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)
// roof.innerLines.push(hip2)
hip1.set({ visible: false })
hip1.setViewLengthText(false)
gable3.set({ visible: false })
gable3.setViewLengthText(false)
hip2.set({ visible: false })
hip2.setViewLengthText(false)
}
}
}