qcast-front/src/hooks/useLine.js

226 lines
6.5 KiB
JavaScript

import { useRecoilValue } from 'recoil'
import {
canvasState,
currentAngleTypeSelector,
fontFamilyState,
fontSizeState,
globalPitchState,
pitchTextSelector,
showAngleUnitSelector,
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { basicSettingState } from '@/store/settingAtom'
import { calcLineActualSizeByLineLength } from '@/util/qpolygon-utils'
import { getDegreeByChon } from '@/util/canvas-util'
import { useText } from '@/hooks/useText'
import { fontSelector } from '@/store/fontAtom'
export const useLine = () => {
const canvas = useRecoilValue(canvasState)
const fontSize = useRecoilValue(fontSizeState)
const fontFamily = useRecoilValue(fontFamilyState)
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const angleUnit = useRecoilValue(showAngleUnitSelector)
const roofSizeSet = useRecoilValue(basicSettingState).roofSizeSet
const globalPitch = useRecoilValue(globalPitchState)
const lengthText = useRecoilValue(fontSelector('lengthText'))
const { changeCorridorDimensionText } = useText()
const addLine = (points = [], options) => {
const line = new QLine(points, {
...options,
fontSize: lengthText.fontSize.value,
fontFamily: lengthText.fontFamily.value,
})
if (line.length < 1) {
return null
}
canvas?.add(line)
return line
}
const hideLine = (line) => {
line.set({
visible: false,
})
const obj = canvas?.getObjects().find((obj) => obj.parentId === line.id)
if (obj) {
obj.set({
visible: false,
})
}
canvas?.renderAll()
}
const showLine = (line) => {
line.set({
visible: true,
})
canvas
?.getObjects()
?.find((obj) => obj.parentId === line.id)
?.set({
visible: true,
})
canvas?.renderAll()
}
const removeLine = (line) => {
removeLineText(line)
canvas?.remove(line)
canvas?.renderAll()
}
const removeLineText = (line) => {
canvas?.remove(canvas?.getObjects().find((obj) => obj.parent === line))
}
const getLengthByLine = (line) => {
const scaleX = line.scaleX
const scaleY = line.scaleY
const x1 = line.left
const y1 = line.top
const x2 = line.left + line.width * scaleX
const y2 = line.top + line.height * scaleY
const dx = x2 - x1
const dy = y2 - y1
return Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10
}
const addPitchText = (line) => {
removePitchText(line)
const { startPoint, endPoint, direction, attributes } = line
const { offset, onlyOffset = false } = attributes
if (offset === 0) {
return
}
let left, top
const textStr = `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}`
// currentAngleType === ANGLE_TYPE.SLOPE
// ? `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${!onlyOffset && attributes.pitch ? '-∠' + attributes.pitch + angleUnit : ''}`
// : `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${!onlyOffset && attributes.pitch ? '-∠' + getDegreeByChon(attributes.pitch) + angleUnit : ''}`
if (direction === 'top') {
left = (startPoint.x + endPoint.x) / 2
top = (startPoint.y + endPoint.y) / 2 - 50
} else if (direction === 'bottom') {
left = (startPoint.x + endPoint.x) / 2
top = (startPoint.y + endPoint.y) / 2 - 50
} else if (direction === 'left') {
left = (startPoint.x + endPoint.x) / 2 + 50
top = (startPoint.y + endPoint.y) / 2 - 30
} else if (direction === 'right') {
left = (startPoint.x + endPoint.x) / 2 + 50
top = (startPoint.y + endPoint.y) / 2 - 30
}
if (!attributes.pitch) {
return
}
const text = new fabric.Text(`${textStr}`, {
left,
top,
fontSize: 20,
originText: `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}`,
fill: 'black',
name: 'pitchText',
parentId: line.id,
pitch: attributes.pitch,
onlyOffset,
})
canvas.add(text)
}
const removePitchText = (line) => {
const { id } = line
const pitchText = canvas.getObjects().filter((obj) => obj.name === 'pitchText' && obj.parentId === id)
// 기존 pitchText가 있으면 삭제
if (pitchText.length > 0) {
canvas.remove(pitchText)
}
}
const addPitchTextsByOuterLines = () => {
canvas
.getObjects()
.filter((obj) => obj.name === 'outerLine')
.forEach((line) => {
addPitchText(line)
})
}
/**
* 복도치수, 실제치수에 따라 actualSize를 설정한다.
* @param line
* @param direction polygon의 방향
* @param pitch
*/
const setActualSize = (line, direction, pitch = globalPitch) => {
const { x1, y1, x2, y2 } = line
const isHorizontal = y1 === y2
const isVertical = x1 === x2
const isDiagonal = !isHorizontal && !isVertical
const lineLength = line.getLength()
line.attributes = { ...line.attributes, planeSize: line.getLength(), actualSize: line.getLength() }
if (+roofSizeSet === 1) {
if (direction === 'south' || direction === 'north') {
if (isVertical) {
line.attributes = {
...line.attributes,
actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)),
}
} else if (isDiagonal) {
const yLength = Math.abs(y2 - y1) * 10
const h = yLength * Math.tan(getDegreeByChon(pitch) * (Math.PI / 180))
const actualSize = Math.sqrt(h ** 2 + lineLength ** 2)
line.attributes = { ...line.attributes, actualSize: actualSize }
}
} else if (direction === 'west' || direction === 'east') {
if (isHorizontal) {
line.attributes = {
...line.attributes,
actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)),
}
} else if (isDiagonal) {
const xLength = Math.abs(x2 - x1) * 10
const h = xLength * Math.tan(getDegreeByChon(pitch) * (Math.PI / 180))
const actualSize = Math.sqrt(h ** 2 + lineLength ** 2)
line.attributes = { ...line.attributes, actualSize: actualSize }
}
}
}
line.attributes = { ...line.attributes, actualSize: Number(line.attributes.actualSize.toFixed(0)) }
}
return {
addLine,
removeLine,
hideLine,
showLine,
addPitchText,
removePitchText,
addPitchTextsByOuterLines,
getLengthByLine,
setActualSize,
}
}