980 lines
38 KiB
JavaScript
980 lines
38 KiB
JavaScript
import { useRecoilValue } from 'recoil'
|
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
|
import { usePopup } from '@/hooks/usePopup'
|
|
import { useMessage } from '@/hooks/useMessage'
|
|
import { useEffect, useRef, useState } from 'react'
|
|
import { useEvent } from '@/hooks/useEvent'
|
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
|
import { useSwal } from '@/hooks/useSwal'
|
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
|
import { getDegreeByChon } from '@/util/canvas-util'
|
|
|
|
//동선이동 형 올림 내림
|
|
export function useMovementSetting(id) {
|
|
const TYPE = {
|
|
FLOW_LINE: 'flowLine', // 동선이동
|
|
UP_DOWN: 'updown', //형 올림내림
|
|
}
|
|
const canvas = useRecoilValue(canvasState)
|
|
const { initEvent, addCanvasMouseEventListener } = useEvent()
|
|
// const { initEvent, addCanvasMouseEventListener } = useContext(EventContext)
|
|
const { closePopup } = usePopup()
|
|
const { getMessage } = useMessage()
|
|
const currentObject = useRecoilValue(currentObjectState)
|
|
const selectedObject = useRef(null)
|
|
const buttonType = [
|
|
{ id: 1, name: getMessage('modal.movement.flow.line.move'), type: TYPE.FLOW_LINE },
|
|
{ id: 2, name: getMessage('modal.movement.flow.line.updown'), type: TYPE.UP_DOWN },
|
|
]
|
|
const [type, setType] = useState(TYPE.FLOW_LINE)
|
|
const typeRef = useRef(type)
|
|
const { swalFire } = useSwal()
|
|
|
|
const FLOW_LINE_REF = {
|
|
FILLED_INPUT_REF: useRef(null),
|
|
DOWN_LEFT_RADIO_REF: useRef(null),
|
|
UP_RIGHT_RADIO_REF: useRef(null),
|
|
}
|
|
|
|
const UP_DOWN_REF = {
|
|
FILLED_INPUT_REF: useRef(null),
|
|
UP_RADIO_REF: useRef(null),
|
|
DOWN_RADIO_REF: useRef(null),
|
|
}
|
|
|
|
useEffect(() => {
|
|
typeRef.current = type
|
|
canvas.getObjects().forEach((obj) => {
|
|
obj.set({ selectable: false })
|
|
})
|
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // 기존 wallLine의 visible false
|
|
roofs.forEach((roof) => {
|
|
roof.set({ selectable: false })
|
|
roof.set({ strokeWidth: 1 })
|
|
roof.set({ stroke: '#000000' })
|
|
roof.innerLines.forEach((line) => {
|
|
line.bringToFront()
|
|
line.set({ selectable: false })
|
|
line.set({ strokeWidth: 1 })
|
|
line.set({ stroke: '#000000' })
|
|
})
|
|
roof.separatePolygon?.forEach((polygon) => {
|
|
polygon.bringToFront()
|
|
polygon.set({ selectable: false })
|
|
polygon.set({ strokeWidth: 1 })
|
|
polygon.set({ stroke: '#000000' })
|
|
})
|
|
})
|
|
if (type === TYPE.FLOW_LINE) {
|
|
roofs.forEach((roof) => {
|
|
roof.innerLines.forEach((line) => {
|
|
if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
|
|
line.bringToFront()
|
|
line.set({ visible: true })
|
|
line.set({ selectable: true })
|
|
line.set({ strokeWidth: 4 })
|
|
line.set({ stroke: '#1083E3' })
|
|
}
|
|
})
|
|
})
|
|
} else if (type === TYPE.UP_DOWN) {
|
|
const wallLine = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 outerLine의 selectable true
|
|
wallLine.forEach((line) => {
|
|
line.bringToFront()
|
|
line.set({ selectable: true })
|
|
})
|
|
}
|
|
canvas.renderAll()
|
|
}, [type])
|
|
|
|
useEffect(() => {
|
|
canvas.renderAll()
|
|
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
|
|
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
|
|
return () => {
|
|
initEvent()
|
|
|
|
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
|
wallLines.forEach((line) => {
|
|
line.set({ visible: true })
|
|
})
|
|
|
|
const wallLine = canvas.getObjects().filter((obj) => obj.name === 'wallLine') // 기존 outerLine의 selectable true
|
|
wallLine.forEach((line) => {
|
|
let wallStroke, wallStrokeWidth
|
|
switch (line.attributes.type) {
|
|
case LINE_TYPE.WALLLINE.EAVES:
|
|
wallStroke = '#45CD7D'
|
|
wallStrokeWidth = 4
|
|
break
|
|
case LINE_TYPE.WALLLINE.HIPANDGABLE:
|
|
wallStroke = '#45CD7D'
|
|
wallStrokeWidth = 4
|
|
break
|
|
case LINE_TYPE.WALLLINE.GABLE:
|
|
wallStroke = '#3FBAE6'
|
|
wallStrokeWidth = 4
|
|
break
|
|
case LINE_TYPE.WALLLINE.JERKINHEAD:
|
|
wallStroke = '#3FBAE6'
|
|
wallStrokeWidth = 4
|
|
break
|
|
case LINE_TYPE.WALLLINE.SHED:
|
|
wallStroke = '#000000'
|
|
wallStrokeWidth = 4
|
|
break
|
|
case LINE_TYPE.WALLLINE.WALL:
|
|
wallStroke = '#000000'
|
|
wallStrokeWidth = 4
|
|
break
|
|
}
|
|
line.set({ selectable: false, stroke: wallStroke, strokeWidth: wallStrokeWidth })
|
|
})
|
|
|
|
canvas.renderAll()
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
console.log('selectedObject.current : ', selectedObject.current)
|
|
if (selectedObject.current != null) {
|
|
let wallStroke
|
|
switch (selectedObject.current.attributes.type) {
|
|
case LINE_TYPE.WALLLINE.EAVES:
|
|
wallStroke = '#45CD7D'
|
|
break
|
|
case LINE_TYPE.WALLLINE.HIPANDGABLE:
|
|
wallStroke = '#45CD7D'
|
|
break
|
|
case LINE_TYPE.WALLLINE.GABLE:
|
|
wallStroke = '#3FBAE6'
|
|
break
|
|
case LINE_TYPE.WALLLINE.JERKINHEAD:
|
|
wallStroke = '#3FBAE6'
|
|
break
|
|
case LINE_TYPE.WALLLINE.SHED:
|
|
wallStroke = '#000000'
|
|
break
|
|
case LINE_TYPE.WALLLINE.WALL:
|
|
wallStroke = '#000000'
|
|
break
|
|
}
|
|
selectedObject.current.set({ stroke: wallStroke })
|
|
selectedObject.current.bringToFront()
|
|
}
|
|
selectedObject.current = null
|
|
if (!currentObject) {
|
|
return
|
|
}
|
|
|
|
clearRef()
|
|
selectedObject.current = currentObject
|
|
if (currentObject.name === 'wallLine') {
|
|
currentObject.set({ stroke: '#EA10AC' })
|
|
currentObject.bringToFront()
|
|
}
|
|
canvas.renderAll()
|
|
}, [currentObject])
|
|
|
|
const clearRef = () => {
|
|
if (type === TYPE.FLOW_LINE) {
|
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = ''
|
|
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
|
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = false
|
|
}
|
|
if (type === TYPE.UP_DOWN) {
|
|
UP_DOWN_REF.FILLED_INPUT_REF.current.value = ''
|
|
UP_DOWN_REF.UP_RADIO_REF.current.checked = true
|
|
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = false
|
|
}
|
|
}
|
|
|
|
const mouseDownEvent = (e) => {
|
|
if (typeRef.current === TYPE.FLOW_LINE) {
|
|
saveFlowLine(e)
|
|
} else {
|
|
saveUpDownLine(e)
|
|
}
|
|
}
|
|
|
|
const mouseMoveEvent = (e) => {
|
|
if (typeRef.current === TYPE.FLOW_LINE) {
|
|
flowLineMoveEvent(e)
|
|
} else {
|
|
updownMoveEvent(e)
|
|
}
|
|
}
|
|
|
|
function edgesIntersection(edgeA, edgeB) {
|
|
const den =
|
|
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex2.x - edgeA.vertex1.x) -
|
|
(edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex2.y - edgeA.vertex1.y)
|
|
|
|
if (den === 0) {
|
|
return null // lines are parallel or coincident
|
|
}
|
|
|
|
const ua =
|
|
((edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) -
|
|
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) /
|
|
den
|
|
|
|
const ub =
|
|
((edgeA.vertex2.x - edgeA.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) -
|
|
(edgeA.vertex2.y - edgeA.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) /
|
|
den
|
|
|
|
// Edges are not intersecting but the lines defined by them are
|
|
const isIntersectionOutside = ua < 0 || ub < 0 || ua > 1 || ub > 1
|
|
|
|
return {
|
|
x: edgeA.vertex1.x + ua * (edgeA.vertex2.x - edgeA.vertex1.x),
|
|
y: edgeA.vertex1.y + ua * (edgeA.vertex2.y - edgeA.vertex1.y),
|
|
isIntersectionOutside,
|
|
}
|
|
}
|
|
|
|
//동선 이동 마우스 클릭 이벤트
|
|
const saveFlowLine = (e) => {
|
|
const target = selectedObject.current
|
|
if (!target) {
|
|
return
|
|
}
|
|
|
|
let newPoint = []
|
|
if (Math.sign(target.x1 - target.x2) !== 0) {
|
|
const sign = FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked ? 1 : -1
|
|
newPoint = [
|
|
target.x1,
|
|
target.y1 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
|
target.x2,
|
|
target.y2 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
|
]
|
|
} else {
|
|
const sign = FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked ? -1 : 1
|
|
newPoint = [
|
|
target.x1 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
|
target.y1,
|
|
target.x2 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
|
target.y2,
|
|
]
|
|
}
|
|
newPoint = newPoint.map((point) => Math.round(point * 10) / 10)
|
|
const cloned = new fabric.Line(newPoint, {})
|
|
let currentObject = selectedObject.current
|
|
const currentX1 = currentObject.x1,
|
|
currentY1 = currentObject.y1,
|
|
currentX2 = currentObject.x2,
|
|
currentY2 = currentObject.y2
|
|
|
|
const currentMidX = (currentX1 + currentX2) / 2
|
|
const currentMidY = (currentY1 + currentY2) / 2
|
|
const clonedMidX = (cloned.x1 + cloned.x2) / 2
|
|
const clonedMidY = (cloned.y1 + cloned.y2) / 2
|
|
|
|
const roof = canvas.getObjects().find((obj) => obj.id === currentObject.attributes.roofId)
|
|
let isOutside = false
|
|
roof.lines.forEach((line) => {
|
|
const intersection = edgesIntersection(
|
|
{ vertex1: { x: currentMidX, y: currentMidY }, vertex2: { x: clonedMidX, y: clonedMidY } },
|
|
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
|
|
)
|
|
if (intersection && !intersection.isIntersectionOutside) {
|
|
isOutside = true
|
|
}
|
|
})
|
|
if (isOutside) {
|
|
swalFire({ text: getMessage('modal.movement.flow.line.move.alert'), icon: 'error' })
|
|
return
|
|
}
|
|
currentObject.set({ x1: cloned.x1, y1: cloned.y1, x2: cloned.x2, y2: cloned.y2 })
|
|
currentObject.setCoords()
|
|
const otherRidges = roof.innerLines.filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE && line.id !== currentObject.id)
|
|
const overlapRidges = otherRidges.filter((line) => {
|
|
if (currentObject.x1 === currentObject.x2 && line.x1 === line.x2 && 0 < Math.abs(currentObject.x1 - line.x1) < 1) {
|
|
if (
|
|
currentObject.y1 <= line.y1 <= currentObject.y2 ||
|
|
currentObject.y1 >= line.y1 >= currentObject.y2 ||
|
|
currentObject.y1 <= line.y2 <= currentObject.y2 ||
|
|
currentObject.y1 >= line.y2 >= currentObject.y2
|
|
) {
|
|
return true
|
|
}
|
|
}
|
|
if (currentObject.y1 === currentObject.y2 && line.y1 === line.y2 && 0 < Math.abs(currentObject.y1 - line.y1) < 1) {
|
|
if (
|
|
currentObject.x1 <= line.x1 <= currentObject.x2 ||
|
|
currentObject.x1 >= line.x1 >= currentObject.x2 ||
|
|
currentObject.x1 <= line.x2 <= currentObject.x2 ||
|
|
currentObject.x1 >= line.x2 >= currentObject.x2
|
|
) {
|
|
return true
|
|
}
|
|
}
|
|
})
|
|
if (overlapRidges.length > 0) {
|
|
const minX = Math.min(...overlapRidges.flatMap((line) => [line.x1, line.x2]), currentObject.x1, currentObject.x2)
|
|
const maxX = Math.max(...overlapRidges.flatMap((line) => [line.x1, line.x2]), currentObject.x1, currentObject.x2)
|
|
const minY = Math.min(...overlapRidges.flatMap((line) => [line.y1, line.y2]), currentObject.y1, currentObject.y2)
|
|
const maxY = Math.max(...overlapRidges.flatMap((line) => [line.y1, line.y2]), currentObject.y1, currentObject.y2)
|
|
const newRidge = new fabric.Line([minX, minY, maxX, maxY], {
|
|
name: LINE_TYPE.SUBLINE.RIDGE,
|
|
selectable: true,
|
|
stroke: '#1083E3',
|
|
strokeWidth: 4,
|
|
attributes: { roofId: roof.id, currentRoofId: currentObject.attributes.currentRoofId },
|
|
})
|
|
|
|
overlapRidges.forEach((line) =>
|
|
line.attributes.currentRoofId.forEach((id) => {
|
|
if (!newRidge.attributes.currentRoofId.includes(id)) {
|
|
newRidge.attributes.currentRoofId.push(id)
|
|
}
|
|
}),
|
|
)
|
|
canvas.add(newRidge)
|
|
newRidge.bringToFront()
|
|
roof.innerLines.push(newRidge)
|
|
|
|
canvas.remove(currentObject)
|
|
roof.innerLines.forEach((innerLine, index) => {
|
|
if (innerLine.id === currentObject.id) {
|
|
roof.innerLines.splice(index, 1)
|
|
}
|
|
})
|
|
|
|
overlapRidges.forEach((line) => {
|
|
canvas.remove(line)
|
|
roof.innerLines.forEach((innerLine, index) => {
|
|
if (innerLine.id === line.id) {
|
|
roof.innerLines.splice(index, 1)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
if (roof.separatePolygon.length > 0) {
|
|
redrawSeparatePolygon(roof)
|
|
} else {
|
|
roof.innerLines
|
|
.filter((line) => currentObject !== line)
|
|
.filter(
|
|
(line) =>
|
|
(line.x1 === currentX1 && line.y1 === currentY1) ||
|
|
(line.x2 === currentX1 && line.y2 === currentY1) ||
|
|
(line.x1 === currentX2 && line.y1 === currentY2) ||
|
|
(line.x2 === currentX2 && line.y2 === currentY2),
|
|
)
|
|
.forEach((line) => {
|
|
const lineDegree = 90 - Math.asin(line.attributes.planeSize / line.attributes.actualSize) * (180 / Math.PI)
|
|
if (line.x1 === currentX1 && line.y1 === currentY1) {
|
|
line.set({ x1: newPoint[0], y1: newPoint[1] })
|
|
} else if (line.x2 === currentX1 && line.y2 === currentY1) {
|
|
line.set({ x2: newPoint[0], y2: newPoint[1] })
|
|
} else if (line.x1 === currentX2 && line.y1 === currentY2) {
|
|
line.set({ x1: newPoint[2], y1: newPoint[3] })
|
|
} else if (line.x2 === currentX2 && line.y2 === currentY2) {
|
|
line.set({ x2: newPoint[2], y2: newPoint[3] })
|
|
}
|
|
line.setCoords()
|
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
|
line.attributes.actualSize = Math.round(
|
|
Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(line.attributes.planeSize * Math.tan(lineDegree * (Math.PI / 180)), 2)),
|
|
)
|
|
})
|
|
}
|
|
|
|
currentObject.set({ x1: cloned.x1, y1: cloned.y1, x2: cloned.x2, y2: cloned.y2 })
|
|
currentObject.setCoords()
|
|
|
|
canvas.renderAll()
|
|
canvas.discardActiveObject()
|
|
|
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = ''
|
|
}
|
|
|
|
//형 올림내림 마우스 클릭 이벤트
|
|
const saveUpDownLine = (e) => {
|
|
const target = selectedObject.current
|
|
if (!target) {
|
|
return
|
|
}
|
|
|
|
const roof = canvas.getObjects().find((obj) => obj.id === target.attributes.roofId)
|
|
const wallLines = roof.wall.lines
|
|
const roofLines = roof.lines
|
|
const currentWall = wallLines.find((line) => line.id === target.attributes.currentWall)
|
|
let prevWall, nextWall
|
|
let prevEave, nextEave
|
|
|
|
wallLines.forEach((wallLine, index) => {
|
|
if (wallLine.id === currentWall.id) {
|
|
prevWall = index === 0 ? wallLines[wallLines.length - 1] : wallLines[index - 1]
|
|
nextWall = index === wallLines.length - 1 ? wallLines[0] : wallLines[index + 1]
|
|
}
|
|
})
|
|
|
|
const eaves = roofLines.filter((line) => line.attributes?.type === LINE_TYPE.WALLLINE.EAVES)
|
|
|
|
wallLines
|
|
.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
|
.forEach((eave, index) => {
|
|
if (eave.id === currentWall.id) {
|
|
prevEave = index === 0 ? eaves[eaves.length - 1] : eaves[index - 1]
|
|
nextEave = index === eaves.length - 1 ? eaves[0] : eaves[index + 1]
|
|
}
|
|
})
|
|
|
|
const currentRoof = roofLines.find((line) => line.id === target.attributes.currentRoof)
|
|
const currentRidges = roof.innerLines.filter(
|
|
(line) => line.name === LINE_TYPE.SUBLINE.RIDGE && line.attributes.currentRoof.includes(currentRoof.id),
|
|
)
|
|
/*const prevWallRidges = roof.innerLines.filter(
|
|
(line) => line.name === LINE_TYPE.SUBLINE.RIDGE && line.attributes.currentRoof.includes(prevEave.id),
|
|
)
|
|
const nextWallRidges = roof.innerLines.filter(
|
|
(line) => line.name === LINE_TYPE.SUBLINE.RIDGE && line.attributes.currentRoof.includes(nextEave.id),
|
|
)
|
|
//라인 확인 작업
|
|
/!* const roofLine = new fabric.Line([currentRoof.x1, currentRoof.y1, currentRoof.x2, currentRoof.y2], {
|
|
stroke: 'red',
|
|
strokeWidth: 5,
|
|
selectable: false,
|
|
})
|
|
canvas.add(roofLine)
|
|
|
|
const prevEaves = new fabric.Line([prevEave.x1, prevEave.y1, prevEave.x2, prevEave.y2], {
|
|
stroke: 'yellow',
|
|
strokeWidth: 5,
|
|
selectable: false,
|
|
})
|
|
canvas.add(prevEaves)
|
|
currentRidges.forEach((ridge) => ridge.set({ stroke: 'purple', strokeWidth: 5 }))
|
|
prevWallRidges.forEach((ridge) => ridge.set({ stroke: 'yellow', strokeWidth: 5 }))
|
|
nextWallRidges.forEach((ridge) => ridge.set({ stroke: 'green', strokeWidth: 5 }))
|
|
canvas.renderAll()*!/*/
|
|
|
|
console.log(
|
|
'UP/DOWN',
|
|
UP_DOWN_REF.UP_RADIO_REF.current.checked,
|
|
UP_DOWN_REF.DOWN_RADIO_REF.current.checked,
|
|
UP_DOWN_REF.FILLED_INPUT_REF.current.value,
|
|
)
|
|
|
|
let compareLine
|
|
if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) {
|
|
const currentDiff = currentRidges[0].x1 - currentRoof.x1
|
|
const prevDiff = prevEave.x1 - currentRoof.x1
|
|
const nextDiff = nextEave.x1 - currentRoof.x1
|
|
|
|
console.log('currentDiff', Math.sign(currentDiff), currentDiff)
|
|
|
|
if (UP_DOWN_REF.UP_RADIO_REF.current.checked) {
|
|
if (Math.sign(currentDiff) === 1) {
|
|
} else {
|
|
if (Math.sign(prevDiff) === 1 && Math.sign(nextDiff) === 1) {
|
|
} else {
|
|
}
|
|
}
|
|
} else {
|
|
if (Math.sign(currentDiff) === -1) {
|
|
} else {
|
|
if (Math.sign(prevDiff) === -1 && Math.sign(nextDiff) === -1) {
|
|
} else {
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const currentDiff = currentRidges[0].y1 - currentRoof.y1
|
|
const prevDiff = prevEave.y1 - currentRoof.y1
|
|
const nextDiff = nextEave.y1 - currentRoof.y1
|
|
|
|
if (UP_DOWN_REF.UP_RADIO_REF.current.checked) {
|
|
if (Math.sign(currentDiff) === 1) {
|
|
} else {
|
|
if (Math.sign(prevDiff) === 1 && Math.sign(nextDiff) === 1) {
|
|
} else {
|
|
}
|
|
}
|
|
} else {
|
|
if (Math.sign(currentDiff) === -1) {
|
|
} else {
|
|
if (Math.sign(prevDiff) === -1 && Math.sign(nextDiff) === -1) {
|
|
} else {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//확인
|
|
/*const compareRoofLine = new fabric.Line([compareRoof.x1, compareRoof.y1, compareRoof.x2, compareRoof.y2], {
|
|
stroke: 'red',
|
|
strokeWidth: 5,
|
|
selectable: false,
|
|
})
|
|
canvas.add(compareRoofLine)
|
|
canvas.renderAll()*/
|
|
}
|
|
|
|
const redrawSeparatePolygon = (roof) => {
|
|
roof.separatePolygon.forEach((polygon) => canvas.remove(polygon))
|
|
roof.separatePolygon = []
|
|
const roofLines = roof.lines
|
|
const wallLines = roof.wall.lines
|
|
const eaves = []
|
|
roofLines.forEach((currentRoof, index) => {
|
|
if (currentRoof.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
|
eaves.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize })
|
|
}
|
|
})
|
|
const ridges = roof.innerLines.filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE)
|
|
eaves.sort((a, b) => a.length - b.length)
|
|
|
|
const ridgeCount = eaves.length - 1
|
|
console.log('ridgeCount', ridgeCount, 'ridges', ridges.length)
|
|
|
|
const duplicatedEaves = []
|
|
ridges.forEach((ridge) => {
|
|
const positiveLines = []
|
|
const negativeLines = []
|
|
ridge.attributes.currentRoof.forEach((id) => {
|
|
console.log('id : ', id)
|
|
const eave = roofLines.find((obj) => obj.id === id)
|
|
console.log('roof : ', eave)
|
|
if (ridge.x1 === ridge.x2) {
|
|
if (eave.y1 < eave.y2) {
|
|
positiveLines.push(eave)
|
|
} else {
|
|
negativeLines.push(eave)
|
|
}
|
|
} else {
|
|
if (eave.x1 < eave.x2) {
|
|
positiveLines.push(eave)
|
|
} else {
|
|
negativeLines.push(eave)
|
|
}
|
|
}
|
|
})
|
|
if (positiveLines.length > 1) {
|
|
duplicatedEaves.push(positiveLines)
|
|
}
|
|
if (negativeLines.length > 1) {
|
|
duplicatedEaves.push(negativeLines)
|
|
}
|
|
})
|
|
console.log('duplicatedEaves', duplicatedEaves)
|
|
|
|
duplicatedEaves.forEach((duplicatedEave) => {
|
|
duplicatedEave.forEach((eave) => {
|
|
const index = eaves.findIndex((item) => item.roof.id === eave.id)
|
|
eaves.splice(index, 1)
|
|
})
|
|
})
|
|
|
|
// if (ridgeCount === ridges.length) {
|
|
eaves.forEach((eave, i) => {
|
|
const index = eave.index,
|
|
currentRoof = eave.roof
|
|
const currentWall = wallLines[index]
|
|
const currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoof.includes(eave.roof.id))
|
|
let points = []
|
|
const signX = Math.sign(currentRoof.x1 - currentRoof.x2)
|
|
let currentX1 = currentRoof.x1,
|
|
currentY1 = currentRoof.y1,
|
|
currentX2 = currentRoof.x2,
|
|
currentY2 = currentRoof.y2
|
|
let changeX1 = [Math.min(currentRoof.x1, currentRoof.x2), Math.min(currentRoof.x1, currentRoof.x2)],
|
|
changeY1 = [Math.min(currentRoof.y1, currentRoof.y2), Math.min(currentRoof.y1, currentRoof.y2)],
|
|
changeX2 = [Math.max(currentRoof.x2, currentRoof.x1), Math.max(currentRoof.x2, currentRoof.x1)],
|
|
changeY2 = [Math.max(currentRoof.y2, currentRoof.y1), Math.max(currentRoof.y2, currentRoof.y1)]
|
|
|
|
if (signX === 0) {
|
|
currentY1 = Math.min(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
|
changeY1[1] = currentY1
|
|
currentY2 = Math.max(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
|
changeY2[1] = currentY2
|
|
} else {
|
|
currentX1 = Math.min(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
|
changeX1[1] = currentX1
|
|
currentX2 = Math.max(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
|
changeX2[1] = currentX2
|
|
}
|
|
points.push({ x: currentX1, y: currentY1 }, { x: currentX2, y: currentY2 })
|
|
|
|
currentRidges.forEach((ridge) => {
|
|
let ridgeX1 = ridge.x1,
|
|
ridgeY1 = ridge.y1,
|
|
ridgeX2 = ridge.x2,
|
|
ridgeY2 = ridge.y2
|
|
if (signX === 0) {
|
|
ridgeY1 = Math.min(ridge.y1, ridge.y2)
|
|
ridgeY2 = Math.max(ridge.y1, ridge.y2)
|
|
} else {
|
|
ridgeX1 = Math.min(ridge.x1, ridge.x2)
|
|
ridgeX2 = Math.max(ridge.x1, ridge.x2)
|
|
}
|
|
points.push({ x: ridgeX1, y: ridgeY1 }, { x: ridgeX2, y: ridgeY2 })
|
|
})
|
|
|
|
points.forEach((point) => {
|
|
if (point.x === changeX1[0] && changeX1[0] !== changeX1[1]) {
|
|
point.x = changeX1[1]
|
|
}
|
|
if (point.x === changeX2[0] && changeX2[0] !== changeX2[1]) {
|
|
point.x = changeX2[1]
|
|
}
|
|
if (point.y === changeY1[0] && changeY1[0] !== changeY1[1]) {
|
|
point.y = changeY1[1]
|
|
}
|
|
if (point.y === changeY2[0] && changeY2[0] !== changeY2[1]) {
|
|
point.y = changeY2[1]
|
|
}
|
|
})
|
|
//중복된 point 제거
|
|
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
|
//point 정렬 (가장 좌측, 최상단의 점을 기준으로 삼는다.)
|
|
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 = []
|
|
sortedPoints.push(startPoint)
|
|
|
|
points.forEach((p, index) => {
|
|
if (index === 0) {
|
|
//시작점 다음 점 찾기, y좌표가 startPoint.y 보다 큰 점 중 x좌표가 가까운 점
|
|
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
|
const nextPoint = underStartPoint
|
|
.filter((point) => point.x === startPoint.x)
|
|
.reduce((prev, current) => {
|
|
if (prev === undefined) {
|
|
return current
|
|
}
|
|
return Math.abs(prev.y - startPoint.y) < Math.abs(current.y - startPoint.y) ? prev : current
|
|
}, undefined)
|
|
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
|
|
}, undefined)
|
|
sortedPoints.push(nextPoint)
|
|
}
|
|
} else {
|
|
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
|
console.log('lastPoint', lastPoint)
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
if (sortedPoints.length > 0) {
|
|
const roofPolygon = new QPolygon(sortedPoints, {
|
|
fill: 'transparent',
|
|
stroke: '#000000',
|
|
strokeWidth: 1,
|
|
selectable: false,
|
|
fontSize: roof.fontSize,
|
|
name: 'roofPolygon',
|
|
attributes: {
|
|
roofId: roof.id,
|
|
currentRoofId: currentRoof.id,
|
|
pitch: currentRoof.attributes.pitch,
|
|
degree: currentRoof.attributes.degree,
|
|
direction: currentRoof.direction,
|
|
},
|
|
})
|
|
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
|
//지붕 각도에 따른 실측치 조정
|
|
roofPolygon.lines.forEach((line) => {
|
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
|
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
|
|
|
|
if (currentDegree > 0 && slope(line) !== slope(currentRoof)) {
|
|
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
|
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
|
|
} else {
|
|
line.attributes.actualSize = line.attributes.planeSize
|
|
}
|
|
})
|
|
roof.separatePolygon.push(roofPolygon)
|
|
canvas.add(roofPolygon)
|
|
canvas.renderAll()
|
|
}
|
|
})
|
|
|
|
duplicatedEaves.forEach((duplicatedEave) => {
|
|
const currentRoof = duplicatedEave[0]
|
|
let points = []
|
|
duplicatedEave.forEach((eave) => {
|
|
points.push({ x: eave.x1, y: eave.y1 }, { x: eave.x2, y: eave.y2 })
|
|
const currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoof.includes(eave.id))
|
|
currentRidges.forEach((ridge) => {
|
|
points.push({ x: ridge.x1, y: ridge.y1 }, { x: ridge.x2, y: ridge.y2 })
|
|
})
|
|
})
|
|
console.log('points', points)
|
|
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
|
//point 정렬 (가장 좌측, 최상단의 점을 기준으로 삼는다.)
|
|
|
|
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 = []
|
|
sortedPoints.push(startPoint)
|
|
|
|
points.forEach((p, index) => {
|
|
if (index === 0) {
|
|
//시작점 다음 점 찾기, y좌표가 startPoint.y 보다 큰 점 중 x좌표가 가까운 점
|
|
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
|
const nextPoint = underStartPoint
|
|
.filter((point) => point.x === startPoint.x)
|
|
.reduce((prev, current) => {
|
|
if (prev === undefined) {
|
|
return current
|
|
}
|
|
return Math.abs(prev.y - startPoint.y) < Math.abs(current.y - startPoint.y) ? prev : current
|
|
}, undefined)
|
|
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
|
|
}, undefined)
|
|
sortedPoints.push(nextPoint)
|
|
}
|
|
} else {
|
|
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
|
console.log('lastPoint', lastPoint)
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
if (sortedPoints.length > 0) {
|
|
const roofPolygon = new QPolygon(sortedPoints, {
|
|
fill: 'transparent',
|
|
stroke: '#000000',
|
|
strokeWidth: 1,
|
|
selectable: false,
|
|
fontSize: roof.fontSize,
|
|
name: 'roofPolygon',
|
|
attributes: {
|
|
roofId: roof.id,
|
|
currentRoofId: currentRoof.id,
|
|
pitch: currentRoof.attributes.pitch,
|
|
degree: currentRoof.attributes.degree,
|
|
direction: currentRoof.direction,
|
|
},
|
|
})
|
|
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
|
//지붕 각도에 따른 실측치 조정
|
|
roofPolygon.lines.forEach((line) => {
|
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
|
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
|
|
|
|
if (currentDegree > 0 && slope(line) !== slope(currentRoof)) {
|
|
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
|
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
|
|
} else {
|
|
line.attributes.actualSize = line.attributes.planeSize
|
|
}
|
|
})
|
|
roof.separatePolygon.push(roofPolygon)
|
|
canvas.add(roofPolygon)
|
|
canvas.renderAll()
|
|
}
|
|
})
|
|
console.log('roof.separatePolygon : ', roof.separatePolygon)
|
|
|
|
ridges.forEach((ridge) => ridge.bringToFront())
|
|
console.log('ridges : ', ridges)
|
|
}
|
|
|
|
const flowLineMoveEvent = (e) => {
|
|
const target = canvas.getActiveObject()
|
|
if (!target) {
|
|
return
|
|
}
|
|
const { top: targetTop, left: targetLeft } = target
|
|
const currentX = canvas.getPointer(e.e).x
|
|
const currentY = Math.floor(canvas.getPointer(e.e).y)
|
|
|
|
if (Math.sign(target.x1 - target.x2) !== 0) {
|
|
if (targetTop > currentY) {
|
|
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
|
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(targetTop - currentY))) / 10000).toFixed(5) * 100000)
|
|
} else {
|
|
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(targetTop - currentY))) / 10000).toFixed(5) * 100000)
|
|
}
|
|
} else {
|
|
if (targetLeft < currentX) {
|
|
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
|
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(currentX - targetLeft))) / 10000).toFixed(5) * 100000)
|
|
} else {
|
|
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(currentX - targetLeft))) / 10000).toFixed(5) * 100000)
|
|
}
|
|
}
|
|
|
|
canvas?.renderAll()
|
|
}
|
|
|
|
const updownMoveEvent = (e) => {
|
|
const target = canvas.getActiveObject()
|
|
if (!target) {
|
|
return
|
|
}
|
|
const { top: targetTop, left: targetLeft } = target
|
|
const currentX = canvas.getPointer(e.e).x
|
|
const currentY = Math.floor(canvas.getPointer(e.e).y)
|
|
|
|
if (Math.sign(target.x1 - target.x2) !== 0) {
|
|
if (targetTop > currentY) {
|
|
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = true
|
|
UP_DOWN_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetTop - currentY)) / 10000).toFixed(5) * 100000)
|
|
} else {
|
|
UP_DOWN_REF.UP_RADIO_REF.current.checked = true
|
|
UP_DOWN_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetTop - currentY)) / 10000).toFixed(5) * 100000)
|
|
}
|
|
} else {
|
|
if (targetLeft > currentX) {
|
|
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = true
|
|
UP_DOWN_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetLeft - currentX)) / 10000).toFixed(5) * 100000)
|
|
} else {
|
|
UP_DOWN_REF.UP_RADIO_REF.current.checked = true
|
|
UP_DOWN_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(targetLeft - currentX)) / 10000).toFixed(5) * 100000)
|
|
}
|
|
}
|
|
|
|
canvas?.renderAll()
|
|
}
|
|
|
|
const handleSave = () => {
|
|
if (type === TYPE.FLOW_LINE) {
|
|
saveFlowLine()
|
|
} else {
|
|
saveUpDownLine()
|
|
}
|
|
}
|
|
|
|
return {
|
|
TYPE,
|
|
closePopup,
|
|
buttonType,
|
|
type,
|
|
setType,
|
|
FLOW_LINE_REF,
|
|
UP_DOWN_REF,
|
|
handleSave,
|
|
}
|
|
}
|