육지붕 수동 모듈 설치 작업중
This commit is contained in:
parent
cf080c24cf
commit
fb577316a0
@ -93,7 +93,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
)}
|
||||
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet === 3 && (
|
||||
<>
|
||||
<button className="btn-frame modal mr5" onClick={manualFlatroofModuleSetup}>
|
||||
<button className="btn-frame modal mr5" onClick={() => manualFlatroofModuleSetup(placementFlatRef)}>
|
||||
{getMessage('modal.module.basic.setting.passivity.placement')}
|
||||
</button>
|
||||
<button className="btn-frame modal act" onClick={() => autoFlatroofModuleSetup(placementFlatRef)}>
|
||||
|
||||
@ -1,16 +1,26 @@
|
||||
import { forwardRef, useState, useEffect } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||
import { compasDegAtom } from '@/store/orientationAtom'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
|
||||
const PitchPlacement = forwardRef((props, refs) => {
|
||||
const { getMessage } = useMessage()
|
||||
const [setupLocation, setSetupLocation] = useState('south')
|
||||
const { makeModuleInstArea } = useModuleBasicSetting()
|
||||
const compasDeg = useRecoilValue(compasDegAtom)
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
|
||||
useEffect(() => {
|
||||
makeModuleInstArea()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
handleChangeSetupLocation()
|
||||
}, [setupLocation])
|
||||
|
||||
const moduleData = {
|
||||
header: [
|
||||
{ type: 'check', name: '', prop: 'check', width: 70 },
|
||||
@ -35,8 +45,41 @@ const PitchPlacement = forwardRef((props, refs) => {
|
||||
}
|
||||
|
||||
const handleSetupLocation = (e) => {
|
||||
refs.setupLocation.current = e.target
|
||||
setSetupLocation(e.target.value)
|
||||
refs.setupLocation.current = e.target.value
|
||||
}
|
||||
|
||||
const handleChangeSetupLocation = () => {
|
||||
if (setupLocation === 'south') {
|
||||
canvas.getObjects().forEach((obj) => obj.name === 'flatExcretaLine' && canvas.remove(obj))
|
||||
return null
|
||||
} else {
|
||||
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
|
||||
moduleSetupSurfaces.forEach((surface, index) => {
|
||||
console.log(`surface ${index} : `, surface)
|
||||
|
||||
const excretaLine = surface.lines
|
||||
|
||||
excretaLine.forEach((line) => {
|
||||
line.set({
|
||||
stroke: '#642EFB',
|
||||
strokeWidth: 5,
|
||||
surfaceId: surface.surfaceId,
|
||||
name: 'flatExcretaLine',
|
||||
})
|
||||
canvas.add(line)
|
||||
|
||||
line.on('selected', () => {
|
||||
excretaLine.forEach((obj) => obj.set({ stroke: '#642EFB', isSelected: false }))
|
||||
if (!line.isSelected) {
|
||||
line.set({ stroke: 'red', isSelected: true })
|
||||
} else {
|
||||
line.set({ stroke: '#642EFB', isSelected: false })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -2,7 +2,7 @@ import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { rectToPolygon, setSurfaceShapePattern } from '@/util/canvas-util'
|
||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||
import offsetPolygon from '@/util/qpolygon-utils'
|
||||
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
@ -11,6 +11,7 @@ import * as turf from '@turf/turf'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { canvasSettingState } from '@/store/canvasAtom'
|
||||
import { compasDegAtom } from '@/store/orientationAtom'
|
||||
|
||||
export function useModuleBasicSetting() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
@ -20,6 +21,8 @@ export function useModuleBasicSetting() {
|
||||
const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useEvent()
|
||||
const { swalFire } = useSwal()
|
||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||
const compasDeg = useRecoilValue(compasDegAtom)
|
||||
|
||||
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
|
||||
let selectedModuleInstSurfaceArray = []
|
||||
|
||||
@ -1445,7 +1448,334 @@ export function useModuleBasicSetting() {
|
||||
return obj
|
||||
}
|
||||
|
||||
const manualFlatroofModuleSetup = () => {}
|
||||
const manualFlatroofModuleSetup = (placementFlatRef) => {
|
||||
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
|
||||
let applyAngle
|
||||
let flatBatchType = placementFlatRef.setupLocation.current.value
|
||||
let excretaLinesAngle = []
|
||||
|
||||
if (flatBatchType === 'south') {
|
||||
applyAngle = compasDeg
|
||||
} else {
|
||||
const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine' && obj.isSelected === true)
|
||||
excretaLines.forEach((obj) => {
|
||||
const points1 = { x: obj.x1, y: obj.y1 }
|
||||
const points2 = { x: obj.x2, y: obj.y2 }
|
||||
excretaLinesAngle.push({
|
||||
surfaceId: obj.surfaceId,
|
||||
angle: calculateAngle(points1, points2),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//calculateAngle
|
||||
|
||||
const batchObjects = canvas
|
||||
?.getObjects()
|
||||
.filter(
|
||||
(obj) =>
|
||||
obj.name === BATCH_TYPE.OPENING ||
|
||||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||
obj.name === BATCH_TYPE.PENTAGON_DORMER ||
|
||||
obj.name === BATCH_TYPE.SHADOW,
|
||||
) //도머s 객체
|
||||
|
||||
const moduleOptions = {
|
||||
fill: '#BFFD9F',
|
||||
stroke: 'black',
|
||||
strokeWidth: 0.1,
|
||||
selectable: false, // 선택 가능하게 설정
|
||||
lockMovementX: true, // X 축 이동 잠금
|
||||
lockMovementY: true, // Y 축 이동 잠금
|
||||
lockRotation: true, // 회전 잠금
|
||||
lockScalingX: true, // X 축 크기 조정 잠금
|
||||
lockScalingY: true, // Y 축 크기 조정 잠금
|
||||
opacity: 0.8,
|
||||
parentId: moduleSetupSurface.parentId,
|
||||
name: 'module',
|
||||
}
|
||||
|
||||
function getRotatedCorners(rect) {
|
||||
// 사각형의 중심점
|
||||
const center = rect.getCenterPoint()
|
||||
|
||||
// 사각형의 원래 꼭짓점 좌표 (로컬 좌표 기준)
|
||||
const halfWidth = (rect.width / 2) * rect.scaleX
|
||||
const halfHeight = (rect.height / 2) * rect.scaleY
|
||||
|
||||
const corners = [
|
||||
{ x: -halfWidth, y: -halfHeight }, // 좌상단
|
||||
{ x: halfWidth, y: -halfHeight }, // 우상단
|
||||
{ x: halfWidth, y: halfHeight }, // 우하단
|
||||
{ x: -halfWidth, y: halfHeight }, // 좌하단
|
||||
]
|
||||
|
||||
// 각 꼭짓점 좌표를 캔버스 좌표로 변환
|
||||
const transformedCorners = corners.map((corner) => {
|
||||
const point = new fabric.Point(corner.x, corner.y)
|
||||
return fabric.util.transformPoint(point, rect.calcTransformMatrix())
|
||||
})
|
||||
|
||||
return transformedCorners
|
||||
}
|
||||
|
||||
function getSelectedExcretaLine() {}
|
||||
|
||||
if (moduleSetupSurfaces.length !== 0) {
|
||||
let tempModule
|
||||
let manualDrawModules = []
|
||||
let inside = false
|
||||
let turfPolygon
|
||||
let flowDirection
|
||||
let trestlePolygon
|
||||
|
||||
addCanvasMouseEventListener('mouse:move', (e) => {
|
||||
//마우스 이벤트 삭제 후 재추가
|
||||
const mousePoint = canvas.getPointer(e.e)
|
||||
|
||||
for (let i = 0; i < moduleSetupSurfaces.length; i++) {
|
||||
turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i])
|
||||
trestlePolygon = moduleSetupSurfaces[i]
|
||||
manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
|
||||
flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
|
||||
|
||||
if (flatBatchType === 'excreta') {
|
||||
const tempLine = excretaLinesAngle.find((obj) => obj.surfaceId === trestlePolygon.surfaceId)
|
||||
if (tempLine) {
|
||||
applyAngle = tempLine.angle
|
||||
} else {
|
||||
applyAngle = compasDeg
|
||||
}
|
||||
}
|
||||
|
||||
// const excretaLine = excretaLines.find((obj) => obj.isSelected === true && obj.surfaceId === trestlePolygon.surfaceId)
|
||||
|
||||
// console.log('excretaLine', excretaLine.x1, excretaLine.y1, excretaLine.x2, excretaLine.y2)
|
||||
|
||||
// applyAngle = calculateAngle(excretaLine.x1, excretaLine.y1, excretaLine.x2, excretaLine.y2)
|
||||
|
||||
// console.log('applyAngle', applyAngle)
|
||||
|
||||
let width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113
|
||||
let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172
|
||||
|
||||
const angledModule = new fabric.Rect({
|
||||
width: width,
|
||||
height: height,
|
||||
left: mousePoint.x - width / 2,
|
||||
top: mousePoint.y - height / 2,
|
||||
})
|
||||
|
||||
const center = angledModule.getCenterPoint()
|
||||
angledModule.set('angle', applyAngle)
|
||||
angledModule.setPositionByOrigin(center, 'center', 'center')
|
||||
|
||||
const points = getRotatedCorners(angledModule) //
|
||||
const turfPoints = coordToTurfPolygon(points)
|
||||
|
||||
if (turf.booleanWithin(turfPoints, turfPolygon)) {
|
||||
let isDrawing = false
|
||||
|
||||
if (isDrawing) return
|
||||
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임
|
||||
|
||||
tempModule = new QPolygon(points, {
|
||||
fill: 'white',
|
||||
stroke: 'black',
|
||||
strokeWidth: 0.3,
|
||||
name: 'tempModule',
|
||||
})
|
||||
|
||||
canvas?.add(tempModule) //움직여가면서 추가됨
|
||||
canvas?.renderAll()
|
||||
|
||||
/**
|
||||
* 스냅기능
|
||||
*/
|
||||
let snapDistance = 10
|
||||
let cellSnapDistance = 20
|
||||
|
||||
const trestleLeft = moduleSetupSurfaces[i].left
|
||||
const trestleTop = moduleSetupSurfaces[i].top
|
||||
const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX
|
||||
const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY
|
||||
const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2
|
||||
|
||||
// 작은 폴리곤의 경계 좌표 계산
|
||||
const smallLeft = tempModule.left
|
||||
const smallTop = tempModule.top
|
||||
const smallRight = smallLeft + tempModule.width * tempModule.scaleX
|
||||
const smallBottom = smallTop + tempModule.height * tempModule.scaleY
|
||||
const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2
|
||||
const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2
|
||||
|
||||
if (manualDrawModules) {
|
||||
manualDrawModules.forEach((cell) => {
|
||||
const holdCellLeft = cell.left
|
||||
const holdCellTop = cell.top
|
||||
const holdCellRight = holdCellLeft + cell.width * cell.scaleX
|
||||
const holdCellBottom = holdCellTop + cell.height * cell.scaleY
|
||||
const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2
|
||||
const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2
|
||||
|
||||
//설치된 셀에 좌측에 스냅
|
||||
if (Math.abs(smallRight - holdCellLeft) < snapDistance) {
|
||||
tempModule.left = holdCellLeft - width - 0.5
|
||||
}
|
||||
|
||||
//설치된 셀에 우측에 스냅
|
||||
if (Math.abs(smallLeft - holdCellRight) < snapDistance) {
|
||||
tempModule.left = holdCellRight + 0.5
|
||||
}
|
||||
|
||||
//설치된 셀에 위쪽에 스냅
|
||||
if (Math.abs(smallBottom - holdCellTop) < snapDistance) {
|
||||
tempModule.top = holdCellTop - height - 0.5
|
||||
}
|
||||
|
||||
//설치된 셀에 밑쪽에 스냅
|
||||
if (Math.abs(smallTop - holdCellBottom) < snapDistance) {
|
||||
tempModule.top = holdCellBottom + 0.5
|
||||
}
|
||||
//가운데 -> 가운데
|
||||
if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) {
|
||||
tempModule.left = holdCellCenterX - width / 2
|
||||
}
|
||||
//왼쪽 -> 가운데
|
||||
if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) {
|
||||
tempModule.left = holdCellCenterX
|
||||
}
|
||||
// 오른쪽 -> 가운데
|
||||
if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) {
|
||||
tempModule.left = holdCellCenterX - width
|
||||
}
|
||||
//세로 가운데 -> 가운데
|
||||
if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) {
|
||||
tempModule.top = holdCellCenterY - height / 2
|
||||
}
|
||||
//위쪽 -> 가운데
|
||||
if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) {
|
||||
tempModule.top = holdCellCenterY
|
||||
}
|
||||
//아랫쪽 -> 가운데
|
||||
if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) {
|
||||
tempModule.top = holdCellCenterY - height
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 위쪽 변에 스냅
|
||||
if (Math.abs(smallTop - trestleTop) < snapDistance) {
|
||||
tempModule.top = trestleTop
|
||||
}
|
||||
|
||||
// 아래쪽 변에 스냅
|
||||
if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) {
|
||||
tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY
|
||||
}
|
||||
|
||||
// 왼쪽변에 스냅
|
||||
if (Math.abs(smallLeft - trestleLeft) < snapDistance) {
|
||||
tempModule.left = trestleLeft
|
||||
}
|
||||
//오른쪽 변에 스냅
|
||||
if (Math.abs(smallRight - trestleRight) < snapDistance) {
|
||||
tempModule.left = trestleRight - tempModule.width * tempModule.scaleX
|
||||
}
|
||||
|
||||
if (flowDirection === 'south' || flowDirection === 'north') {
|
||||
// 모듈왼쪽이 세로중앙선에 붙게 스냅
|
||||
if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
|
||||
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2
|
||||
}
|
||||
|
||||
// 모듈이 가운데가 세로중앙선에 붙게 스냅
|
||||
if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
|
||||
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2
|
||||
}
|
||||
|
||||
// 모듈오른쪽이 세로중앙선에 붙게 스냅
|
||||
if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
|
||||
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX
|
||||
}
|
||||
} else {
|
||||
// 모듈이 가로중앙선에 스냅
|
||||
if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) {
|
||||
tempModule.top = bigCenterY - tempModule.height / 2
|
||||
}
|
||||
|
||||
if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
|
||||
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2
|
||||
}
|
||||
// 모듈 밑면이 가로중앙선에 스냅
|
||||
if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
|
||||
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY
|
||||
}
|
||||
}
|
||||
|
||||
inside = true
|
||||
break
|
||||
} else {
|
||||
inside = false
|
||||
}
|
||||
}
|
||||
|
||||
if (!inside) {
|
||||
// tempModule.set({ fill: 'red' })
|
||||
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule'))
|
||||
canvas?.renderAll()
|
||||
}
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||
let isIntersection = true
|
||||
if (!inside) return
|
||||
if (tempModule) {
|
||||
const tempTurfModule = polygonToTurfPolygon(tempModule)
|
||||
|
||||
//도머 객체를 가져옴
|
||||
if (batchObjects) {
|
||||
batchObjects.forEach((object) => {
|
||||
let dormerTurfPolygon
|
||||
|
||||
if (object.type === 'group') {
|
||||
//도머는 그룹형태임
|
||||
dormerTurfPolygon = batchObjectGroupToTurfPolygon(object)
|
||||
} else {
|
||||
//개구, 그림자
|
||||
dormerTurfPolygon = polygonToTurfPolygon(rectToPolygon(object))
|
||||
}
|
||||
|
||||
const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인
|
||||
//겹치면 안됨
|
||||
if (intersection) {
|
||||
alert('도머위에 모듈을 올릴 수 없습니다.')
|
||||
isIntersection = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (!isIntersection) return
|
||||
|
||||
if (turf.booleanWithin(tempTurfModule, turfPolygon)) {
|
||||
//마우스 클릭시 set으로 해당 위치에 셀을 넣음
|
||||
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
|
||||
if (!isOverlap) {
|
||||
console.log('tempModule.points', tempModule.points)
|
||||
|
||||
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
|
||||
canvas?.add(manualModule)
|
||||
manualDrawModules.push(tempModule)
|
||||
} else {
|
||||
alert('셀끼리 겹치면 안되죠?')
|
||||
}
|
||||
} else {
|
||||
alert('나갔죠?!!')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const autoFlatroofModuleSetup = (placementFlatRef) => {}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user