Compare commits
No commits in common. "d95e5d63e0409ab7a361f51c0a2a1886fdf97b4c" and "c6e0c12394bfbed6420b3dfef1af5bd87a5db175" have entirely different histories.
d95e5d63e0
...
c6e0c12394
@ -98,10 +98,6 @@ export default function Join() {
|
||||
alert(getMessage('common.message.required.data', [getMessage('join.sub1.fax')]))
|
||||
faxRef.current.focus()
|
||||
return false
|
||||
}else if (!telRegex.test(fax)) {
|
||||
alert(getMessage('join.validation.check1', [getMessage('join.sub1.fax')]))
|
||||
faxRef.current.focus()
|
||||
return false
|
||||
}
|
||||
|
||||
const bizNo = formData.get('bizNo')
|
||||
@ -178,10 +174,6 @@ export default function Join() {
|
||||
alert(getMessage('common.message.required.data', [getMessage('join.sub2.fax')]))
|
||||
userFaxRef.current.focus()
|
||||
return false
|
||||
} else if (!telRegex.test(userFax)) {
|
||||
alert(getMessage('join.validation.check1', [getMessage('join.sub2.fax')]))
|
||||
userFaxRef.current.focus()
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
@ -357,15 +349,7 @@ export default function Join() {
|
||||
<th>{getMessage('join.sub1.fax')}<span className="important">*</span></th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="fax"
|
||||
name="fax"
|
||||
className="input-light"
|
||||
maxLength={15}
|
||||
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={faxRef} />
|
||||
<input type="text" id="fax" name="fax" className="input-light" maxLength={15} onChange={inputNumberCheck} ref={faxRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -482,8 +466,7 @@ export default function Join() {
|
||||
name="userFax"
|
||||
className="input-light"
|
||||
maxLength={15}
|
||||
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
||||
onChange={inputTelNumberCheck}
|
||||
onChange={inputNumberCheck}
|
||||
ref={userFaxRef}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -859,7 +859,7 @@ const Trestle = forwardRef((props, ref) => {
|
||||
type="checkbox"
|
||||
id={`ch01`}
|
||||
disabled={!cvrYn || cvrYn === 'N'}
|
||||
checked={cvrChecked ?? false}
|
||||
checked={cvrChecked || true}
|
||||
// onChange={() => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, cvrChecked: !trestleState.cvrChecked } })}
|
||||
onChange={() => setCvrChecked(!cvrChecked)}
|
||||
/>
|
||||
|
||||
@ -124,9 +124,6 @@ export default function CircuitTrestleSetting({ id }) {
|
||||
*/
|
||||
const validateModuleSizeForRack = (surface) => {
|
||||
const { modules, direction, trestleDetail } = surface
|
||||
if (!trestleDetail) {
|
||||
return true // 상세 정보 없음
|
||||
}
|
||||
const { rackYn, moduleIntvlHor, moduleIntvlVer } = trestleDetail
|
||||
|
||||
if (rackYn === 'N' || !modules || modules.length < 2) {
|
||||
|
||||
@ -13,7 +13,6 @@ import { usePolygon } from '@/hooks/usePolygon'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
import { BATCH_TYPE } from '@/common/common'
|
||||
import { useMouse } from '@/hooks/useMouse'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
|
||||
export function useCommonUtils() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
@ -618,168 +617,6 @@ export function useCommonUtils() {
|
||||
|
||||
const buttonAct = dormerName == BATCH_TYPE.TRIANGLE_DORMER ? 3 : 4
|
||||
applyDormers(dormerParams, buttonAct)
|
||||
} else if (obj.name === 'roof' && obj.type === 'QPolygon') {
|
||||
// roof(QPolygon) 객체는 순환 참조(lines[].parent -> polygon)로 인해
|
||||
// fabric.clone() 사용 시 Maximum call stack size exceeded 에러 발생
|
||||
// getCurrentPoints()를 사용하여 새 QPolygon을 직접 생성
|
||||
|
||||
// 원본 객체의 line attributes 복사 (순환 참조 제거)
|
||||
const lineAttributes = obj.lines.map((line) => ({
|
||||
type: line.attributes?.type,
|
||||
offset: line.attributes?.offset,
|
||||
actualSize: line.attributes?.actualSize,
|
||||
planeSize: line.attributes?.planeSize,
|
||||
}))
|
||||
|
||||
// 원본 roof의 자식 오브젝트들 찾기 (개구, 그림자, 도머 등)
|
||||
const childObjectTypes = [BATCH_TYPE.OPENING, BATCH_TYPE.SHADOW, BATCH_TYPE.TRIANGLE_DORMER, BATCH_TYPE.PENTAGON_DORMER]
|
||||
const childObjects = canvas.getObjects().filter(
|
||||
(o) => o.parentId === obj.id && childObjectTypes.includes(o.name)
|
||||
)
|
||||
|
||||
// 원본 roof 중심점 계산
|
||||
const originalPoints = obj.getCurrentPoints()
|
||||
const originalCenterX = originalPoints.reduce((sum, p) => sum + p.x, 0) / originalPoints.length
|
||||
const originalCenterY = originalPoints.reduce((sum, p) => sum + p.y, 0) / originalPoints.length
|
||||
|
||||
let clonedObj = null
|
||||
let clonedChildren = []
|
||||
|
||||
addCanvasMouseEventListener('mouse:move', (e) => {
|
||||
const pointer = canvas?.getPointer(e.e)
|
||||
|
||||
// 이전 임시 객체들 제거
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((o) => o.name === 'clonedObj' || o.name === 'clonedChildTemp')
|
||||
.forEach((o) => canvas?.remove(o))
|
||||
|
||||
// 새 QPolygon 생성 (매 move마다 생성하여 위치 업데이트)
|
||||
const currentPoints = obj.getCurrentPoints()
|
||||
const centerX = currentPoints.reduce((sum, p) => sum + p.x, 0) / currentPoints.length
|
||||
const centerY = currentPoints.reduce((sum, p) => sum + p.y, 0) / currentPoints.length
|
||||
|
||||
// 이동 오프셋 계산
|
||||
const offsetX = pointer.x - centerX
|
||||
const offsetY = pointer.y - centerY
|
||||
|
||||
// 포인터 위치로 이동된 새 points 계산
|
||||
const newPoints = currentPoints.map((p) => ({
|
||||
x: p.x + offsetX,
|
||||
y: p.y + offsetY,
|
||||
}))
|
||||
|
||||
clonedObj = new QPolygon(newPoints, {
|
||||
fill: obj.fill || 'transparent',
|
||||
stroke: obj.stroke || 'black',
|
||||
strokeWidth: obj.strokeWidth || 1,
|
||||
fontSize: 0, // 이동 중에는 lengthText 생성하지 않음 (fontSize=0이면 addLengthText가 스킵됨)
|
||||
selectable: true,
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
name: 'clonedObj',
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
pitch: obj.pitch,
|
||||
surfaceId: obj.surfaceId,
|
||||
sort: false,
|
||||
}, canvas)
|
||||
|
||||
canvas.add(clonedObj)
|
||||
|
||||
// 자식 오브젝트들도 이동해서 미리보기 표시
|
||||
clonedChildren = []
|
||||
childObjects.forEach((child) => {
|
||||
child.clone((clonedChild) => {
|
||||
clonedChild.set({
|
||||
left: child.left + offsetX,
|
||||
top: child.top + offsetY,
|
||||
name: 'clonedChildTemp',
|
||||
selectable: false,
|
||||
evented: false,
|
||||
})
|
||||
clonedChildren.push({ original: child, cloned: clonedChild })
|
||||
canvas.add(clonedChild)
|
||||
})
|
||||
})
|
||||
|
||||
canvas.renderAll()
|
||||
})
|
||||
|
||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||
if (!clonedObj) return
|
||||
|
||||
const newRoofId = uuidv4()
|
||||
|
||||
clonedObj.set({
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
name: 'roof',
|
||||
editable: false,
|
||||
selectable: true,
|
||||
id: newRoofId,
|
||||
direction: obj.direction,
|
||||
directionText: obj.directionText,
|
||||
roofMaterial: obj.roofMaterial,
|
||||
stroke: 'black',
|
||||
evented: true,
|
||||
isFixed: false,
|
||||
fontSize: lengthTextFont.fontSize.value, // 최종 확정 시 fontSize 설정
|
||||
})
|
||||
|
||||
// line attributes 복원
|
||||
lineAttributes.forEach((attr, index) => {
|
||||
if (clonedObj.lines[index]) {
|
||||
clonedObj.lines[index].set({ attributes: attr })
|
||||
}
|
||||
})
|
||||
|
||||
// 임시 자식 오브젝트들 제거
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((o) => o.name === 'clonedChildTemp')
|
||||
.forEach((o) => canvas?.remove(o))
|
||||
|
||||
// 자식 오브젝트들 최종 복사 (새 roof의 id를 parentId로 설정)
|
||||
const pointer = canvas?.getPointer(e.e)
|
||||
const currentPoints = obj.getCurrentPoints()
|
||||
const centerX = currentPoints.reduce((sum, p) => sum + p.x, 0) / currentPoints.length
|
||||
const centerY = currentPoints.reduce((sum, p) => sum + p.y, 0) / currentPoints.length
|
||||
const offsetX = pointer.x - centerX
|
||||
const offsetY = pointer.y - centerY
|
||||
|
||||
childObjects.forEach((child) => {
|
||||
child.clone((clonedChild) => {
|
||||
clonedChild.set({
|
||||
left: child.left + offsetX,
|
||||
top: child.top + offsetY,
|
||||
id: uuidv4(),
|
||||
parentId: newRoofId, // 새 roof의 id를 부모로 설정
|
||||
name: child.name,
|
||||
selectable: true,
|
||||
evented: true,
|
||||
})
|
||||
// 그룹 객체인 경우 groupId도 새로 설정
|
||||
if (clonedChild.type === 'group') {
|
||||
clonedChild.set({ groupId: uuidv4() })
|
||||
}
|
||||
canvas.add(clonedChild)
|
||||
})
|
||||
})
|
||||
|
||||
clonedObj.fire('polygonMoved')
|
||||
clonedObj.fire('modified')
|
||||
clonedObj.setCoords()
|
||||
canvas.setActiveObject(clonedObj)
|
||||
canvas.renderAll()
|
||||
addLengthText(clonedObj) // fontSize가 설정된 후 lengthText 추가
|
||||
drawDirectionArrow(clonedObj)
|
||||
|
||||
initEvent()
|
||||
})
|
||||
} else {
|
||||
let clonedObj = null
|
||||
|
||||
@ -818,6 +655,32 @@ export function useCommonUtils() {
|
||||
//객체가 그룹일 경우에는 그룹 아이디를 따로 넣어준다
|
||||
if (clonedObj.type === 'group') clonedObj.set({ groupId: uuidv4() })
|
||||
|
||||
//배치면일 경우
|
||||
if (obj.name === 'roof') {
|
||||
clonedObj.canvas = canvas // canvas 참조 설정
|
||||
clonedObj.set({
|
||||
direction: obj.direction,
|
||||
directionText: obj.directionText,
|
||||
roofMaterial: obj.roofMaterial,
|
||||
stroke: 'black', // 복사된 객체는 선택 해제 상태의 색상으로 설정
|
||||
selectable: true, // 선택 가능하도록 설정
|
||||
evented: true, // 마우스 이벤트를 받을 수 있도록 설정
|
||||
isFixed: false, // containsPoint에서 특별 처리 방지
|
||||
})
|
||||
|
||||
obj.lines.forEach((line, index) => {
|
||||
clonedObj.lines[index].set({ attributes: line.attributes })
|
||||
})
|
||||
|
||||
clonedObj.fire('polygonMoved') // 내부 좌표 재계산 (points, pathOffset)
|
||||
clonedObj.fire('modified')
|
||||
clonedObj.setCoords() // 모든 속성 설정 후 좌표 업데이트
|
||||
canvas.setActiveObject(clonedObj)
|
||||
canvas.renderAll()
|
||||
addLengthText(clonedObj) //수치 추가
|
||||
drawDirectionArrow(clonedObj) //방향 화살표 추가
|
||||
}
|
||||
|
||||
initEvent()
|
||||
})
|
||||
}
|
||||
|
||||
@ -749,7 +749,7 @@ export function useModule() {
|
||||
const copyModules = []
|
||||
const moduleSetupSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)
|
||||
let isWarning = false
|
||||
const { moduleIntvlHor = 0, moduleIntvlVer = 0 } = moduleSetupSurface.trestleDetail || {}
|
||||
const { moduleIntvlHor, moduleIntvlVer } = moduleSetupSurface.trestleDetail
|
||||
canvas.discardActiveObject()
|
||||
targetModules.forEach((module) => {
|
||||
const { top, left } = getPosotion(module, type, moduleIntvlHor, true)
|
||||
@ -859,7 +859,7 @@ export function useModule() {
|
||||
const copyModules = []
|
||||
const moduleSetupSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)
|
||||
let isWarning = false
|
||||
const { moduleIntvlHor = 0, moduleIntvlVer = 0 } = moduleSetupSurface.trestleDetail || {}
|
||||
const { moduleIntvlHor, moduleIntvlVer } = moduleSetupSurface.trestleDetail
|
||||
canvas.discardActiveObject()
|
||||
targetModules.forEach((module) => {
|
||||
const { top, left } = getPosotion(module, type, moduleIntvlVer, true)
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
import { calculateVisibleModuleHeight, getDegreeByChon, polygonToTurfPolygon, rectToPolygon, toFixedWithoutRounding } from '@/util/canvas-util'
|
||||
import '@/util/fabric-extensions' // fabric 객체들에 getCurrentPoints 메서드 추가
|
||||
import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom'
|
||||
import offsetPolygon, { calculateAngle, cleanSelfIntersectingPolygon, createLinesFromPolygon } from '@/util/qpolygon-utils'
|
||||
import offsetPolygon, { calculateAngle, createLinesFromPolygon, cleanSelfIntersectingPolygon } from '@/util/qpolygon-utils'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { BATCH_TYPE, LINE_TYPE, MODULE_SETUP_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||
@ -338,27 +338,10 @@ export function useModuleBasicSetting(tabNum) {
|
||||
})
|
||||
|
||||
let isNorth = false
|
||||
const defaultTrestleDetail = {
|
||||
rackYn: 'N',
|
||||
moduleIntvlHor: +roofSizeSet === 3 ? 300 : 0,
|
||||
moduleIntvlVer: +roofSizeSet === 3 ? 100 : 0,
|
||||
rack: null,
|
||||
rackQty: 0,
|
||||
rackIntvlPct: 0,
|
||||
cvrPlvrYn: 'N',
|
||||
lessSupFitIntvlPct: 0,
|
||||
lessSupFitQty: 0,
|
||||
}
|
||||
|
||||
const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
|
||||
const normalizedTrestleDetail = trestleDetail
|
||||
? { ...defaultTrestleDetail, ...trestleDetail }
|
||||
: isExistSurface?.trestleDetail
|
||||
? { ...defaultTrestleDetail, ...isExistSurface.trestleDetail }
|
||||
: defaultTrestleDetail
|
||||
|
||||
if (isExistSurface) {
|
||||
isExistSurface.set({ trestleDetail: normalizedTrestleDetail })
|
||||
if (canvasSetting.roofSizeSet != '3') {
|
||||
//북면이 있지만
|
||||
if (roof.directionText && roof.directionText.indexOf('北') > -1) {
|
||||
@ -441,7 +424,7 @@ export function useModuleBasicSetting(tabNum) {
|
||||
originY: 'center',
|
||||
modules: [],
|
||||
roofMaterial: roof.roofMaterial,
|
||||
trestleDetail: normalizedTrestleDetail,
|
||||
trestleDetail: trestleDetail,
|
||||
isNorth: isNorth,
|
||||
perPixelTargetFind: true,
|
||||
isSaleStoreNorthFlg: moduleSelectionData.common.saleStoreNorthFlg == '1' ? true : false, //북면설치가능점 여부
|
||||
@ -2122,7 +2105,7 @@ export function useModuleBasicSetting(tabNum) {
|
||||
}
|
||||
|
||||
//흐름 방향이 남쪽(아래)
|
||||
const downFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef) => {
|
||||
const downFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer) => {
|
||||
let setupModule = []
|
||||
|
||||
const trestleDetailData = moduleSetupSurface.trestleDetail
|
||||
@ -2201,11 +2184,6 @@ export function useModuleBasicSetting(tabNum) {
|
||||
calcAreaHeight = isNaN(calcAreaHeight) ? moduleSetupSurface.height : calcAreaHeight
|
||||
let calcModuleHeightCount = calcAreaHeight / (height + intvVer)
|
||||
|
||||
// 대칭 지붕을 위해 south의 calcAreaWidth 저장 (north에서 참조)
|
||||
if (symmetricWidthRef && moduleIndex === 0) {
|
||||
symmetricWidthRef.south = calcAreaWidth
|
||||
}
|
||||
|
||||
if (type === MODULE_SETUP_TYPE.LAYOUT) {
|
||||
calcModuleWidthCount = layoutCol > calcModuleWidthCount ? calcModuleWidthCount : layoutCol
|
||||
calcModuleHeightCount = layoutRow
|
||||
@ -2309,7 +2287,7 @@ export function useModuleBasicSetting(tabNum) {
|
||||
}
|
||||
}
|
||||
|
||||
const topFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef) => {
|
||||
const topFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer) => {
|
||||
let setupModule = []
|
||||
|
||||
const trestleDetailData = moduleSetupSurface.trestleDetail
|
||||
@ -2388,22 +2366,9 @@ export function useModuleBasicSetting(tabNum) {
|
||||
//육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음
|
||||
const moduleArray = []
|
||||
|
||||
// 북쪽: 남쪽과 동일한 방식으로 계산 (대칭을 위해)
|
||||
let calcAreaWidth = Math.abs(flowLines.right.x1 - flowLines.left.x1) //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직
|
||||
|
||||
// 대칭 지붕: south의 calcAreaWidth가 있고 north의 값이 south보다 10% 이상 작으면 south 값 사용
|
||||
if (symmetricWidthRef?.south && calcAreaWidth < symmetricWidthRef.south * 0.9) {
|
||||
// flowLines 좌표도 보정 (중심점 유지하면서 너비 확장)
|
||||
const center = (flowLines.right.x1 + flowLines.left.x1) / 2
|
||||
const halfWidth = symmetricWidthRef.south / 2
|
||||
flowLines.left.x1 = center - halfWidth
|
||||
flowLines.right.x1 = center + halfWidth
|
||||
|
||||
calcAreaWidth = symmetricWidthRef.south
|
||||
}
|
||||
|
||||
let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직
|
||||
let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직
|
||||
let calcAreaHeight = Math.abs(flowLines.bottom.y1 - flowLines.top.y1)
|
||||
let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1
|
||||
let calcModuleHeightCount = calcAreaHeight / (height + intvVer)
|
||||
|
||||
//단수지정 자동이면
|
||||
@ -2504,7 +2469,7 @@ export function useModuleBasicSetting(tabNum) {
|
||||
|
||||
//남, 북과 같은 로직으로 적용하려면 좌우는 열 -> 행 으로 그려야함
|
||||
//변수명은 bottom 기준으로 작성하여 동일한 방향으로 진행한다
|
||||
const leftFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef) => {
|
||||
const leftFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer) => {
|
||||
let setupModule = []
|
||||
|
||||
const trestleDetailData = moduleSetupSurface.trestleDetail //가대 상세 데이터
|
||||
@ -2592,11 +2557,6 @@ export function useModuleBasicSetting(tabNum) {
|
||||
let calcAreaHeight = Math.abs(flowLines.right.x1 - flowLines.left.x1)
|
||||
let calcModuleHeightCount = calcAreaHeight / (width + intvVer)
|
||||
|
||||
// 대칭 지붕을 위해 west의 calcAreaWidth 저장 (east에서 참조)
|
||||
if (symmetricWidthRef && moduleIndex === 0) {
|
||||
symmetricWidthRef.west = calcAreaWidth
|
||||
}
|
||||
|
||||
//단수지정 자동이면
|
||||
if (type === MODULE_SETUP_TYPE.LAYOUT) {
|
||||
calcModuleWidthCount = layoutCol > calcModuleWidthCount ? calcModuleWidthCount : layoutCol
|
||||
@ -2695,7 +2655,7 @@ export function useModuleBasicSetting(tabNum) {
|
||||
}
|
||||
}
|
||||
|
||||
const rightFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef) => {
|
||||
const rightFlowSetupModule = (maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer) => {
|
||||
let setupModule = []
|
||||
|
||||
const trestleDetailData = moduleSetupSurface.trestleDetail //가대 상세 데이터
|
||||
@ -2776,22 +2736,9 @@ export function useModuleBasicSetting(tabNum) {
|
||||
//육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음
|
||||
const moduleArray = []
|
||||
|
||||
// 동쪽: 서쪽과 동일한 방식으로 계산 (대칭을 위해)
|
||||
let calcAreaWidth = Math.abs(flowLines.bottom.y1 - flowLines.top.y1) //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직
|
||||
|
||||
// 대칭 지붕: west의 calcAreaWidth가 있고 east의 값이 west보다 10% 이상 작으면 west 값 사용
|
||||
if (symmetricWidthRef?.west && calcAreaWidth < symmetricWidthRef.west * 0.9) {
|
||||
// flowLines 좌표도 보정 (중심점 유지하면서 높이 확장)
|
||||
const center = (flowLines.bottom.y1 + flowLines.top.y1) / 2
|
||||
const halfHeight = symmetricWidthRef.west / 2
|
||||
flowLines.top.y1 = center - halfHeight
|
||||
flowLines.bottom.y1 = center + halfHeight
|
||||
|
||||
calcAreaWidth = symmetricWidthRef.west
|
||||
}
|
||||
|
||||
let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직
|
||||
let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직
|
||||
let calcAreaHeight = Math.abs(flowLines.right.x1 - flowLines.left.x1)
|
||||
let calcAreaHeight = flowLines.right.x1 - flowLines.left.x1
|
||||
let calcModuleHeightCount = calcAreaHeight / (width + intvVer)
|
||||
|
||||
//단수지정 자동이면
|
||||
@ -2801,14 +2748,15 @@ export function useModuleBasicSetting(tabNum) {
|
||||
}
|
||||
|
||||
let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀
|
||||
let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount)
|
||||
// let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다
|
||||
let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다
|
||||
|
||||
let calcStartPoint = flowLines.top.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * height) / 2 : 0 //반씩 나눠서 중앙에 맞춤 left 높이 기준으로 양변이 직선일때만 가운데 정렬
|
||||
let startPointX = flowLines.bottom.y1 - calcStartPoint //시작점을 만든다
|
||||
let startPointX = flowLines.bottom.y2 - calcStartPoint //시작점을 만든다
|
||||
|
||||
//근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다
|
||||
if (flowLines.top.type === 'curve' && flowLines.bottom.type === 'curve') {
|
||||
startPointX = flowLines.bottom.y1 - (calcAreaWidth - totalModuleWidthCount * height) / 2
|
||||
startPointX = flowLines.bottom.y2 - (calcAreaWidth - totalModuleWidthCount * height) / 2
|
||||
}
|
||||
|
||||
let heightMargin = 0
|
||||
@ -2895,18 +2843,7 @@ export function useModuleBasicSetting(tabNum) {
|
||||
}
|
||||
}
|
||||
|
||||
// 대칭 지붕을 위한 calcAreaWidth 공유 객체 (south→north, west→east)
|
||||
const symmetricWidthRef = { south: null, west: null }
|
||||
|
||||
// 대칭 보정을 위해 south/west가 north/east보다 먼저 처리되도록 정렬
|
||||
const directionOrder = { south: 0, west: 1, north: 2, east: 3 }
|
||||
const sortedModuleSetupSurfaces = [...moduleSetupSurfaces].sort((a, b) => {
|
||||
const orderA = directionOrder[a.direction] ?? 4
|
||||
const orderB = directionOrder[b.direction] ?? 4
|
||||
return orderA - orderB
|
||||
})
|
||||
|
||||
sortedModuleSetupSurfaces.forEach((moduleSetupSurface, index) => {
|
||||
moduleSetupSurfaces.forEach((moduleSetupSurface, index) => {
|
||||
moduleSetupSurface.fire('mousedown')
|
||||
const moduleSetupArray = []
|
||||
|
||||
@ -2932,30 +2869,30 @@ export function useModuleBasicSetting(tabNum) {
|
||||
if (setupLocation === 'eaves') {
|
||||
// 흐름방향이 남쪽일때
|
||||
if (moduleSetupSurface.direction === 'south') {
|
||||
downFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
downFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
if (moduleSetupSurface.direction === 'west') {
|
||||
leftFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
leftFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
if (moduleSetupSurface.direction === 'east') {
|
||||
rightFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
rightFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
if (moduleSetupSurface.direction === 'north') {
|
||||
topFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
topFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
} else if (setupLocation === 'ridge') {
|
||||
//용마루
|
||||
if (moduleSetupSurface.direction === 'south') {
|
||||
topFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
topFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
if (moduleSetupSurface.direction === 'west') {
|
||||
rightFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
rightFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
if (moduleSetupSurface.direction === 'east') {
|
||||
leftFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
leftFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
if (moduleSetupSurface.direction === 'north') {
|
||||
downFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer, symmetricWidthRef)
|
||||
downFlowSetupModule(maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, intvHor, intvVer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3135,26 +3072,13 @@ export function useModuleBasicSetting(tabNum) {
|
||||
type: 'flat',
|
||||
}
|
||||
} else {
|
||||
// NaN 체크: offset이 너무 커서 꼭짓점을 넘어가면 NaN 발생
|
||||
if (isNaN(pointX1) || isNaN(pointX2) || isNaN(pointY1) || isNaN(pointY2)) {
|
||||
// NaN이면 꼭짓점 좌표 사용 (모듈 설치 영역 없음)
|
||||
rtnObj = {
|
||||
target: index === 0 ? 'bottom' : 'top',
|
||||
x1: center.x1,
|
||||
y1: center.y1,
|
||||
x2: center.x1,
|
||||
y2: center.y1,
|
||||
type: 'curve',
|
||||
}
|
||||
} else {
|
||||
rtnObj = {
|
||||
target: index === 0 ? 'bottom' : 'top',
|
||||
x1: pointX1,
|
||||
y1: pointY1,
|
||||
x2: pointX2,
|
||||
y2: pointY2,
|
||||
type: 'curve',
|
||||
}
|
||||
rtnObj = {
|
||||
target: index === 0 ? 'bottom' : 'top',
|
||||
x1: pointX1,
|
||||
y1: pointY1,
|
||||
x2: pointX2,
|
||||
y2: pointY2,
|
||||
type: 'curve',
|
||||
}
|
||||
}
|
||||
|
||||
@ -3280,26 +3204,13 @@ export function useModuleBasicSetting(tabNum) {
|
||||
type: 'flat',
|
||||
}
|
||||
} else {
|
||||
// NaN 체크: offset이 너무 커서 꼭짓점을 넘어가면 NaN 발생
|
||||
if (isNaN(pointX1) || isNaN(pointX2) || isNaN(pointY1) || isNaN(pointY2)) {
|
||||
// NaN이면 꼭짓점 좌표 사용 (모듈 설치 영역 없음)
|
||||
rtnObj = {
|
||||
target: index === 0 ? 'left' : 'right',
|
||||
x1: center.x1,
|
||||
y1: center.y1,
|
||||
x2: center.x1,
|
||||
y2: center.y1,
|
||||
type: 'curve',
|
||||
}
|
||||
} else {
|
||||
rtnObj = {
|
||||
target: index === 0 ? 'left' : 'right',
|
||||
x1: pointX1,
|
||||
y1: pointY1,
|
||||
x2: pointX2,
|
||||
y2: pointY2,
|
||||
type: 'curve',
|
||||
}
|
||||
rtnObj = {
|
||||
target: index === 0 ? 'left' : 'right',
|
||||
x1: pointX1,
|
||||
y1: pointY1,
|
||||
x2: pointX2,
|
||||
y2: pointY2,
|
||||
type: 'curve',
|
||||
}
|
||||
}
|
||||
rtnObjArray.push(rtnObj)
|
||||
@ -4190,7 +4101,6 @@ export function useModuleBasicSetting(tabNum) {
|
||||
left: leftRightFlowLine(moduleSetupSurface, length).find((obj) => obj.target === 'left'),
|
||||
right: leftRightFlowLine(moduleSetupSurface, length).find((obj) => obj.target === 'right'),
|
||||
}
|
||||
|
||||
return flowLines
|
||||
}
|
||||
|
||||
|
||||
@ -65,10 +65,6 @@ export const useTrestle = () => {
|
||||
if (+roofSizeSet === 3) {
|
||||
return
|
||||
}
|
||||
const trestleDetail = surface.trestleDetail
|
||||
if (!trestleDetail) {
|
||||
return
|
||||
}
|
||||
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
||||
if (!construction) {
|
||||
return
|
||||
@ -80,8 +76,8 @@ export const useTrestle = () => {
|
||||
let isSnowGuard = construction.setupSnowCover
|
||||
let cvrLmtRow = construction.cvrLmtRow
|
||||
const direction = parent.direction
|
||||
const rack = trestleDetail.rack
|
||||
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn, lessSupFitIntvlPct, lessSupFitQty } = trestleDetail
|
||||
const rack = surface.trestleDetail.rack
|
||||
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn, lessSupFitIntvlPct, lessSupFitQty } = surface.trestleDetail
|
||||
|
||||
if (!rack && lessSupFitIntvlPct === 0 && lessSupFitQty === 0) {
|
||||
//25/02/06 가대없음의 경우 랙정보가 없음
|
||||
|
||||
@ -152,17 +152,11 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
|
||||
rect.set({ width: Math.abs(width), height: Math.abs(height) })
|
||||
|
||||
// 마우스를 왼쪽으로 드래그한 경우 left를 현재 포인터 위치로 설정
|
||||
if (width < 0) {
|
||||
rect.set({ left: pointer.x })
|
||||
} else {
|
||||
rect.set({ left: origX })
|
||||
rect.set({ left: Math.abs(pointer.x) })
|
||||
}
|
||||
// 마우스를 위쪽으로 드래그한 경우 top을 현재 포인터 위치로 설정
|
||||
if (height < 0) {
|
||||
rect.set({ top: pointer.y })
|
||||
} else {
|
||||
rect.set({ top: origY })
|
||||
rect.set({ top: Math.abs(pointer.y) })
|
||||
}
|
||||
|
||||
canvas?.renderAll()
|
||||
@ -185,8 +179,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
}
|
||||
|
||||
// 그림자(SHADOW)는 중복 설치 허용, 개구(OPENING)만 중복 체크
|
||||
if (!isCrossChecked && buttonAct === 1) {
|
||||
if (!isCrossChecked) {
|
||||
const preObjects = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.SHADOW)
|
||||
const preObjectsArray = preObjects.map((obj) => rectToPolygon(obj))
|
||||
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
|
||||
@ -273,8 +266,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
}
|
||||
|
||||
// 그림자(SHADOW)는 중복 설치 허용, 개구(OPENING)만 중복 체크
|
||||
if (!isCrossChecked && buttonAct === 1) {
|
||||
if (!isCrossChecked) {
|
||||
const preObjects = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.SHADOW)
|
||||
const preObjectsArray = preObjects.map((obj) => rectToPolygon(obj))
|
||||
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
|
||||
|
||||
@ -159,6 +159,10 @@ export function useContextMenu() {
|
||||
}
|
||||
break
|
||||
case 'roof':
|
||||
case 'auxiliaryLine':
|
||||
case 'hip':
|
||||
case 'ridge':
|
||||
case 'eaveHelpLine':
|
||||
if (selectedMenu === 'surface') {
|
||||
setContextMenu([
|
||||
[
|
||||
@ -245,73 +249,6 @@ export function useContextMenu() {
|
||||
},
|
||||
},
|
||||
],
|
||||
])
|
||||
}
|
||||
|
||||
break
|
||||
case 'auxiliaryLine':
|
||||
case 'hip':
|
||||
case 'ridge':
|
||||
case 'eaveHelpLine':
|
||||
if (selectedMenu === 'surface') {
|
||||
setContextMenu([
|
||||
[
|
||||
{
|
||||
id: 'sizeEdit',
|
||||
name: getMessage('contextmenu.size.edit'),
|
||||
component: <SizeSetting id={popupId} target={currentObject} />,
|
||||
},
|
||||
{
|
||||
id: 'rotate',
|
||||
name: `${getMessage('contextmenu.rotate')}`,
|
||||
fn: () => rotateSurfaceShapeBatch(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialRemove',
|
||||
shortcut: ['d', 'D'],
|
||||
name: `${getMessage('contextmenu.remove')}(D)`,
|
||||
fn: () => deleteObject(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialMove',
|
||||
shortcut: ['m', 'M'],
|
||||
name: `${getMessage('contextmenu.move')}(M)`,
|
||||
fn: () => moveSurfaceShapeBatch(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialCopy',
|
||||
shortcut: ['c', 'C'],
|
||||
name: `${getMessage('contextmenu.copy')}(C)`,
|
||||
fn: () => copyObject(),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
id: 'roofMaterialEdit',
|
||||
name: getMessage('contextmenu.roof.material.edit'),
|
||||
component: <ContextRoofAllocationSetting id={popupId} />,
|
||||
},
|
||||
{
|
||||
id: 'linePropertyEdit',
|
||||
name: getMessage('contextmenu.line.property.edit'),
|
||||
fn: () => {
|
||||
if (+canvasSetting.roofSizeSet === 3) {
|
||||
swalFire({ text: getMessage('contextmenu.line.property.edit.roof.size.3') })
|
||||
} else {
|
||||
addPopup(popupId, 1, <PlacementSurfaceLineProperty id={popupId} roof={currentObject} />)
|
||||
}
|
||||
},
|
||||
// component: <LinePropertySetting id={popupId} target={currentObject} />,
|
||||
},
|
||||
{
|
||||
id: 'flowDirectionEdit',
|
||||
name: getMessage('contextmenu.flow.direction.edit'),
|
||||
component: <FlowDirectionSetting id={popupId} target={currentObject} />,
|
||||
},
|
||||
],
|
||||
])
|
||||
} else if (selectedMenu === 'outline') {
|
||||
setContextMenu([
|
||||
[
|
||||
{
|
||||
id: 'sizeEdit',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user