버그 수정

This commit is contained in:
Jaeyoung Lee 2025-02-13 16:44:43 +09:00
parent 55b29bfdd3
commit 2ca9fd5bbc
4 changed files with 56 additions and 123 deletions

View File

@ -2,7 +2,7 @@ import { fabric } from 'fabric'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils'
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import Big from 'big.js' import Big from 'big.js'
@ -188,8 +188,28 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
}) })
}, },
// 보조선 그리기 /**
* 보조선 그리기
* @param settingModalFirstOptions
*/
drawHelpLine(settingModalFirstOptions) { drawHelpLine(settingModalFirstOptions) {
let textMode = 'plane'
const dimensionDisplay = settingModalFirstOptions?.dimensionDisplay.find((opt) => opt.selected).id
? settingModalFirstOptions?.dimensionDisplay.find((opt) => opt.selected).id
: 1
switch (dimensionDisplay) {
case 1:
textMode = 'plane'
break
case 2:
textMode = 'actual'
break
case 3:
textMode = 'none'
break
}
const types = [] const types = []
this.lines.forEach((line) => types.push(line.attributes.type)) this.lines.forEach((line) => types.push(line.attributes.type))
@ -206,7 +226,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
(gableOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableEven.every((type) => gableType.includes(type))) || (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))) (gableEven.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableOdd.every((type) => gableType.includes(type)))
) { ) {
drawGabledRoof(this.id, this.canvas, settingModalFirstOptions) drawGabledRoof(this.id, this.canvas, textMode)
} else if (hasShed) { } else if (hasShed) {
const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED)
const areLinesParallel = function (line1, line2) { const areLinesParallel = function (line1, line2) {
@ -233,18 +253,18 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false) const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false)
const isGable = gables.every((line) => gableType.includes(line.attributes.type)) const isGable = gables.every((line) => gableType.includes(line.attributes.type))
if (isGable) { if (isGable) {
drawShedRoof(this.id, this.canvas, settingModalFirstOptions) drawShedRoof(this.id, this.canvas, textMode)
} else { } else {
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) drawRidgeRoof(this.id, this.canvas, textMode)
} }
} else { } else {
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) drawRidgeRoof(this.id, this.canvas, textMode)
} }
} else { } else {
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) drawRidgeRoof(this.id, this.canvas, textMode)
} }
} else { } else {
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) drawRidgeRoof(this.id, this.canvas, textMode)
} }
}, },
@ -264,11 +284,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.texts = [] this.texts = []
points.forEach((start, i) => { points.forEach((start, i) => {
const end = points[(i + 1) % points.length] const end = points[(i + 1) % points.length]
// 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,
const dx = Big(end.x).minus(Big(start.x)) const dx = Big(end.x).minus(Big(start.x))
const dy = Big(end.y).minus(Big(start.y)) const dy = Big(end.y).minus(Big(start.y))
// const length = Math.round(Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2))) * 10
const length = dx.pow(2).plus(dy.pow(2)).sqrt().times(10).round().toNumber() const length = dx.pow(2).plus(dy.pow(2)).sqrt().times(10).round().toNumber()
let midPoint let midPoint
@ -323,75 +340,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
setCanvas(canvas) { setCanvas(canvas) {
this.canvas = canvas this.canvas = canvas
}, },
fillCell(cell = { width: 50, height: 100, padding: 10 }) {
const points = this.points
const minX = Math.min(...points.map((p) => p.x))
const maxX = Math.max(...points.map((p) => p.x))
const minY = Math.min(...points.map((p) => p.y))
const maxY = Math.max(...points.map((p) => p.y))
const boundingBoxWidth = maxX - minX
const boundingBoxHeight = maxY - minY
const rectWidth = cell.width
const rectHeight = cell.height
const cols = Math.floor((boundingBoxWidth + cell.padding) / (rectWidth + cell.padding))
const rows = Math.floor((boundingBoxHeight + cell.padding) / (rectHeight + cell.padding))
//전체 높이에서 패딩을 포함하고 rows를 곱해서 여백길이를 계산 후에 2로 나누면 반높이를 넣어서 중간으로 정렬
const tmpHeight = (boundingBoxHeight - (rectHeight + cell.padding) * rows) / 2
//센터 정렬시에 쓴다 체크박스가 존재함 TODO: if문 추가해서 정렬해야함
let tmpWidth = (boundingBoxWidth - (rectWidth + cell.padding) * cols) / 2
const drawCellsArray = [] //그려진 셀의 배열
let idx = 1
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
const rectLeft = minX + i * (rectWidth + cell.padding)
const rectTop = minY + j * (rectHeight + cell.padding)
const rectPoints = [
{ x: rectLeft, y: rectTop },
{ x: rectLeft, y: rectTop + rectHeight },
{ x: rectLeft + rectWidth, y: rectTop + rectHeight },
{ x: rectLeft + rectWidth, y: rectTop },
]
if (inPolygon(this.points, rectPoints)) {
const rect = new fabric.Rect({
left: rectLeft,
top: rectTop,
width: rectWidth,
height: rectHeight,
fill: '#BFFD9F',
stroke: 'black',
selectable: true, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
name: 'cell',
idx: idx,
parentId: this.id,
parent: this,
})
idx++
drawCellsArray.push(rect) //배열에 넣어서 반환한다
this.canvas.add(rect)
}
}
}
this.canvas?.renderAll()
this.cells = drawCellsArray
return drawCellsArray
},
fillCellABType( fillCellABType(
cell = { width: 50, height: 100, padding: 5, wallDirection: 'left', referenceDirection: 'none', startIndex: -1, isCellCenter: false }, cell = { width: 50, height: 100, padding: 5, wallDirection: 'left', referenceDirection: 'none', startIndex: -1, isCellCenter: false },
) { ) {

View File

@ -329,7 +329,9 @@ export function useRoofFn() {
const allRoofObject = canvas const allRoofObject = canvas
.getObjects() .getObjects()
.filter((obj) => /*obj !== roof && obj !== wall &&*/ obj.attributes?.roofId === roof.id || obj.parentId === roof.id || obj.parentId === wall.id) .filter(
(obj) => /*obj !== roof && obj !== wall &&*/ obj.attributes?.roofId === roof.id || obj.parentId === roof.id || obj.parentId === wall?.id,
)
allRoofObject.forEach((obj) => { allRoofObject.forEach((obj) => {
canvas.remove(obj) canvas.remove(obj)

View File

@ -1797,6 +1797,10 @@ export function useMode() {
roof.direction = wall.direction roof.direction = wall.direction
} }
if (wall.attributes?.roofId) { if (wall.attributes?.roofId) {
canvas
.getObjects()
.filter((obj) => obj.parentId === roof.id)
.forEach((obj) => obj.set('parentId', wall.attributes.roofId))
roof.id = wall.attributes.roofId roof.id = wall.attributes.roofId
} }
roof.name = POLYGON_TYPE.ROOF roof.name = POLYGON_TYPE.ROOF

View File

@ -312,8 +312,9 @@ export const isSamePoint = (a, b) => {
* 박공지붕(templateA, templateB) 그린다. * 박공지붕(templateA, templateB) 그린다.
* @param roofId * @param roofId
* @param canvas * @param canvas
* @param textMode
*/ */
export const drawGabledRoof = (roofId, canvas, settingModalFirstOptions) => { export const drawGabledRoof = (roofId, canvas, textMode) => {
const roof = canvas?.getObjects().find((object) => object.id === roofId) const roof = canvas?.getObjects().find((object) => object.id === roofId)
const roofLines = roof.lines const roofLines = roof.lines
const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines
@ -323,15 +324,6 @@ export const drawGabledRoof = (roofId, canvas, settingModalFirstOptions) => {
return 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))
// 맞은편 라인을 찾기 위해 현재 polygon 으로 만들수 있는 최대한의 길이를 구한다.
// const checkLength = Math.abs(Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)))
// 처마라인의 기본속성 입력 // 처마라인의 기본속성 입력
const eaves = [] const eaves = []
roofLines.forEach((currentRoof, index) => { roofLines.forEach((currentRoof, index) => {
@ -650,8 +642,9 @@ export const drawGabledRoof = (roofId, canvas, settingModalFirstOptions) => {
* 한쪽흐름 지붕 * 한쪽흐름 지붕
* @param roofId * @param roofId
* @param canvas * @param canvas
* @param textMode
*/ */
export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => { export const drawShedRoof = (roofId, canvas, textMode) => {
const roof = canvas?.getObjects().find((object) => object.id === roofId) const roof = canvas?.getObjects().find((object) => object.id === roofId)
const hasNonParallelLines = roof.lines.filter((line) => Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1) const hasNonParallelLines = roof.lines.filter((line) => Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1)
if (hasNonParallelLines.length > 0) { if (hasNonParallelLines.length > 0) {
@ -673,11 +666,9 @@ export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => {
return Math.tan(degree * (Math.PI / 180)) * adjust return Math.tan(degree * (Math.PI / 180)) * adjust
} }
gables.forEach((gable) => { gables.forEach(
const adjust = gable.attributes.planeSize (gable) => (gable.attributes.actualSize = calcLineActualSize({ x1: gable.x1, y1: gable.y1, x2: gable.x2, y2: gable.y2 }, shedDegree)),
const height = getHeight(adjust, shedDegree) )
gable.attributes.actualSize = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2)))
})
const pitchSizeLines = [] const pitchSizeLines = []
@ -707,8 +698,11 @@ export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => {
x2 = eave.x1 x2 = eave.x1
} }
points.sort((a, b) => a - b) points.sort((a, b) => a - b)
const planeSize = Math.round(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)) * 10) // const planeSize = Math.round(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)) * 10)
const actualSize = Math.round(Math.sqrt(Math.pow(planeSize, 2) + Math.pow(getHeight(planeSize, shedDegree), 2)) * 10) const planeSize = calcLinePlaneSize({ x1, y1, x2, y2 })
// const actualSize = Math.round(Math.sqrt (Math.pow(planeSize, 2) + Math.pow(getHeight(planeSize, shedDegree), 2)) * 10)
const actualSize = calcLineActualSize({ x1, y1, x2, y2 }, shedDegree)
const line = new QLine([x1, y1, x2, y2], { const line = new QLine([x1, y1, x2, y2], {
parentId: roof.id, parentId: roof.id,
stroke: '#000000', stroke: '#000000',
@ -716,10 +710,11 @@ export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => {
strokeDashArray: [5, 5], strokeDashArray: [5, 5],
selectable: false, selectable: false,
fontSize: roof.fontSize, fontSize: roof.fontSize,
textMode: textMode,
attributes: { attributes: {
roofId: roof.id, roofId: roof.id,
type: 'pitchSizeLine', type: 'pitchSizeLine',
planeSize: planeSize, planeSize: actualSize,
actualSize: actualSize, actualSize: actualSize,
}, },
}) })
@ -730,33 +725,17 @@ export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => {
const maxLine = pitchSizeLines.reduce((prev, current) => (prev.length > current.length ? prev : current), pitchSizeLines[0]) const maxLine = pitchSizeLines.reduce((prev, current) => (prev.length > current.length ? prev : current), pitchSizeLines[0])
canvas.add(maxLine) canvas.add(maxLine)
canvas.renderAll() canvas.renderAll()
const adjust = Math.sqrt(
Math.pow(Math.round(Math.abs(maxLine.x1 - maxLine.x2) * 10), 2) + Math.pow(Math.round(Math.abs(maxLine.y1 - maxLine.y2) * 10), 2),
)
const height = getHeight(adjust, shedDegree)
const lengthText = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2)))
maxLine.setLengthText(lengthText)
} }
export const drawRidgeRoof = (roofId, canvas, settingModalFirstOptions) => { /**
* 마루가 있는 지붕을 그린다.
* @param roofId
* @param canvas
* @param textMode
*/
export const drawRidgeRoof = (roofId, canvas, textMode) => {
const roof = canvas?.getObjects().find((object) => object.id === roofId) const roof = canvas?.getObjects().find((object) => object.id === roofId)
let textMode = 'plane'
const dimensionDisplay = settingModalFirstOptions?.dimensionDisplay.find((opt) => opt.selected).id
? settingModalFirstOptions?.dimensionDisplay.find((opt) => opt.selected).id
: 1
switch (dimensionDisplay) {
case 1:
textMode = 'plane'
break
case 2:
textMode = 'actual'
break
case 3:
textMode = 'none'
break
}
//Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1 //Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1
const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1)) const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1))
if (hasNonParallelLines.length > 0) { if (hasNonParallelLines.length > 0) {