작업중 dev와 merge 금지
This commit is contained in:
parent
2159046e8f
commit
4101a3ede9
@ -13,6 +13,7 @@
|
|||||||
"@nextui-org/react": "^2.4.2",
|
"@nextui-org/react": "^2.4.2",
|
||||||
"ag-grid-react": "^32.0.2",
|
"ag-grid-react": "^32.0.2",
|
||||||
"axios": "^1.7.8",
|
"axios": "^1.7.8",
|
||||||
|
"big.js": "^6.2.2",
|
||||||
"chart.js": "^4.4.6",
|
"chart.js": "^4.4.6",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"fabric": "^5.3.0",
|
"fabric": "^5.3.0",
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
|
|
||||||
this.idx = options.idx ?? 0
|
this.idx = options.idx ?? 0
|
||||||
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
||||||
|
this.textMode = options.textMode ?? 'plane' // plane:복시도, actual:실측, none:표시안함
|
||||||
if (length !== 0) {
|
if (length !== 0) {
|
||||||
this.length = length
|
this.length = length
|
||||||
} else {
|
} else {
|
||||||
@ -60,70 +61,84 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
setLength() {
|
setLength() {
|
||||||
const scaleX = this.scaleX
|
if (this.attributes?.actualSize !== undefined && this.attributes?.planeSize !== undefined) {
|
||||||
const scaleY = this.scaleY
|
if (this.textMode === 'plane') {
|
||||||
const x1 = this.left
|
this.length = this.attributes.planeSize / 10
|
||||||
const y1 = this.top
|
} else if (this.textMode === 'actual') {
|
||||||
const x2 = this.left + this.width * scaleX
|
this.length = this.attributes.actualSize / 10
|
||||||
const y2 = this.top + this.height * scaleY
|
}
|
||||||
const dx = x2 - x1
|
} else {
|
||||||
const dy = y2 - y1
|
const scaleX = this.scaleX
|
||||||
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1))
|
const scaleY = this.scaleY
|
||||||
|
const x1 = this.left
|
||||||
|
const y1 = this.top
|
||||||
|
const x2 = this.left + this.width * scaleX
|
||||||
|
const y2 = this.top + this.height * scaleY
|
||||||
|
const dx = x2 - x1
|
||||||
|
const dy = y2 - y1
|
||||||
|
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addLengthText() {
|
addLengthText() {
|
||||||
const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
||||||
|
|
||||||
this.setLength()
|
if (this.textMode === 'none') {
|
||||||
const scaleX = this.scaleX
|
if (thisText) {
|
||||||
const scaleY = this.scaleY
|
this.canvas.remove(thisText)
|
||||||
const x1 = this.left
|
}
|
||||||
const y1 = this.top
|
} else {
|
||||||
const x2 = this.left + this.width * scaleX
|
this.setLength()
|
||||||
const y2 = this.top + this.height * scaleY
|
const scaleX = this.scaleX
|
||||||
|
const scaleY = this.scaleY
|
||||||
|
const x1 = this.left
|
||||||
|
const y1 = this.top
|
||||||
|
const x2 = this.left + this.width * scaleX
|
||||||
|
const y2 = this.top + this.height * scaleY
|
||||||
|
|
||||||
if (thisText) {
|
if (thisText) {
|
||||||
thisText.set({ text: this.getLength().toString(), left: (x1 + x2) / 2, top: (y1 + y2) / 2 })
|
thisText.set({ text: this.getLength().toString(), left: (x1 + x2) / 2, top: (y1 + y2) / 2 })
|
||||||
this.text = thisText
|
this.text = thisText
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
let left, top
|
||||||
|
if (this.direction === 'left' || this.direction === 'right') {
|
||||||
|
left = (x1 + x2) / 2
|
||||||
|
top = (y1 + y2) / 2 + 10
|
||||||
|
} else if (this.direction === 'top' || this.direction === 'bottom') {
|
||||||
|
left = (x1 + x2) / 2 + 10
|
||||||
|
top = (y1 + y2) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
const minX = this.left
|
||||||
|
const maxX = this.left + this.width
|
||||||
|
const minY = this.top
|
||||||
|
const maxY = this.top + this.length
|
||||||
|
const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI
|
||||||
|
|
||||||
|
const text = new fabric.Textbox(this.getLength().toString(), {
|
||||||
|
left: left,
|
||||||
|
top: top,
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
minX,
|
||||||
|
maxX,
|
||||||
|
minY,
|
||||||
|
maxY,
|
||||||
|
parentDirection: this.direction,
|
||||||
|
parentDegree: degree,
|
||||||
|
parentId: this.id,
|
||||||
|
editable: false,
|
||||||
|
selectable: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
|
parent: this,
|
||||||
|
name: 'lengthText',
|
||||||
|
})
|
||||||
|
|
||||||
|
this.text = text
|
||||||
|
this.canvas.add(text)
|
||||||
}
|
}
|
||||||
let left, top
|
|
||||||
if (this.direction === 'left' || this.direction === 'right') {
|
|
||||||
left = (x1 + x2) / 2
|
|
||||||
top = (y1 + y2) / 2 + 10
|
|
||||||
} else if (this.direction === 'top' || this.direction === 'bottom') {
|
|
||||||
left = (x1 + x2) / 2 + 10
|
|
||||||
top = (y1 + y2) / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
const minX = this.left
|
|
||||||
const maxX = this.left + this.width
|
|
||||||
const minY = this.top
|
|
||||||
const maxY = this.top + this.length
|
|
||||||
const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI
|
|
||||||
|
|
||||||
const text = new fabric.Textbox(this.getLength().toString(), {
|
|
||||||
left: left,
|
|
||||||
top: top,
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
minX,
|
|
||||||
maxX,
|
|
||||||
minY,
|
|
||||||
maxY,
|
|
||||||
parentDirection: this.direction,
|
|
||||||
parentDegree: degree,
|
|
||||||
parentId: this.id,
|
|
||||||
editable: false,
|
|
||||||
selectable: true,
|
|
||||||
lockRotation: true,
|
|
||||||
lockScalingX: true,
|
|
||||||
lockScalingY: true,
|
|
||||||
parent: this,
|
|
||||||
name: 'lengthText',
|
|
||||||
})
|
|
||||||
|
|
||||||
this.text = text
|
|
||||||
this.canvas.add(text)
|
|
||||||
},
|
},
|
||||||
setFontSize(fontSize) {
|
setFontSize(fontSize) {
|
||||||
this.fontSize = fontSize
|
this.fontSize = fontSize
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint
|
|||||||
import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils'
|
import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, 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'
|
||||||
|
|
||||||
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||||
type: 'QPolygon',
|
type: 'QPolygon',
|
||||||
@ -188,7 +189,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 보조선 그리기
|
// 보조선 그리기
|
||||||
drawHelpLine() {
|
drawHelpLine(settingModalFirstOptions) {
|
||||||
const types = []
|
const types = []
|
||||||
this.lines.forEach((line) => types.push(line.attributes.type))
|
this.lines.forEach((line) => types.push(line.attributes.type))
|
||||||
|
|
||||||
@ -205,7 +206,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)
|
drawGabledRoof(this.id, this.canvas, settingModalFirstOptions)
|
||||||
} 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) {
|
||||||
@ -232,18 +233,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)
|
drawShedRoof(this.id, this.canvas, settingModalFirstOptions)
|
||||||
} else {
|
} else {
|
||||||
drawRidgeRoof(this.id, this.canvas)
|
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drawRidgeRoof(this.id, this.canvas)
|
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drawRidgeRoof(this.id, this.canvas)
|
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drawRidgeRoof(this.id, this.canvas)
|
drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -262,15 +263,16 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
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,
|
// 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,
|
// actualSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
|
||||||
const dx = end.x - start.x
|
const dx = Big(end.x).minus(Big(start.x))
|
||||||
const dy = end.y - 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 = 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()
|
||||||
|
|
||||||
let midPoint
|
let midPoint
|
||||||
|
|
||||||
midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2)
|
midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2)
|
||||||
|
|
||||||
const degree = (Math.atan2(dy, dx) * 180) / Math.PI
|
const degree = Big(Math.atan2(dy.toNumber(), dx.toNumber())).times(180).div(Math.PI).toNumber()
|
||||||
|
|
||||||
// Create new text object if it doesn't exist
|
// Create new text object if it doesn't exist
|
||||||
const text = new fabric.Text(length.toString(), {
|
const text = new fabric.Text(length.toString(), {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { outerLineFixState } from '@/store/outerLineAtom'
|
|||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { getChonByDegree } from '@/util/canvas-util'
|
import { getChonByDegree } from '@/util/canvas-util'
|
||||||
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
|
|
||||||
// 처마.케라바 변경
|
// 처마.케라바 변경
|
||||||
export function useEavesGableEdit(id) {
|
export function useEavesGableEdit(id) {
|
||||||
@ -46,6 +47,8 @@ export function useEavesGableEdit(id) {
|
|||||||
{ id: 4, name: getMessage('shed'), type: TYPES.SHED },
|
{ id: 4, name: getMessage('shed'), type: TYPES.SHED },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
if (!outerLineFix || outerLines.length === 0) {
|
if (!outerLineFix || outerLines.length === 0) {
|
||||||
@ -180,7 +183,7 @@ export function useEavesGableEdit(id) {
|
|||||||
const roof = drawRoofPolygon(wallLine)
|
const roof = drawRoofPolygon(wallLine)
|
||||||
|
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine(settingModalFirstOptions)
|
||||||
})
|
})
|
||||||
|
|
||||||
wallLines.forEach((wallLine) => {
|
wallLines.forEach((wallLine) => {
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import { fabric } from 'fabric'
|
|||||||
import { outlineDisplaySelector } from '@/store/settingAtom'
|
import { outlineDisplaySelector } from '@/store/settingAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting'
|
import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting'
|
||||||
|
import Big from 'big.js'
|
||||||
|
|
||||||
//외벽선 그리기
|
//외벽선 그리기
|
||||||
export function useOuterLineWall(id, propertiesId) {
|
export function useOuterLineWall(id, propertiesId) {
|
||||||
@ -141,6 +142,8 @@ export function useOuterLineWall(id, propertiesId) {
|
|||||||
|
|
||||||
const mouseDown = (e) => {
|
const mouseDown = (e) => {
|
||||||
let pointer = getIntersectMousePoint(e)
|
let pointer = getIntersectMousePoint(e)
|
||||||
|
pointer = { x: Big(pointer.x).round(1).toNumber(), y: Big(pointer.y).round(1).toNumber() }
|
||||||
|
console.log('mouseDown', pointer, points)
|
||||||
|
|
||||||
if (points.length === 0) {
|
if (points.length === 0) {
|
||||||
setPoints((prev) => [...prev, pointer])
|
setPoints((prev) => [...prev, pointer])
|
||||||
@ -148,24 +151,30 @@ export function useOuterLineWall(id, propertiesId) {
|
|||||||
const lastPoint = points[points.length - 1]
|
const lastPoint = points[points.length - 1]
|
||||||
let newPoint = { x: pointer.x, y: pointer.y }
|
let newPoint = { x: pointer.x, y: pointer.y }
|
||||||
const length = distanceBetweenPoints(lastPoint, newPoint)
|
const length = distanceBetweenPoints(lastPoint, newPoint)
|
||||||
|
console.log('length', length)
|
||||||
if (verticalHorizontalMode) {
|
if (verticalHorizontalMode) {
|
||||||
const vector = {
|
const vector = {
|
||||||
x: pointer.x - points[points.length - 1].x,
|
x: Big(pointer.x).minus(Big(points[points.length - 1].x)),
|
||||||
y: pointer.y - points[points.length - 1].y,
|
y: Big(pointer.y).minus(Big(points[points.length - 1].y)),
|
||||||
}
|
}
|
||||||
const slope = Math.abs(vector.y / vector.x) // 기울기 계산
|
// const slope = Math.abs(vector.y / vector.x) // 기울기 계산
|
||||||
|
console.log('vector', vector.x.toNumber(), vector.y.toNumber(), Math.abs(vector.y.toNumber() / vector.x.toNumber()) >= 1)
|
||||||
|
const slope = vector.x.eq(0) ? Big(1) : vector.y.div(vector.x).abs() // 기울기 계산
|
||||||
|
|
||||||
let scaledVector
|
let scaledVector
|
||||||
if (slope >= 1) {
|
// if (slope >= 1) {
|
||||||
|
if (slope.gte(1)) {
|
||||||
// 기울기가 1 이상이면 x축 방향으로 그림
|
// 기울기가 1 이상이면 x축 방향으로 그림
|
||||||
scaledVector = {
|
scaledVector = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: vector.y >= 0 ? Number(length) : -Number(length),
|
// y: vector.y >= 0 ? Number(length) : -Number(length),
|
||||||
|
y: vector.y.gte(0) ? Big(length).toNumber() : Big(length).neg().toNumber(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 기울기가 1 미만이면 y축 방향으로 그림
|
// 기울기가 1 미만이면 y축 방향으로 그림
|
||||||
scaledVector = {
|
scaledVector = {
|
||||||
x: vector.x >= 0 ? Number(length) : -Number(length),
|
// x: vector.x >= 0 ? Number(length) : -Number(length),
|
||||||
|
x: vector.x.gte(0) ? Big(length).toNumber() : Big(length).neg().toNumber(),
|
||||||
y: 0,
|
y: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,9 +182,11 @@ export function useOuterLineWall(id, propertiesId) {
|
|||||||
const verticalLength = scaledVector.y
|
const verticalLength = scaledVector.y
|
||||||
const horizontalLength = scaledVector.x
|
const horizontalLength = scaledVector.x
|
||||||
|
|
||||||
|
console.log('verticalLength', verticalLength, 'horizontalLength', horizontalLength)
|
||||||
|
|
||||||
newPoint = {
|
newPoint = {
|
||||||
x: lastPoint.x + horizontalLength,
|
x: Big(lastPoint.x).plus(horizontalLength).toNumber(),
|
||||||
y: lastPoint.y + verticalLength,
|
y: Big(lastPoint.y).plus(verticalLength).toNumber(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setPoints((prev) => [...prev, newPoint])
|
setPoints((prev) => [...prev, newPoint])
|
||||||
@ -865,6 +876,8 @@ export function useOuterLineWall(id, propertiesId) {
|
|||||||
|
|
||||||
const firstPoint = points[0]
|
const firstPoint = points[0]
|
||||||
|
|
||||||
|
console.log('points 좌표 : ', points)
|
||||||
|
|
||||||
points.forEach((point, idx) => {
|
points.forEach((point, idx) => {
|
||||||
if (idx === 0 || !isAllRightAngle) {
|
if (idx === 0 || !isAllRightAngle) {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
import { useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
|
|
||||||
// 외벽선 속성 설정
|
// 외벽선 속성 설정
|
||||||
export function usePropertiesSetting(id) {
|
export function usePropertiesSetting(id) {
|
||||||
@ -16,6 +17,7 @@ export function usePropertiesSetting(id) {
|
|||||||
|
|
||||||
const { drawRoofPolygon } = useMode()
|
const { drawRoofPolygon } = useMode()
|
||||||
const setPoints = useResetRecoilState(outerLinePointsState)
|
const setPoints = useResetRecoilState(outerLinePointsState)
|
||||||
|
const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState)
|
||||||
|
|
||||||
const { addPolygonByLines } = usePolygon()
|
const { addPolygonByLines } = usePolygon()
|
||||||
const { removeLine, hideLine } = useLine()
|
const { removeLine, hideLine } = useLine()
|
||||||
@ -156,7 +158,7 @@ export function usePropertiesSetting(id) {
|
|||||||
|
|
||||||
setPoints([])
|
setPoints([])
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine(settingModalFirstOptions)
|
||||||
|
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { outerLineFixState } from '@/store/outerLineAtom'
|
|||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { getChonByDegree } from '@/util/canvas-util'
|
import { getChonByDegree } from '@/util/canvas-util'
|
||||||
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
|
|
||||||
// 지붕형상 설정
|
// 지붕형상 설정
|
||||||
export function useRoofShapeSetting(id) {
|
export function useRoofShapeSetting(id) {
|
||||||
@ -48,6 +49,8 @@ export function useRoofShapeSetting(id) {
|
|||||||
const history = useRef([])
|
const history = useRef([])
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
pitchRef.current = currentAngleType === ANGLE_TYPE.SLOPE ? pitch : getChonByDegree(pitch)
|
pitchRef.current = currentAngleType === ANGLE_TYPE.SLOPE ? pitch : getChonByDegree(pitch)
|
||||||
}, [pitch])
|
}, [pitch])
|
||||||
@ -423,7 +426,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
const roof = drawRoofPolygon(polygon)
|
const roof = drawRoofPolygon(polygon)
|
||||||
|
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine(settingModalFirstOptions)
|
||||||
isFixRef.current = true
|
isFixRef.current = true
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,8 @@ import offsetPolygon from '@/util/qpolygon-utils'
|
|||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common'
|
import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common'
|
||||||
|
import Big from 'big.js'
|
||||||
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
|
|
||||||
export function useMode() {
|
export function useMode() {
|
||||||
const [mode, setMode] = useRecoilState(modeState)
|
const [mode, setMode] = useRecoilState(modeState)
|
||||||
@ -78,6 +80,8 @@ export function useMode() {
|
|||||||
|
|
||||||
const [objectPlacementMode, setObjectPlacementModeState] = useRecoilState(objectPlacementModeState)
|
const [objectPlacementMode, setObjectPlacementModeState] = useRecoilState(objectPlacementModeState)
|
||||||
|
|
||||||
|
const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if (!canvas) {
|
// if (!canvas) {
|
||||||
// canvas?.setZoom(0.8)
|
// canvas?.setZoom(0.8)
|
||||||
@ -1554,7 +1558,7 @@ export function useMode() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const roof = drawRoofPolygon(polygon) //지붕 그리기
|
const roof = drawRoofPolygon(polygon) //지붕 그리기
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine(settingModalFirstOptions)
|
||||||
// roof.divideLine()
|
// roof.divideLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1664,11 +1668,18 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* polygon 을 기준으로 margin 된 polygon 을 작성한다.
|
||||||
|
* @param polygon
|
||||||
|
* @param lines
|
||||||
|
* @param arcSegments
|
||||||
|
* @returns {{vertices, edges: *[], minX: *, minY: *, maxX: *, maxY: *}}
|
||||||
|
*/
|
||||||
function createMarginPolygon(polygon, lines, arcSegments = 0) {
|
function createMarginPolygon(polygon, lines, arcSegments = 0) {
|
||||||
const offsetEdges = []
|
const offsetEdges = []
|
||||||
|
|
||||||
polygon.edges.forEach((edge, i) => {
|
polygon.edges.forEach((edge, i) => {
|
||||||
const offset = lines[i % lines.length].attributes.offset === 0 ? 1 : lines[i % lines.length].attributes.offset
|
const offset = lines[i % lines.length].attributes.offset === 0 ? 0.1 : lines[i % lines.length].attributes.offset
|
||||||
const dx = edge.outwardNormal.x * offset
|
const dx = edge.outwardNormal.x * offset
|
||||||
const dy = edge.outwardNormal.y * offset
|
const dy = edge.outwardNormal.y * offset
|
||||||
offsetEdges.push(createOffsetEdge(edge, dx, dy))
|
offsetEdges.push(createOffsetEdge(edge, dx, dy))
|
||||||
@ -1692,6 +1703,13 @@ export function useMode() {
|
|||||||
return marginPolygon
|
return marginPolygon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* polygon 을 기준으로 padding 된 polygon 을 작성한다.
|
||||||
|
* @param polygon
|
||||||
|
* @param lines
|
||||||
|
* @param arcSegments
|
||||||
|
* @returns {{vertices, edges: *[], minX: *, minY: *, maxX: *, maxY: *}}
|
||||||
|
*/
|
||||||
function createPaddingPolygon(polygon, lines, arcSegments = 0) {
|
function createPaddingPolygon(polygon, lines, arcSegments = 0) {
|
||||||
const offsetEdges = []
|
const offsetEdges = []
|
||||||
|
|
||||||
@ -1720,7 +1738,13 @@ export function useMode() {
|
|||||||
return paddingPolygon
|
return paddingPolygon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 외벽선을 기준으로 지붕을 그린다.
|
||||||
|
* @param wall
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
const drawRoofPolygon = (wall) => {
|
const drawRoofPolygon = (wall) => {
|
||||||
|
//외벽선의 순서를 최좌측 선을 기준으로 반시계방향으로 정리한다. 지붕선과 순서를 맞추기 위함.
|
||||||
const startLine = wall.lines
|
const startLine = wall.lines
|
||||||
.filter((line) => line.x1 === Math.min(...wall.lines.map((line) => line.x1)))
|
.filter((line) => line.x1 === Math.min(...wall.lines.map((line) => line.x1)))
|
||||||
.reduce((prev, current) => {
|
.reduce((prev, current) => {
|
||||||
@ -1740,12 +1764,15 @@ export function useMode() {
|
|||||||
|
|
||||||
wall.lines = afterLine.concat(beforeLine)
|
wall.lines = afterLine.concat(beforeLine)
|
||||||
|
|
||||||
|
//외벽선을 기준으로 polygon을 생성한다. 지붕선의 기준이 됨.
|
||||||
const polygon = createRoofPolygon(wall.points)
|
const polygon = createRoofPolygon(wall.points)
|
||||||
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
|
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
|
||||||
originPolygon.setViewLengthText(false)
|
originPolygon.setViewLengthText(false)
|
||||||
let offsetPolygon
|
let offsetPolygon
|
||||||
|
|
||||||
let result = createMarginPolygon(polygon, wall.lines).vertices
|
let result = createMarginPolygon(polygon, wall.lines).vertices
|
||||||
|
|
||||||
|
//margin polygon 의 point가 기준 polygon의 밖에 있는지 판단한다.
|
||||||
const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point))
|
const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point))
|
||||||
|
|
||||||
if (allPointsOutside) {
|
if (allPointsOutside) {
|
||||||
@ -1759,6 +1786,7 @@ export function useMode() {
|
|||||||
return { x1: point.x, y1: point.y }
|
return { x1: point.x, y1: point.y }
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (wall.direction) {
|
if (wall.direction) {
|
||||||
roof.direction = wall.direction
|
roof.direction = wall.direction
|
||||||
}
|
}
|
||||||
@ -1769,9 +1797,11 @@ export function useMode() {
|
|||||||
roof.setWall(wall)
|
roof.setWall(wall)
|
||||||
|
|
||||||
roof.lines.forEach((line, index) => {
|
roof.lines.forEach((line, index) => {
|
||||||
const lineLength = Math.sqrt(
|
const x1 = Big(line.x1)
|
||||||
Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2),
|
const x2 = Big(line.x2)
|
||||||
)
|
const y1 = Big(line.y1)
|
||||||
|
const y2 = Big(line.y2)
|
||||||
|
const lineLength = x1.minus(x2).abs().pow(2).plus(y1.minus(y2).abs().pow(2)).sqrt().times(10).round().toNumber()
|
||||||
line.attributes = {
|
line.attributes = {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
planeSize: lineLength,
|
planeSize: lineLength,
|
||||||
@ -1789,14 +1819,18 @@ export function useMode() {
|
|||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//외벽선 삭제
|
||||||
canvas
|
canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((line) => line.attributes?.wallId === wall.id)
|
.filter((line) => line.attributes?.wallId === wall.id)
|
||||||
.forEach((line) => canvas.remove(line))
|
.forEach((line) => canvas.remove(line))
|
||||||
|
|
||||||
wall.lines.forEach((line, index) => {
|
wall.lines.forEach((line, index) => {
|
||||||
const lineLength = Math.sqrt(
|
const x1 = Big(line.x1)
|
||||||
Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2),
|
const x2 = Big(line.x2)
|
||||||
)
|
const y1 = Big(line.y1)
|
||||||
|
const y2 = Big(line.y2)
|
||||||
|
const lineLength = x1.minus(x2).abs().pow(2).plus(y1.minus(y2).abs().pow(2)).sqrt().times(10).round().toNumber()
|
||||||
line.attributes.roofId = roof.id
|
line.attributes.roofId = roof.id
|
||||||
line.attributes.currentRoofId = roof.lines[index].id
|
line.attributes.currentRoofId = roof.lines[index].id
|
||||||
line.attributes.planeSize = lineLength
|
line.attributes.planeSize = lineLength
|
||||||
@ -1829,6 +1863,8 @@ export function useMode() {
|
|||||||
wallStrokeWidth = 4
|
wallStrokeWidth = 4
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//외벽선의 색깔 표시를 위해 라인을 추가한다.
|
||||||
const wallLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
|
const wallLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
|
||||||
parentId: wall.id,
|
parentId: wall.id,
|
||||||
name: 'wallLine',
|
name: 'wallLine',
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { calculateIntersection, getInterSectionLineNotOverCoordinate } from '@/util/canvas-util'
|
import { getInterSectionLineNotOverCoordinate } from '@/util/canvas-util'
|
||||||
|
|
||||||
export function useMouse() {
|
export function useMouse() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
//가로선, 세로선의 교차점을 return
|
//가로선, 세로선의 교차점을 return
|
||||||
const getIntersectMousePoint = (e) => {
|
/*const getIntersectMousePoint = (e) => {
|
||||||
let pointer = canvas.getPointer(e.e)
|
let pointer = canvas.getPointer(e.e)
|
||||||
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
|
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
|
||||||
|
|
||||||
@ -15,6 +15,17 @@ export function useMouse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return getInterSectionLineNotOverCoordinate(mouseLines[0], mouseLines[1]) || pointer
|
return getInterSectionLineNotOverCoordinate(mouseLines[0], mouseLines[1]) || pointer
|
||||||
|
}*/
|
||||||
|
//가로선, 세로선의 교차점을 return
|
||||||
|
const getIntersectMousePoint = (e) => {
|
||||||
|
let pointer = canvas.getPointer(e.e)
|
||||||
|
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
|
||||||
|
|
||||||
|
if (mouseLines.length < 2) {
|
||||||
|
return { x: Math.round(pointer.x), y: Math.round(pointer.y) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return getInterSectionLineNotOverCoordinate(mouseLines[0], mouseLines[1]) || { x: Math.round(pointer.x), y: Math.round(pointer.y) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { intersect } from 'mathjs'
|
import { intersect } from 'mathjs'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
|
import Big from 'big.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of function to use on canvas
|
* Collection of function to use on canvas
|
||||||
@ -128,9 +129,9 @@ export const formattedWithComma = (value, unit = 'mm') => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const distanceBetweenPoints = (point1, point2) => {
|
export const distanceBetweenPoints = (point1, point2) => {
|
||||||
const dx = point2.x - point1.x
|
const dx = Big(point2.x).minus(Big(point1.x))
|
||||||
const dy = point2.y - point1.y
|
const dy = Big(point2.y).minus(Big(point1.y))
|
||||||
return Math.sqrt(dx * dx + dy * dy)
|
return dx.pow(2).plus(dy.pow(2)).sqrt().round(1).toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user