육지붕 자동 모듈 설치 작업중

This commit is contained in:
yjnoh 2024-12-11 17:25:38 +09:00
parent 7e2180cd76
commit 61c99c1458
2 changed files with 539 additions and 137 deletions

View File

@ -1,17 +1,17 @@
import { forwardRef, useState, useEffect } from 'react' import { forwardRef, useState, useEffect } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { compasDegAtom } from '@/store/orientationAtom'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent'
const PitchPlacement = forwardRef((props, refs) => { const PitchPlacement = forwardRef((props, refs) => {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [setupLocation, setSetupLocation] = useState('south') const [setupLocation, setSetupLocation] = useState('south')
const { makeModuleInstArea } = useModuleBasicSetting() const { makeModuleInstArea } = useModuleBasicSetting()
const compasDeg = useRecoilValue(compasDegAtom)
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const { initEvent } = useEvent()
useEffect(() => { useEffect(() => {
makeModuleInstArea() makeModuleInstArea()
@ -45,6 +45,7 @@ const PitchPlacement = forwardRef((props, refs) => {
} }
const handleSetupLocation = (e) => { const handleSetupLocation = (e) => {
initEvent()
refs.setupLocation.current = e.target refs.setupLocation.current = e.target
setSetupLocation(e.target.value) setSetupLocation(e.target.value)
} }
@ -153,7 +154,7 @@ const PitchPlacement = forwardRef((props, refs) => {
value={'south'} value={'south'}
checked={setupLocation === 'south'} checked={setupLocation === 'south'}
defaultChecked defaultChecked
onChange={handleSetupLocation} onClick={handleSetupLocation}
/> />
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label> <label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
</div> </div>
@ -164,7 +165,7 @@ const PitchPlacement = forwardRef((props, refs) => {
id="ra02" id="ra02"
value={'excreta'} value={'excreta'}
checked={setupLocation === 'excreta'} checked={setupLocation === 'excreta'}
onChange={handleSetupLocation} onClick={handleSetupLocation}
/> />
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label> <label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
</div> </div>

View File

@ -12,6 +12,7 @@ import { v4 as uuidv4 } from 'uuid'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { canvasSettingState } from '@/store/canvasAtom' import { canvasSettingState } from '@/store/canvasAtom'
import { compasDegAtom } from '@/store/orientationAtom' import { compasDegAtom } from '@/store/orientationAtom'
import { QLine } from '@/components/fabric/QLine'
export function useModuleBasicSetting() { export function useModuleBasicSetting() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -51,6 +52,7 @@ export function useModuleBasicSetting() {
const makeModuleInstArea = () => { const makeModuleInstArea = () => {
//지붕 객체 반환 //지붕 객체 반환
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20
if (!roofs) { if (!roofs) {
return return
@ -63,13 +65,11 @@ export function useModuleBasicSetting() {
} }
setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경 setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
const offsetPoints = offsetPolygon(roof.points, -20) //안쪽 offset const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
//모듈설치영역?? 생성 //모듈설치영역?? 생성
const surfaceId = uuidv4() const surfaceId = uuidv4()
console.log('roof.moduleCompass', roof.moduleCompass)
let setupSurface = new QPolygon(offsetPoints, { let setupSurface = new QPolygon(offsetPoints, {
stroke: 'red', stroke: 'red',
fill: 'transparent', fill: 'transparent',
@ -88,7 +88,10 @@ export function useModuleBasicSetting() {
flipX: roof.flipX, flipX: roof.flipX,
flipY: roof.flipY, flipY: roof.flipY,
surfaceId: surfaceId, surfaceId: surfaceId,
originX: 'center',
originY: 'center',
modules: [], modules: [],
// angle: -compasDeg,
}) })
setupSurface.setViewLengthText(false) setupSurface.setViewLengthText(false)
@ -102,6 +105,7 @@ export function useModuleBasicSetting() {
} }
setupSurface.set({ flowLines: flowLines }) setupSurface.set({ flowLines: flowLines })
flatRoofMakeSurface(roof, setupSurface)
//지붕면 선택 금지 //지붕면 선택 금지
roof.set({ roof.set({
@ -656,7 +660,7 @@ export function useModuleBasicSetting() {
} }
} }
const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, flowModuleLine, isCenter = false) => { const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, aaa, isCenter = false) => {
let startPoint = flowModuleLine.left let startPoint = flowModuleLine.left
//중앙배치일 경우에는 계산한다 //중앙배치일 경우에는 계산한다
@ -1206,9 +1210,10 @@ export function useModuleBasicSetting() {
return turf.polygon([coordinates]) return turf.polygon([coordinates])
} }
const polygonToTurfPolygon = (object) => { const polygonToTurfPolygon = (object, current = false) => {
let coordinates let coordinates
coordinates = object.points.map((point) => [point.x, point.y]) coordinates = object.points.map((point) => [point.x, point.y])
if (current) coordinates = object.getCurrentPoints().map((point) => [point.x, point.y])
coordinates.push(coordinates[0]) coordinates.push(coordinates[0])
return turf.polygon( return turf.polygon(
[coordinates], [coordinates],
@ -1526,17 +1531,18 @@ export function useModuleBasicSetting() {
let flatBatchType = placementFlatRef.setupLocation.current.value let flatBatchType = placementFlatRef.setupLocation.current.value
let excretaLinesAngle = [] let excretaLinesAngle = []
if (flatBatchType === 'south') { if (flatBatchType === 'excreta') {
applyAngle = compasDeg const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine')
} else {
const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine' && obj.isSelected === true)
excretaLines.forEach((obj) => { excretaLines.forEach((obj) => {
const points1 = { x: obj.x1, y: obj.y1 } if (obj.isSelected) {
const points2 = { x: obj.x2, y: obj.y2 } const points1 = { x: obj.x1, y: obj.y1 }
excretaLinesAngle.push({ const points2 = { x: obj.x2, y: obj.y2 }
surfaceId: obj.surfaceId, excretaLinesAngle.push({
angle: calculateAngle(points1, points2), surfaceId: obj.surfaceId,
}) angle: calculateAngle(points1, points2),
})
}
canvas.remove(obj)
}) })
} }
@ -1591,8 +1597,6 @@ export function useModuleBasicSetting() {
return transformedCorners return transformedCorners
} }
function getSelectedExcretaLine() {}
if (moduleSetupSurfaces.length !== 0) { if (moduleSetupSurfaces.length !== 0) {
let tempModule let tempModule
let manualDrawModules = [] let manualDrawModules = []
@ -1606,7 +1610,7 @@ export function useModuleBasicSetting() {
const mousePoint = canvas.getPointer(e.e) const mousePoint = canvas.getPointer(e.e)
for (let i = 0; i < moduleSetupSurfaces.length; i++) { for (let i = 0; i < moduleSetupSurfaces.length; i++) {
turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i]) turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i], true)
trestlePolygon = moduleSetupSurfaces[i] trestlePolygon = moduleSetupSurfaces[i]
manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨 manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향 flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
@ -1616,18 +1620,11 @@ export function useModuleBasicSetting() {
if (tempLine) { if (tempLine) {
applyAngle = tempLine.angle applyAngle = tempLine.angle
} else { } else {
//혹시나 두개의 지붕을 그리고 한쪽면만 선택했을때 한면은 그냥 기본 기울기를 준다
applyAngle = compasDeg 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 width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113
let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172 let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172
@ -1667,123 +1664,125 @@ export function useModuleBasicSetting() {
let snapDistance = 10 let snapDistance = 10
let cellSnapDistance = 20 let cellSnapDistance = 20
const trestleLeft = moduleSetupSurfaces[i].left // if (applyAngle === 90 || applyAngle === 180 || applyAngle === 270 || applyAngle === 0) {
const trestleTop = moduleSetupSurfaces[i].top // const trestleLeft = moduleSetupSurfaces[i].left
const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX // const trestleTop = moduleSetupSurfaces[i].top
const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY // const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX
const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 // const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY
// const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2
// 작은 폴리곤의 경계 좌표 계산 // // 작은 폴리곤의 경계 좌표 계산
const smallLeft = tempModule.left // const smallLeft = tempModule.left
const smallTop = tempModule.top // const smallTop = tempModule.top
const smallRight = smallLeft + tempModule.width * tempModule.scaleX // const smallRight = smallLeft + tempModule.width * tempModule.scaleX
const smallBottom = smallTop + tempModule.height * tempModule.scaleY // const smallBottom = smallTop + tempModule.height * tempModule.scaleY
const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 // const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2
const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 // const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2
if (manualDrawModules) { // if (manualDrawModules) {
manualDrawModules.forEach((cell) => { // manualDrawModules.forEach((cell) => {
const holdCellLeft = cell.left // const holdCellLeft = cell.left
const holdCellTop = cell.top // const holdCellTop = cell.top
const holdCellRight = holdCellLeft + cell.width * cell.scaleX // const holdCellRight = holdCellLeft + cell.width * cell.scaleX
const holdCellBottom = holdCellTop + cell.height * cell.scaleY // const holdCellBottom = holdCellTop + cell.height * cell.scaleY
const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 // const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2
const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 // const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2
//설치된 셀에 좌측에 스냅 // //설치된 셀에 좌측에 스냅
if (Math.abs(smallRight - holdCellLeft) < snapDistance) { // if (Math.abs(smallRight - holdCellLeft) < snapDistance) {
tempModule.left = holdCellLeft - width - 0.5 // tempModule.left = holdCellLeft - width - 0.5
} // }
//설치된 셀에 우측에 스냅 // //설치된 셀에 우측에 스냅
if (Math.abs(smallLeft - holdCellRight) < snapDistance) { // if (Math.abs(smallLeft - holdCellRight) < snapDistance) {
tempModule.left = holdCellRight + 0.5 // tempModule.left = holdCellRight + 0.5
} // }
//설치된 셀에 위쪽에 스냅 // //설치된 셀에 위쪽에 스냅
if (Math.abs(smallBottom - holdCellTop) < snapDistance) { // if (Math.abs(smallBottom - holdCellTop) < snapDistance) {
tempModule.top = holdCellTop - height - 0.5 // tempModule.top = holdCellTop - height - 0.5
} // }
//설치된 셀에 밑쪽에 스냅 // //설치된 셀에 밑쪽에 스냅
if (Math.abs(smallTop - holdCellBottom) < snapDistance) { // if (Math.abs(smallTop - holdCellBottom) < snapDistance) {
tempModule.top = holdCellBottom + 0.5 // tempModule.top = holdCellBottom + 0.5
} // }
//가운데 -> 가운데 // //가운데 -> 가운데
if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { // if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX - width / 2 // tempModule.left = holdCellCenterX - width / 2
} // }
//왼쪽 -> 가운데 // //왼쪽 -> 가운데
if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { // if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX // tempModule.left = holdCellCenterX
} // }
// 오른쪽 -> 가운데 // // 오른쪽 -> 가운데
if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { // if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX - width // tempModule.left = holdCellCenterX - width
} // }
//세로 가운데 -> 가운데 // //세로 가운데 -> 가운데
if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { // if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) {
tempModule.top = holdCellCenterY - height / 2 // tempModule.top = holdCellCenterY - height / 2
} // }
//위쪽 -> 가운데 // //위쪽 -> 가운데
if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) {
tempModule.top = holdCellCenterY // tempModule.top = holdCellCenterY
} // }
//아랫쪽 -> 가운데 // //아랫쪽 -> 가운데
if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) {
tempModule.top = holdCellCenterY - height // tempModule.top = holdCellCenterY - height
} // }
}) // })
} // }
// 위쪽 변에 스냅 // // 위쪽 변에 스냅
if (Math.abs(smallTop - trestleTop) < snapDistance) { // if (Math.abs(smallTop - trestleTop) < snapDistance) {
tempModule.top = trestleTop // tempModule.top = trestleTop
} // }
// 아래쪽 변에 스냅 // // 아래쪽 변에 스냅
if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { // if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY // tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY
} // }
// 왼쪽변에 스냅 // // 왼쪽변에 스냅
if (Math.abs(smallLeft - trestleLeft) < snapDistance) { // if (Math.abs(smallLeft - trestleLeft) < snapDistance) {
tempModule.left = trestleLeft // tempModule.left = trestleLeft
} // }
//오른쪽 변에 스냅 // //오른쪽 변에 스냅
if (Math.abs(smallRight - trestleRight) < snapDistance) { // if (Math.abs(smallRight - trestleRight) < snapDistance) {
tempModule.left = trestleRight - tempModule.width * tempModule.scaleX // tempModule.left = trestleRight - tempModule.width * tempModule.scaleX
} // }
if (flowDirection === 'south' || flowDirection === 'north') { // if (flowDirection === 'south' || flowDirection === 'north') {
// 모듈왼쪽이 세로중앙선에 붙게 스냅 // // 모듈왼쪽이 세로중앙선에 붙게 스냅
if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2
} // }
// 모듈이 가운데가 세로중앙선에 붙게 스냅 // // 모듈이 가운데가 세로중앙선에 붙게 스냅
if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2
} // }
// 모듈오른쪽이 세로중앙선에 붙게 스냅 // // 모듈오른쪽이 세로중앙선에 붙게 스냅
if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX
} // }
} else { // } else {
// 모듈이 가로중앙선에 스냅 // // 모듈이 가로중앙선에 스냅
if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { // if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) {
tempModule.top = bigCenterY - tempModule.height / 2 // tempModule.top = bigCenterY - tempModule.height / 2
} // }
if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2
} // }
// 모듈 밑면이 가로중앙선에 스냅 // // 모듈 밑면이 가로중앙선에 스냅
if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY
} // }
} // }
// }
inside = true inside = true
break break
@ -1833,8 +1832,6 @@ export function useModuleBasicSetting() {
//마우스 클릭시 set으로 해당 위치에 셀을 넣음 //마우스 클릭시 set으로 해당 위치에 셀을 넣음
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
if (!isOverlap) { if (!isOverlap) {
console.log('tempModule.points', tempModule.points)
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions }) let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
canvas?.add(manualModule) canvas?.add(manualModule)
manualDrawModules.push(tempModule) manualDrawModules.push(tempModule)
@ -1849,7 +1846,411 @@ export function useModuleBasicSetting() {
} }
} }
const autoFlatroofModuleSetup = (placementFlatRef) => {} const autoFlatroofModuleSetup = (placementFlatRef) => {
initEvent() //마우스 이벤트 초기화
let flatBatchType = placementFlatRef.setupLocation.current.value
const moduleSetupSurfaces = moduleSetupSurface //선택 설치면
const notSelectedTrestlePolygons = canvas
?.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && !moduleSetupSurfaces.includes(obj)) //설치면이 아닌것
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 객체
if (moduleSetupSurfaces.length === 0) {
alert('선택된 모듈 설치면이 없습니다.')
return
}
//어짜피 자동으로 누르면 선택안된데도 다 날아간다
canvas.getObjects().forEach((obj) => {
if (obj.name === 'module') {
canvas.remove(obj)
}
})
notSelectedTrestlePolygons.forEach((obj) => {
if (obj.modules) {
obj.modules.forEach((module) => {
canvas?.remove(module)
})
obj.modules = []
}
})
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',
}
let leftMargin, bottomMargin, square, chidoriLength
//선택된 지붕안에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 포함되면 배열 반환
const objectsIncludeSurface = (turfModuleSetupSurface) => {
let containsBatchObjects = []
containsBatchObjects = batchObjects.filter((batchObject) => {
let convertBatchObject
if (batchObject.type === 'group') {
//도머는 그룹형태임
convertBatchObject = batchObjectGroupToTurfPolygon(batchObject)
} else {
//개구, 그림자
batchObject.set({ points: rectToPolygon(batchObject) })
canvas?.renderAll() // set된걸 바로 적용하기 위해
convertBatchObject = polygonToTurfPolygon(batchObject) //rect를 폴리곤으로 변환 -> turf 폴리곤으로 변환
}
// 폴리곤 안에 도머 폴리곤이 포함되어있는지 확인해서 반환하는 로직
return turf.booleanContains(turfModuleSetupSurface, convertBatchObject) || turf.booleanWithin(convertBatchObject, turfModuleSetupSurface)
})
return containsBatchObjects
}
/**
* 도머나 개구가 모듈에 걸치는지 확인하는 로직
* @param {*} squarePolygon
* @param {*} containsBatchObjects
* @returns
*/
const checkModuleDisjointObjects = (squarePolygon, containsBatchObjects) => {
let isDisjoint = false
if (containsBatchObjects.length > 0) {
let convertBatchObject
//도머가 있으면 적용되는 로직
isDisjoint = containsBatchObjects.every((batchObject) => {
if (batchObject.type === 'group') {
convertBatchObject = batchObjectGroupToTurfPolygon(batchObject)
} else {
convertBatchObject = polygonToTurfPolygon(batchObject)
}
/**
* 도머가 여러개일수있으므로 겹치는게 있다면...
* 안겹치는지 확인하는 로직이라 안겹치면 true를 반환
*/
return turf.booleanDisjoint(squarePolygon, convertBatchObject)
})
} else {
isDisjoint = true
}
return isDisjoint
}
/**
* 배치면 안에 있는지 확인
* @param {*} squarePolygon
* @param {*} turfModuleSetupSurface
* @returns
*/
const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => {
return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface)
}
let moduleGroup = []
const flatRoofDownFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.bottom
const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측
const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측
const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단
let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1
let totalTopEndPoint = maxTopEndPoint - startPoint.y1
let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width)
let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width)
let diffTopEndPoint = Math.abs(totalTopEndPoint / height)
let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1)
let tempMaxWidth = width //최대배치인지 확인하려고 넣음
for (let j = 0; j < diffTopEndPoint; j++) {
bottomMargin = marginHeight * j
for (let i = 0; i <= totalWidth; i++) {
leftMargin = marginWidth * i
square = [
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 - height * j - bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 - height * j - height - bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - height - bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
const flatRoofLeftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.left
const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측
const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단
const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단
let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌
let diffTopEndPoint = Math.abs(totalTopEndPoint / height)
let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height)
let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width
let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint)
let tempMaxHeight = height //최대배치인지 확인하려고 넣음
for (let i = 0; i <= totalWidth; i++) {
bottomMargin = marginHeight * i
for (let j = 0; j < totalHeight; j++) {
leftMargin = marginWidth * j
square = [
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
const flatRoofTopFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.top
const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측
const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측
const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단
let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1
let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint
let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1
let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width)
let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width))
let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height))
let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1)
let tempMaxWidth = width //최대배치인지 확인하려고 넣음
for (let j = 0; j < diffBottomEndPoint; j++) {
bottomMargin = marginHeight * j
for (let i = 0; i < diffRightEndPoint; i++) {
leftMargin = marginWidth * i
square = [
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 + height * j + bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 + height * j + bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 + height * j + bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
const flatRoofRightFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.right
const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측
const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단
const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단
let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌
let diffTopEndPoint = Math.abs(totalTopEndPoint / height)
let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height)
let totalWidth = Math.abs(startPoint.x1 - maxLeftEndPoint) / width
let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - 3 // -3으로 위치살짝 보정
let tempMaxHeight = height //최대배치인지 확인하려고 넣음
for (let i = 0; i <= totalWidth; i++) {
bottomMargin = marginHeight * i
for (let j = 0; j < totalHeight; j++) {
leftMargin = marginWidth * j
square = [
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
moduleSetupSurfaces.forEach((moduleSetupSurface, index) => {
moduleSetupSurface.fire('mousedown')
const moduleSetupArray = []
let maxLengthLine = moduleSetupSurface.lines.reduce((acc, cur) => {
return acc.length > cur.length ? acc : cur
})
const turfModuleSetupSurface = polygonToTurfPolygon(moduleSetupSurface, true) //폴리곤을 turf 객체로 변환
const containsBatchObjects = objectsIncludeSurface(turfModuleSetupSurface) //배치면에 오브젝트(도머, 개구등)이 있는지 확인하는 로직
let width = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 172.2 : 113.4
let height = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 113.4 : 172.2
//배치면때는 방향쪽으로 패널이 넓게 누워져야함
if (moduleSetupSurface.flowDirection !== undefined) {
width = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 172.2 : 113.4
height = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 113.4 : 172.2
}
const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface)
const marginWidth = 0
const marginHeight = 0
canvas.renderAll()
if (compasDeg >= 0 && compasDeg < 90) {
flatRoofDownFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
} else if (compasDeg >= 90 && compasDeg < 180) {
flatRoofLeftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
} else if (compasDeg >= 180 && compasDeg < 270) {
flatRoofRightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
} else {
flatRoofTopFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
}
const setupedModules = moduleSetupArray.filter((module, index) => {
let disjointFromTrestle = checkModuleDisjointSurface(module.turfPoints, turfModuleSetupSurface)
let isDisjoint = checkModuleDisjointObjects(module.turfPoints, containsBatchObjects)
if (!(disjointFromTrestle && isDisjoint)) {
canvas?.remove(module)
// module.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 })
return false
} else {
return module
}
})
canvas?.renderAll()
//나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기
// setupedModules.forEach((module, index) => {
// if (isMaxSetup && index > 0) {
// const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module))
// //겹치는지 확인
// if (isOverlap) {
// //겹쳐있으면 삭제
// // canvas?.remove(module)
// module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 })
// canvas.renderAll()
// setupedModules.splice(index, 1)
// return false
// }
// }
// })
moduleSetupSurface.set({ modules: setupedModules })
// const moduleArray = [...moduleIsSetup]
// moduleArray.push({
// surfaceId: moduleSetupSurface.surfaceId,
// moduleSetupArray: setupedModules,
// })
// setModuleIsSetup(moduleArray)
})
// console.log(calculateForApi())
}
const flatRoofMakeSurface = (roof, setupSurface) => {
setupSurface.angle = -compasDeg
roof.angle = -compasDeg
const roofPoints = roof.getCurrentPoints()
const roofLines = roofPoints.map((point, index) => {
const nextIndex = (index + 1) % roofPoints.length
const nextPoint = roofPoints[nextIndex]
return {
x1: point.x,
y1: point.y,
x2: nextPoint.x,
y2: nextPoint.y,
}
})
roof.set({ lines: roofLines })
roof.fire('modified')
const surfacePoints = setupSurface.getCurrentPoints()
const surfaceLines = surfacePoints.map((point, index) => {
const nextIndex = (index + 1) % surfacePoints.length
const nextPoint = surfacePoints[nextIndex]
return {
x1: point.x,
y1: point.y,
x2: nextPoint.x,
y2: nextPoint.y,
}
})
setupSurface.set({ lines: surfaceLines })
const flowLines = {
bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'),
top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'),
left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'),
right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'),
}
setupSurface.set({ flowLines: flowLines })
setupSurface.fire('modified')
}
return { return {
makeModuleInstArea, makeModuleInstArea,