모듈 설치 간격 적용

This commit is contained in:
lelalela 2025-01-16 12:52:42 +09:00
parent de282fd969
commit 895e28ef37
9 changed files with 463 additions and 343 deletions

View File

@ -169,6 +169,7 @@ export const SAVE_KEY = [
'supFitQty', 'supFitQty',
'supFitIntvlPct', 'supFitIntvlPct',
'rackLen', 'rackLen',
'trestleDetail',
] ]
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]

View File

@ -78,7 +78,6 @@ export default function CanvasMenu(props) {
const { commonFunctions } = useCommonUtils() const { commonFunctions } = useCommonUtils()
const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext) const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext)
const { restoreModuleInstArea } = useModuleBasicSetting()
const [addedRoofs, setAddedRoofsState] = useRecoilState(addedRoofsState) const [addedRoofs, setAddedRoofsState] = useRecoilState(addedRoofsState)
const [basicSetting, setBasicSetting] = useRecoilState(basicSettingState) const [basicSetting, setBasicSetting] = useRecoilState(basicSettingState)
@ -162,10 +161,6 @@ export default function CanvasMenu(props) {
setType('outline') setType('outline')
break break
case 3: case 3:
if (type === 'module') {
restoreModuleInstArea()
}
setType('surface') setType('surface')
break break
case 4: case 4:

View File

@ -5,8 +5,8 @@ import Module from '@/components/floor-plan/modal/basic/step/Module'
import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchModule' import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchModule'
import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement'
import Placement from '@/components/floor-plan/modal/basic/step/Placement' import Placement from '@/components/floor-plan/modal/basic/step/Placement'
import { useRecoilValue } from 'recoil' import { useRecoilValue, useRecoilState } from 'recoil'
import { canvasSettingState } from '@/store/canvasAtom' import { canvasSettingState, isManualModuleSetupState } from '@/store/canvasAtom'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation' import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
@ -19,6 +19,8 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
const canvasSetting = useRecoilValue(canvasSettingState) const canvasSetting = useRecoilValue(canvasSettingState)
const orientationRef = useRef(null) const orientationRef = useRef(null)
const { initEvent } = useEvent() const { initEvent } = useEvent()
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
// const { initEvent } = useContext(EventContext) // const { initEvent } = useContext(EventContext)
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting() const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting()
const handleBtnNextStep = () => { const handleBtnNextStep = () => {
@ -38,6 +40,14 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
setupLocation: useRef('south'), setupLocation: useRef('south'),
} }
const handleManualModuleSetup = () => {
setIsManualModuleSetup(!isManualModuleSetup)
}
useEffect(() => {
manualModuleSetup()
}, [isManualModuleSetup])
return ( return (
<WithDraggable isShow={true} pos={pos}> <WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap lx-2`}> <div className={`modal-pop-wrap lx-2`}>
@ -83,7 +93,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
<> <>
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != 3 && ( {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != 3 && (
<> <>
<button className="btn-frame modal mr5" onClick={manualModuleSetup}> <button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
{getMessage('modal.module.basic.setting.passivity.placement')} {getMessage('modal.module.basic.setting.passivity.placement')}
</button> </button>
<button className="btn-frame modal act" onClick={() => autoModuleSetup(placementRef)}> <button className="btn-frame modal act" onClick={() => autoModuleSetup(placementRef)}>

View File

@ -235,7 +235,6 @@ export default function Module({ setTabNum }) {
index={index} index={index}
addRoof={roof} addRoof={roof}
roofTab={index} roofTab={index}
moduleCommonSelectionData={moduleSelectionData.common}
moduleConstructionSelectionData={moduleSelectionData.roofConstructions[index]} moduleConstructionSelectionData={moduleSelectionData.roofConstructions[index]}
setModuleSelectionData={setModuleSelectionData} setModuleSelectionData={setModuleSelectionData}
tempModuleSelectionData={tempModuleSelectionData} tempModuleSelectionData={tempModuleSelectionData}

View File

@ -1,24 +1,22 @@
import { useEffect, useState, useRef } from 'react' import { useEffect, useState, useRef } from 'react'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasSettingState, pitchSelector, pitchTextSelector } from '@/store/canvasAtom' import { pitchTextSelector } from '@/store/canvasAtom'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useMasterController } from '@/hooks/common/useMasterController' import { useMasterController } from '@/hooks/common/useMasterController'
import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCommonCode } from '@/hooks/common/useCommonCode'
import { moduleSelectionInitParamsState, selectedModuleState } from '@/store/selectedModuleOptions' import { moduleSelectionInitParamsState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils' import { isObjectNotEmpty } from '@/util/common-utils'
import QSelectBox from '@/components/common/select/QSelectBox' import QSelectBox from '@/components/common/select/QSelectBox'
export default function ModuleTabContents({ export default function ModuleTabContents({
addRoof, addRoof,
roofTab, roofTab,
moduleCommonSelectionData,
moduleConstructionSelectionData, moduleConstructionSelectionData,
setModuleSelectionData, setModuleSelectionData,
tempModuleSelectionData, tempModuleSelectionData,
setTempModuleSelectionData, setTempModuleSelectionData,
}) { }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const canvasSetting = useRecoilValue(canvasSettingState) //
const [roofMaterial, setRoofMaterial] = useState(addRoof) //` const [roofMaterial, setRoofMaterial] = useState(addRoof) //`
const globalPitchText = useRecoilValue(pitchTextSelector) // const globalPitchText = useRecoilValue(pitchTextSelector) //
@ -61,18 +59,23 @@ export default function ModuleTabContents({
setTrestleList([]) // setTrestleList([]) //
setConstMthdList([]) // setConstMthdList([]) //
setRoofBaseList([]) // setRoofBaseList([]) //
setConstructionList([]) //
} }
// //
const handleChangeTrestle = (option) => { const handleChangeTrestle = (option) => {
setSelectedTrestle(option) // setSelectedTrestle(option) //
setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' }) setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' })
setConstMthdList([]) //
setRoofBaseList([]) //
setConstructionList([]) //
} }
// //
const handleChangeConstMthd = (option) => { const handleChangeConstMthd = (option) => {
setSelectedConstMthd(option) // setSelectedConstMthd(option) //
setRoofBaseParams({ ...trestleParams, trestleMkrCd: selectedTrestle.trestleMkrCd, constMthdCd: option.constMthdCd, roofBaseCd: '' }) setRoofBaseParams({ ...trestleParams, trestleMkrCd: selectedTrestle.trestleMkrCd, constMthdCd: option.constMthdCd, roofBaseCd: '' })
setConstructionList([]) //
} }
// //
@ -127,28 +130,34 @@ export default function ModuleTabContents({
} }
const handleConstruction = (index) => { const handleConstruction = (index) => {
const isPossibleIndex = constructionRef.current if (index > -1) {
.map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1)) const isPossibleIndex = constructionRef.current
.filter((index) => index !== -1) .map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1))
.filter((index) => index !== -1)
isPossibleIndex.forEach((index) => { isPossibleIndex.forEach((index) => {
if (constructionRef.current[index].classList.contains('blue')) { if (constructionRef.current[index].classList.contains('blue')) {
constructionRef.current[index].classList.remove('blue') constructionRef.current[index].classList.remove('blue')
constructionRef.current[index].classList.add('white') constructionRef.current[index].classList.add('white')
} }
}) })
constructionRef.current[index].classList.remove('white') constructionRef.current[index].classList.remove('white')
constructionRef.current[index].classList.add('blue') constructionRef.current[index].classList.add('blue')
const selectedConstruction = constructionList[index] const selectedConstruction = constructionList[index]
selectedConstruction.roofIndex = roofTab selectedConstruction.roofIndex = roofTab
selectedConstruction.setupCover = false // selectedConstruction.setupCover = false //
selectedConstruction.setupSnowCover = false // selectedConstruction.setupSnowCover = false //
selectedConstruction.selectedIndex = index selectedConstruction.selectedIndex = index
setCvrYn(selectedConstruction.cvrYn) setCvrYn(selectedConstruction.cvrYn)
setSnowGdPossYn(selectedConstruction.snowGdPossYn) setSnowGdPossYn(selectedConstruction.snowGdPossYn)
setSelectedConstruction(selectedConstruction) setSelectedConstruction(selectedConstruction)
} else {
constructionRef.current.forEach((ref) => {
ref.classList.remove('blue')
})
}
} }
useEffect(() => { useEffect(() => {

View File

@ -1,6 +1,6 @@
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState, checkedModuleState, selectedModuleState } from '@/store/canvasAtom' import { canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom'
import { rectToPolygon, setSurfaceShapePattern, polygonToTurfPolygon } from '@/util/canvas-util' import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util'
import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom' import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom'
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
@ -23,13 +23,14 @@ export function useModuleBasicSetting() {
const roofDisplay = useRecoilValue(roofDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector)
const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState) const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState)
const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState) const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState)
const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useEvent() const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const canvasSetting = useRecoilValue(canvasSettingState) const canvasSetting = useRecoilValue(canvasSettingState)
const compasDeg = useRecoilValue(compasDegAtom) const compasDeg = useRecoilValue(compasDegAtom)
const { setSurfaceShapePattern } = useRoofFn() const { setSurfaceShapePattern } = useRoofFn()
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const checkedModule = useRecoilValue(checkedModuleState) const checkedModule = useRecoilValue(checkedModuleState)
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
useEffect(() => { useEffect(() => {
// console.log('basicSetting', basicSetting) // console.log('basicSetting', basicSetting)
@ -67,6 +68,7 @@ export function useModuleBasicSetting() {
setSurfaceShapePattern(roof, roofDisplay.column, false) //패턴 변경 setSurfaceShapePattern(roof, roofDisplay.column, false) //패턴 변경
}) })
} }
const makeModuleInstArea = () => { const makeModuleInstArea = () => {
//지붕 객체 반환 //지붕 객체 반환
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
@ -109,6 +111,7 @@ export function useModuleBasicSetting() {
originX: 'center', originX: 'center',
originY: 'center', originY: 'center',
modules: [], modules: [],
roofMaterial: roof.roofMaterial,
// angle: -compasDeg, // angle: -compasDeg,
}) })
@ -129,8 +132,6 @@ export function useModuleBasicSetting() {
//설치 범위 지정 클릭 이벤트 //설치 범위 지정 클릭 이벤트
const toggleSelection = (setupSurface) => { const toggleSelection = (setupSurface) => {
console.log('setupSurface', setupSurface)
const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId) const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
//최초 선택일때 //최초 선택일때
if (!isExist) { if (!isExist) {
@ -171,303 +172,329 @@ export function useModuleBasicSetting() {
* 확인 셀을 이동시킴 * 확인 셀을 이동시킴
*/ */
const manualModuleSetup = () => { const manualModuleSetup = () => {
if (checkedModule.length === 0) { // console.log('isManualModuleSetup', isManualModuleSetup)
swalFire({ text: getMessage('module.place.select.module') })
return
}
if (checkedModule.length > 1) { if (isManualModuleSetup) {
swalFire({ text: getMessage('module.place.select.one.module') }) if (checkedModule.length === 0) {
return swalFire({ text: getMessage('module.place.select.module') })
} setIsManualModuleSetup(!isManualModuleSetup)
return
}
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 if (checkedModule.length > 1) {
const batchObjects = canvas swalFire({ text: getMessage('module.place.select.one.module') })
?.getObjects() setIsManualModuleSetup(!isManualModuleSetup)
.filter( return
(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 = { const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
fill: checkedModule[0].color, const batchObjects = canvas
stroke: 'black', ?.getObjects()
strokeWidth: 0.1, .filter(
selectable: true, // 선택 가능하게 설정 (obj) =>
lockMovementX: true, // X 축 이동 잠금 obj.name === BATCH_TYPE.OPENING ||
lockMovementY: true, // Y 축 이동 잠금 obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
lockRotation: true, // 회전 잠금 obj.name === BATCH_TYPE.PENTAGON_DORMER ||
lockScalingX: true, // X 축 크기 조정 잠금 obj.name === BATCH_TYPE.SHADOW,
lockScalingY: true, // Y 축 크기 조정 잠금 ) //도머s 객체
name: 'module',
}
if (moduleSetupSurfaces.length !== 0) { const moduleOptions = {
let tempModule fill: checkedModule[0].color,
let manualDrawModules = [] stroke: 'black',
let inside = false strokeWidth: 0.1,
let turfPolygon selectable: true, // 선택 가능하게 설정
let flowDirection lockMovementX: true, // X 축 이동 잠금
let trestlePolygon lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
name: 'module',
}
addCanvasMouseEventListener('mouse:move', (e) => { if (moduleSetupSurfaces.length !== 0) {
//마우스 이벤트 삭제 후 재추가 let tempModule
const mousePoint = canvas.getPointer(e.e) let manualDrawModules = []
let inside = false
let turfPolygon
let flowDirection
let trestlePolygon
for (let i = 0; i < moduleSetupSurfaces.length; i++) { addCanvasMouseEventListener('mouse:move', (e) => {
turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i]) //마우스 이벤트 삭제 후 재추가
trestlePolygon = moduleSetupSurfaces[i] const mousePoint = canvas.getPointer(e.e)
manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
const moduleWidth = Number(checkedModule[0].longAxis) / 10
const moduleHeight = Number(checkedModule[0].shortAxis) / 10
let width = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight
let height = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth
const points = [ for (let i = 0; i < moduleSetupSurfaces.length; i++) {
{ x: mousePoint.x - width / 2, y: mousePoint.y - height / 2 }, turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i])
{ x: mousePoint.x + width / 2, y: mousePoint.y - height / 2 }, trestlePolygon = moduleSetupSurfaces[i]
{ x: mousePoint.x + width / 2, y: mousePoint.y + height / 2 }, manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
{ x: mousePoint.x - width / 2, y: mousePoint.y + height / 2 }, flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
]
const turfPoints = coordToTurfPolygon(points) const moduleWidth = Number(checkedModule[0].longAxis) / 10
const moduleHeight = Number(checkedModule[0].shortAxis) / 10
let tmpWidth = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight
let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth
let { width, height } = calculateVisibleModuleHeight(
tmpWidth,
tmpHeight,
getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch),
flowDirection,
) //각도 적용
if (turf.booleanWithin(turfPoints, turfPolygon)) { const points = [
let isDrawing = false { x: mousePoint.x - width / 2, y: mousePoint.y - height / 2 },
{ x: mousePoint.x + width / 2, y: mousePoint.y - height / 2 },
{ x: mousePoint.x + width / 2, y: mousePoint.y + height / 2 },
{ x: mousePoint.x - width / 2, y: mousePoint.y + height / 2 },
]
if (isDrawing) return const turfPoints = coordToTurfPolygon(points)
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임
tempModule = new fabric.Rect({ if (turf.booleanWithin(turfPoints, turfPolygon)) {
fill: 'white', let isDrawing = false
stroke: 'black',
strokeWidth: 0.3,
width: width,
height: height,
left: mousePoint.x - width / 2,
top: mousePoint.y - height / 2,
selectable: false,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: 'tempModule',
parentId: moduleSetupSurfaces[i].parentId,
})
canvas?.add(tempModule) //움직여가면서 추가됨 if (isDrawing) return
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임
/** tempModule = new fabric.Rect({
* 스냅기능 fill: 'white',
*/ stroke: 'black',
let snapDistance = 10 strokeWidth: 0.3,
let cellSnapDistance = 20 width: width,
height: height,
left: mousePoint.x - width / 2,
top: mousePoint.y - height / 2,
selectable: false,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: 'tempModule',
parentId: moduleSetupSurfaces[i].parentId,
})
const trestleLeft = moduleSetupSurfaces[i].left canvas?.add(tempModule) //움직여가면서 추가됨
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 let snapDistance = 10
const smallBottom = smallTop + tempModule.height * tempModule.scaleY let cellSnapDistance = 20
const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2
const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2
/** let intvHor =
* 미리 깔아놓은 셀이 있을때 셀에 흡착됨 flowDirection === 'south' || flowDirection === 'north'
*/ ? moduleSetupSurfaces[i].trestleDetail.moduleIntvlHor
if (manualDrawModules) { : moduleSetupSurfaces[i].trestleDetail.moduleIntvlVer
manualDrawModules.forEach((cell) => { let intvVer =
const holdCellLeft = cell.left flowDirection === 'south' || flowDirection === 'north'
const holdCellTop = cell.top ? moduleSetupSurfaces[i].trestleDetail.moduleIntvlVer
const holdCellRight = holdCellLeft + cell.width * cell.scaleX : moduleSetupSurfaces[i].trestleDetail.moduleIntvlHor
const holdCellBottom = holdCellTop + cell.height * cell.scaleY
const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2
const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2
//설치된 셀에 좌측에 스냅 const trestleLeft = moduleSetupSurfaces[i].left
if (Math.abs(smallRight - holdCellLeft) < snapDistance) { const trestleTop = moduleSetupSurfaces[i].top
tempModule.left = holdCellLeft - width - 1 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 - intvHor
}
//설치된 셀에 우측에 스냅
if (Math.abs(smallLeft - holdCellRight) < snapDistance) {
tempModule.left = holdCellRight + intvHor
}
//설치된 셀에 위쪽에 스냅
if (Math.abs(smallBottom - holdCellTop) < snapDistance) {
tempModule.top = holdCellTop - height - intvVer
}
//설치된 셀에 밑쪽에 스냅
if (Math.abs(smallTop - holdCellBottom) < snapDistance) {
tempModule.top = holdCellBottom + intvVer
}
//가운데 -> 가운데
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(smallLeft - holdCellRight) < snapDistance) { if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = holdCellRight + 1 tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2
} }
//설치된 셀에 위쪽에 스냅 // 모듈오른쪽이 세로중앙선에 붙게 스냅
if (Math.abs(smallBottom - holdCellTop) < snapDistance) { if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.top = holdCellTop - height - 1 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) {
if (Math.abs(smallTop - holdCellBottom) < snapDistance) { tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2
tempModule.top = holdCellBottom + 1
} }
//가운데 -> 가운데 // 모듈 밑면이 가로중앙선에 스냅
if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
tempModule.left = holdCellCenterX - width / 2 tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY
} }
//왼쪽 -> 가운데 }
if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX tempModule.setCoords()
canvas?.renderAll()
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 rectPoints = [
{ x: tempModule.left, y: tempModule.top },
{ x: tempModule.left + tempModule.width * tempModule.scaleX, y: tempModule.top },
{
x: tempModule.left + tempModule.width * tempModule.scaleX,
y: tempModule.top + tempModule.height * tempModule.scaleY,
},
{ x: tempModule.left, y: tempModule.top + tempModule.height * tempModule.scaleY },
]
tempModule.set({ points: rectPoints })
const tempTurfModule = polygonToTurfPolygon(tempModule)
//도머 객체를 가져옴
if (batchObjects) {
batchObjects.forEach((object) => {
let dormerTurfPolygon
if (object.type === 'group') {
//도머는 그룹형태임
dormerTurfPolygon = batchObjectGroupToTurfPolygon(object)
} else {
//개구, 그림자
object.set({ points: rectToPolygon(object) })
dormerTurfPolygon = polygonToTurfPolygon(object)
} }
// 오른쪽 -> 가운데
if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인
tempModule.left = holdCellCenterX - width //겹치면 안됨
if (intersection) {
swalFire({ text: getMessage('module.place.overobject') })
isIntersection = false
} }
//세로 가운데 -> 가운데
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 (!isIntersection) return
if (Math.abs(smallTop - trestleTop) < snapDistance) {
tempModule.top = trestleTop
}
// 아래쪽 변에 스냅 tempModule.setCoords() //좌표 재정렬
if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY
}
// 왼쪽변에 스냅 if (turf.booleanWithin(tempTurfModule, turfPolygon)) {
if (Math.abs(smallLeft - trestleLeft) < snapDistance) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음
tempModule.left = trestleLeft const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
} if (!isOverlap) {
//오른쪽 변에 스냅 canvas?.remove(tempModule)
if (Math.abs(smallRight - trestleRight) < snapDistance) { //안겹치면 넣는다
tempModule.left = trestleRight - tempModule.width * tempModule.scaleX // tempModule.setCoords()
} moduleOptions.surfaceId = trestlePolygon.id
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
if (flowDirection === 'south' || flowDirection === 'north') { canvas?.add(manualModule)
// 모듈왼쪽이 세로중앙선에 붙게 스냅 manualDrawModules.push(manualModule)
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
}
}
tempModule.setCoords()
canvas?.renderAll()
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 rectPoints = [
{ x: tempModule.left, y: tempModule.top },
{ x: tempModule.left + tempModule.width * tempModule.scaleX, y: tempModule.top },
{
x: tempModule.left + tempModule.width * tempModule.scaleX,
y: tempModule.top + tempModule.height * tempModule.scaleY,
},
{ x: tempModule.left, y: tempModule.top + tempModule.height * tempModule.scaleY },
]
tempModule.set({ points: rectPoints })
const tempTurfModule = polygonToTurfPolygon(tempModule)
//도머 객체를 가져옴
if (batchObjects) {
batchObjects.forEach((object) => {
let dormerTurfPolygon
if (object.type === 'group') {
//도머는 그룹형태임
dormerTurfPolygon = batchObjectGroupToTurfPolygon(object)
} else { } else {
//개구, 그림자 swalFire({ text: getMessage('module.place.overlab') })
object.set({ points: rectToPolygon(object) })
dormerTurfPolygon = polygonToTurfPolygon(object)
} }
const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인
//겹치면 안됨
if (intersection) {
swalFire({ text: getMessage('module.place.overobject') })
isIntersection = false
}
})
}
if (!isIntersection) return
tempModule.setCoords() //좌표 재정렬
if (turf.booleanWithin(tempTurfModule, turfPolygon)) {
//마우스 클릭시 set으로 해당 위치에 셀을 넣음
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
if (!isOverlap) {
canvas?.remove(tempModule)
//안겹치면 넣는다
// tempModule.setCoords()
moduleOptions.surfaceId = trestlePolygon.id
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
canvas?.add(manualModule)
manualDrawModules.push(manualModule)
} else { } else {
swalFire({ text: getMessage('module.place.overlab') }) swalFire({ text: getMessage('module.place.out') })
} }
} else {
swalFire({ text: getMessage('module.place.out') })
} }
} })
}) }
} else {
removeMouseEvent('mouse:up')
removeMouseEvent('mouse:move')
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임
} }
} }
@ -511,8 +538,6 @@ export function useModuleBasicSetting() {
} }
}) })
// console.log('moduleIsSetup', moduleIsSetup)
// if (moduleIsSetup.length > 0) { // if (moduleIsSetup.length > 0) {
// swalFire({ text: 'alert 아이콘 테스트입니다.', icon: 'error' }) // swalFire({ text: 'alert 아이콘 테스트입니다.', icon: 'error' })
// } // }
@ -620,23 +645,29 @@ export function useModuleBasicSetting() {
* @returns {object} 모듈의 너비와 높이 * @returns {object} 모듈의 너비와 높이
*/ */
const getModuleWidthHeight = (maxLengthLine, moduleSetupSurface, module) => { const getModuleWidthHeight = (maxLengthLine, moduleSetupSurface, module) => {
let width = let tmpWidth =
(maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? Number(module.longAxis) : Number(module.shortAxis)) / 10 (maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? Number(module.longAxis) : Number(module.shortAxis)) / 10
let height = let tmpHeight =
(maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? Number(module.shortAxis) : Number(module.longAxis)) / 10 (maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? Number(module.shortAxis) : Number(module.longAxis)) / 10
//배치면때는 방향쪽으로 패널이 넓게 누워져야함 //배치면때는 방향쪽으로 패널이 넓게 누워져야함
if (moduleSetupSurface.flowDirection !== undefined) { if (moduleSetupSurface.flowDirection !== undefined) {
width = tmpWidth =
(moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' (moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north'
? Number(module.longAxis) ? Number(module.longAxis)
: Number(module.shortAxis)) / 10 : Number(module.shortAxis)) / 10
height = tmpHeight =
(moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' (moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north'
? Number(module.shortAxis) ? Number(module.shortAxis)
: Number(module.longAxis)) / 10 : Number(module.longAxis)) / 10
} }
return { width, height }
return calculateVisibleModuleHeight(
tmpWidth,
tmpHeight,
getDegreeByChon(moduleSetupSurface.roofMaterial.pitch),
moduleSetupSurface.flowDirection,
) //각도 적
} }
const getFlowLines = (moduleSetupSurface, module) => { const getFlowLines = (moduleSetupSurface, module) => {
@ -649,13 +680,19 @@ export function useModuleBasicSetting() {
right: leftRightFlowLine(moduleSetupSurface, module).find((obj) => obj.target === 'right'), right: leftRightFlowLine(moduleSetupSurface, module).find((obj) => obj.target === 'right'),
} }
} }
console.log('flowLines', flowLines)
return flowLines return flowLines
} }
const downFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { const downFlowSetupModule = (
surfaceMaxLines,
maxLengthLine,
moduleSetupArray,
moduleSetupSurface,
containsBatchObjects,
isCenter = false,
intvHor,
intvVer,
) => {
let setupModule = [] let setupModule = []
checkedModule.forEach((module, index) => { checkedModule.forEach((module, index) => {
@ -705,9 +742,9 @@ export function useModuleBasicSetting() {
if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
for (let j = 0; j < diffTopEndPoint; j++) { for (let j = 0; j < diffTopEndPoint; j++) {
bottomMargin = 0 bottomMargin = j === 0 ? 0 : intvVer * j
for (let i = 0; i <= totalWidth; i++) { for (let i = 0; i <= totalWidth; i++) {
leftMargin = 0 leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0 chidoriLength = 0
if (isChidori) { if (isChidori) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 chidoriLength = j % 2 === 0 ? 0 : width / 2
@ -757,7 +794,16 @@ export function useModuleBasicSetting() {
}) })
} }
const leftFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { const leftFlowSetupModule = (
surfaceMaxLines,
maxLengthLine,
moduleSetupArray,
moduleSetupSurface,
containsBatchObjects,
isCenter = false,
intvHor,
intvVer,
) => {
let setupModule = [] let setupModule = []
checkedModule.forEach((module, index) => { checkedModule.forEach((module, index) => {
@ -794,23 +840,23 @@ export function useModuleBasicSetting() {
let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint)
let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음
if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사
for (let i = 0; i <= totalWidth; i++) { for (let i = 0; i <= totalWidth; i++) {
bottomMargin = 0 bottomMargin = i === 0 ? 0 : intvHor * i
for (let j = 0; j < totalHeight; j++) { for (let j = 0; j < totalHeight; j++) {
leftMargin = 0 leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0 chidoriLength = 0
if (isChidori) { if (isChidori) {
chidoriLength = i % 2 === 0 ? 0 : height / 2 chidoriLength = i % 2 === 0 ? 0 : height / 2
} }
square = [ square = [
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength],
[startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength],
[startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin - chidoriLength], [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength],
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin - chidoriLength], [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength],
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin - chidoriLength], [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength],
] ]
let squarePolygon = turf.polygon([square]) let squarePolygon = turf.polygon([square])
@ -847,7 +893,16 @@ export function useModuleBasicSetting() {
}) })
} }
const topFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { const topFlowSetupModule = (
surfaceMaxLines,
maxLengthLine,
moduleSetupArray,
moduleSetupSurface,
containsBatchObjects,
isCenter = false,
intvHor,
intvVer,
) => {
let setupModule = [] let setupModule = []
checkedModule.forEach((module, index) => { checkedModule.forEach((module, index) => {
@ -896,14 +951,17 @@ export function useModuleBasicSetting() {
let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음
if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
startColPoint = Math.round(startColPoint - intvHor * diffRightEndPoint)
for (let j = 0; j < diffBottomEndPoint; j++) { for (let j = 0; j < diffBottomEndPoint; j++) {
bottomMargin = 0 bottomMargin = j === 0 ? 0 : intvVer * j
for (let i = 0; i < diffRightEndPoint; i++) { for (let i = 0; i < diffRightEndPoint; i++) {
leftMargin = 0 leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0 chidoriLength = 0
if (isChidori) { if (isChidori) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 chidoriLength = j % 2 === 0 ? 0 : width / 2
} }
square = [ square = [
[startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin],
[startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
@ -947,7 +1005,16 @@ export function useModuleBasicSetting() {
}) })
} }
const rightFlowSetupModule = (surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, isCenter = false) => { const rightFlowSetupModule = (
surfaceMaxLines,
maxLengthLine,
moduleSetupArray,
moduleSetupSurface,
containsBatchObjects,
isCenter = false,
intvHor,
intvVer,
) => {
let setupModule = [] let setupModule = []
checkedModule.forEach((module, index) => { checkedModule.forEach((module, index) => {
@ -986,20 +1053,21 @@ export function useModuleBasicSetting() {
if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사
for (let i = 0; i <= totalWidth; i++) { for (let i = 0; i <= totalWidth; i++) {
bottomMargin = 0 bottomMargin = i === 0 ? 0 : -(intvHor * i)
for (let j = 0; j < totalHeight; j++) { for (let j = 0; j < totalHeight; j++) {
leftMargin = 0 leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0 chidoriLength = 0
if (isChidori) { if (isChidori) {
chidoriLength = i % 2 === 0 ? 0 : height / 2 chidoriLength = i % 2 === 0 ? 0 : height / 2
} }
square = [ square = [
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength],
[startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], [startPoint.x1 - width * i - width + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength],
[startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin + chidoriLength], [startPoint.x1 - width * i - width + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + height + leftMargin + chidoriLength],
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin + chidoriLength], [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + height + leftMargin + chidoriLength],
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin + chidoriLength], [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength],
] ]
let squarePolygon = turf.polygon([square]) let squarePolygon = turf.polygon([square])
@ -1048,48 +1116,59 @@ export function useModuleBasicSetting() {
return acc.length > cur.length ? acc : cur return acc.length > cur.length ? acc : cur
}) })
const flowDirection = moduleSetupSurface.flowDirection
let intvHor =
flowDirection === 'south' || flowDirection === 'north'
? moduleSetupSurface.trestleDetail.moduleIntvlHor
: moduleSetupSurface.trestleDetail.moduleIntvlVer
let intvVer =
flowDirection === 'south' || flowDirection === 'north'
? moduleSetupSurface.trestleDetail.moduleIntvlVer
: moduleSetupSurface.trestleDetail.moduleIntvlHor
//처마면 배치 //처마면 배치
if (setupLocation === 'eaves') { if (setupLocation === 'eaves') {
// 흐름방향이 남쪽일때 // 흐름방향이 남쪽일때
if (moduleSetupSurface.flowDirection === 'south') { if (moduleSetupSurface.flowDirection === 'south') {
downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'west') { if (moduleSetupSurface.flowDirection === 'west') {
leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'east') { if (moduleSetupSurface.flowDirection === 'east') {
rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'north') { if (moduleSetupSurface.flowDirection === 'north') {
topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
} else if (setupLocation === 'ridge') { } else if (setupLocation === 'ridge') {
//용마루 //용마루
if (moduleSetupSurface.flowDirection === 'south') { if (moduleSetupSurface.flowDirection === 'south') {
topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'west') { if (moduleSetupSurface.flowDirection === 'west') {
rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'east') { if (moduleSetupSurface.flowDirection === 'east') {
leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'north') { if (moduleSetupSurface.flowDirection === 'north') {
downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects) downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer)
} }
} else if (setupLocation === 'center') { } else if (setupLocation === 'center') {
//중가면 //중가면
if (moduleSetupSurface.flowDirection === 'south') { if (moduleSetupSurface.flowDirection === 'south') {
downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'west') { if (moduleSetupSurface.flowDirection === 'west') {
leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'east') { if (moduleSetupSurface.flowDirection === 'east') {
rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer)
} }
if (moduleSetupSurface.flowDirection === 'north') { if (moduleSetupSurface.flowDirection === 'north') {
topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true) topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer)
} }
} }

View File

@ -69,7 +69,7 @@ export function useModulePlace() {
.getObjects() .getObjects()
.filter((surface) => surface.name === 'moduleSetupSurface' && surface.parentId === roof.id) .filter((surface) => surface.name === 'moduleSetupSurface' && surface.parentId === roof.id)
.forEach((surface) => { .forEach((surface) => {
surface.set({ trestleDetail: detail.data }) surface.set({ trestleDetail: detail.data, roofMaterial: roof.roofMaterial })
}) })
} }
}) })

View File

@ -379,3 +379,8 @@ export const checkedModuleState = atom({
default: [], default: [],
dangerouslyAllowMutability: true, dangerouslyAllowMutability: true,
}) })
export const isManualModuleSetupState = atom({
key: 'isManualModuleSetupState',
default: false,
})

View File

@ -1009,3 +1009,25 @@ export function polygonToTurfPolygon(object, current = false) {
}, },
) )
} }
export function calculateVisibleModuleHeight(sourceWidth, sourceHeight, angle, direction) {
// 각도를 라디안으로 변환
const radians = (angle * Math.PI) / 180
let visibleWidth = sourceWidth // 가로는 기울어도 변하지 않음
let visibleHeight = sourceHeight * Math.cos(radians) // 세로는 각도에 따라 줄어듦
// 가로와 세로의 보이는 크기 계산
if (direction === 'south' || direction === 'north') {
visibleWidth = sourceWidth // 가로는 기울어도 변하지 않음
visibleHeight = sourceHeight * Math.cos(radians) // 세로는 각도에 따라 줄어듦
} else {
visibleWidth = sourceWidth * Math.cos(radians) // 가로는 기울어도 변하지 않음
visibleHeight = sourceHeight // 세로는 각도에 따라 줄어듦
}
return {
width: Number(visibleWidth.toFixed(1)),
height: Number(visibleHeight.toFixed(1)), // 소수점 두 자리로 고정
}
}