외벽선 없는 경우 처리 추가

This commit is contained in:
hyojun.choi 2025-12-31 13:52:50 +09:00
parent 5131e20a5c
commit 1524766b7e
6 changed files with 130 additions and 90 deletions

View File

@ -222,6 +222,7 @@ export const SAVE_KEY = [
'skeletonLines', 'skeletonLines',
'skeleton', 'skeleton',
'viewportTransform', 'viewportTransform',
'outerLineFix',
] ]
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]

View File

@ -142,6 +142,15 @@ export function useMovementSetting(id) {
} }
}, []) }, [])
useEffect(() => {
const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
if (roofs.length === 0) {
swalFire({ text: getMessage('roof.line.not.found') })
closePopup(id)
return
}
}, [])
/** object 선택이 변경될 때 처리*/ /** object 선택이 변경될 때 처리*/
useEffect(() => { useEffect(() => {
if (FOLLOW_LINE_REF.current != null) { if (FOLLOW_LINE_REF.current != null) {
@ -186,7 +195,6 @@ export function useMovementSetting(id) {
canvas.renderAll() canvas.renderAll()
}, [currentObject]) }, [currentObject])
const clearRef = () => { const clearRef = () => {
if (type === TYPE.FLOW_LINE) { if (type === TYPE.FLOW_LINE) {
// 안전한 ref 접근 // 안전한 ref 접근
@ -258,23 +266,25 @@ export function useMovementSetting(id) {
let value = '' let value = ''
let direction = '' let direction = ''
if (Math.abs(target.y1 - target.y2) < 0.5) { // 수평 라인 if (Math.abs(target.y1 - target.y2) < 0.5) {
// 수평 라인
value = Big(targetTop).minus(currentY).times(10).round(0) value = Big(targetTop).minus(currentY).times(10).round(0)
// 방향 감지 // 방향 감지
if (value.toNumber() > 0) { if (value.toNumber() > 0) {
direction = 'up' // 마우스가 라인 위쪽에 있음 (위로 움직임) direction = 'up' // 마우스가 라인 위쪽에 있음 (위로 움직임)
} else if (value.toNumber() < 0) { } else if (value.toNumber() < 0) {
direction = 'down' // 마우스가 라인 아래쪽에 있음 (아래로 움직임) direction = 'down' // 마우스가 라인 아래쪽에 있음 (아래로 움직임)
} }
} else { // 수직 라인 } else {
// 수직 라인
value = Big(targetLeft).minus(currentX).times(10).round(0).neg() value = Big(targetLeft).minus(currentX).times(10).round(0).neg()
// 방향 감지 // 방향 감지
if (value.toNumber() > 0) { if (value.toNumber() > 0) {
direction = 'right' // 마우스가 라인 오른쪽에 있음 (오른쪽으로 움직임) direction = 'right' // 마우스가 라인 오른쪽에 있음 (오른쪽으로 움직임)
} else if (value.toNumber() < 0) { } else if (value.toNumber() < 0) {
direction = 'left' // 마우스가 라인 왼쪽에 있음 (왼쪽으로 움직임) direction = 'left' // 마우스가 라인 왼쪽에 있음 (왼쪽으로 움직임)
} }
} }
@ -312,37 +322,35 @@ export function useMovementSetting(id) {
const midY = Big(target.y1).plus(target.y2).div(2) const midY = Big(target.y1).plus(target.y2).div(2)
const wall = canvas.getObjects().find((obj) => obj.id === target.attributes.wallId) const wall = canvas.getObjects().find((obj) => obj.id === target.attributes.wallId)
const result = getSelectLinePosition(wall, target, { const result = getSelectLinePosition(wall, target, {
testDistance: 5, // 테스트 거리 testDistance: 5, // 테스트 거리
debug: true // 디버깅 로그 출력 debug: true, // 디버깅 로그 출력
}); })
//console.log("1111litarget:::::", target); //console.log("1111litarget:::::", target);
//console.log("1111linePosition:::::", result.position); // 'top', 'bottom', 'left', 'right' //console.log("1111linePosition:::::", result.position); // 'top', 'bottom', 'left', 'right'
let linePosition = result.position; let linePosition = result.position
//console.log("1111linePosition:::::", direction, linePosition); //console.log("1111linePosition:::::", direction, linePosition);
if (target.y1 === target.y2) { //수평벽 if (target.y1 === target.y2) {
//수평벽
const setRadioStates = (isUp) => { const setRadioStates = (isUp) => {
if (UP_DOWN_REF.UP_RADIO_REF.current) { if (UP_DOWN_REF.UP_RADIO_REF.current) {
UP_DOWN_REF.UP_RADIO_REF.current.checked = isUp; UP_DOWN_REF.UP_RADIO_REF.current.checked = isUp
} }
if (UP_DOWN_REF.DOWN_RADIO_REF.current) { if (UP_DOWN_REF.DOWN_RADIO_REF.current) {
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = !isUp; UP_DOWN_REF.DOWN_RADIO_REF.current.checked = !isUp
} }
};
if (linePosition === 'top') {
setRadioStates(value.s !== -1);
} else if (linePosition === 'bottom') {
setRadioStates(value.s !== 1);
} }
if(direction === 'up') { if (linePosition === 'top') {
setRadioStates(value.s !== -1)
} else if (linePosition === 'bottom') {
setRadioStates(value.s !== 1)
}
if (direction === 'up') {
} }
/* /*
checkPoint = { x: midX.toNumber(), y: midY.plus(10).toNumber() } checkPoint = { x: midX.toNumber(), y: midY.plus(10).toNumber() }
@ -367,20 +375,19 @@ export function useMovementSetting(id) {
} }
*/ */
} else { } else {
const setRadioStates = (isUp) => { const setRadioStates = (isUp) => {
if (UP_DOWN_REF.UP_RADIO_REF.current) { if (UP_DOWN_REF.UP_RADIO_REF.current) {
UP_DOWN_REF.UP_RADIO_REF.current.checked = isUp; UP_DOWN_REF.UP_RADIO_REF.current.checked = isUp
} }
if (UP_DOWN_REF.DOWN_RADIO_REF.current) { if (UP_DOWN_REF.DOWN_RADIO_REF.current) {
UP_DOWN_REF.DOWN_RADIO_REF.current.checked = !isUp; UP_DOWN_REF.DOWN_RADIO_REF.current.checked = !isUp
} }
}; }
if (linePosition === 'left') { if (linePosition === 'left') {
setRadioStates(value.s !== 1); setRadioStates(value.s !== 1)
} else if (linePosition === 'right') { } else if (linePosition === 'right') {
setRadioStates(value.s !== -1); setRadioStates(value.s !== -1)
} }
/* /*
checkPoint = { x: midX.plus(10).toNumber(), y: midY.toNumber() } checkPoint = { x: midX.plus(10).toNumber(), y: midY.toNumber() }
@ -407,11 +414,8 @@ export function useMovementSetting(id) {
*/ */
} }
} }
} }
const mouseDownEvent = (e) => { const mouseDownEvent = (e) => {
canvas canvas
.getObjects() .getObjects()
@ -460,7 +464,6 @@ export function useMovementSetting(id) {
canvas.renderAll() canvas.renderAll()
} }
const target = selectedObject.current !== null ? selectedObject.current : CONFIRM_LINE_REF.current?.target const target = selectedObject.current !== null ? selectedObject.current : CONFIRM_LINE_REF.current?.target
if (!target) return if (!target) return
@ -468,23 +471,23 @@ export function useMovementSetting(id) {
const roof = canvas.getObjects().find((obj) => obj.id === roofId) const roof = canvas.getObjects().find((obj) => obj.id === roofId)
// 현이동, 동이동 추가 // 현이동, 동이동 추가
let flPointValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value ?? 0; let flPointValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value ?? 0
let flFilledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value ?? 0; let flFilledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value ?? 0
flPointValue = (flFilledValue > 0 || flFilledValue < 0) ? flFilledValue : flPointValue; flPointValue = flFilledValue > 0 || flFilledValue < 0 ? flFilledValue : flPointValue
const moveFlowLine = typeRef.current === TYPE.FLOW_LINE ? flPointValue : 0 const moveFlowLine = typeRef.current === TYPE.FLOW_LINE ? flPointValue : 0
let udPointValue = UP_DOWN_REF.POINTER_INPUT_REF.current?.value ?? 0; let udPointValue = UP_DOWN_REF.POINTER_INPUT_REF.current?.value ?? 0
let udFilledValue = UP_DOWN_REF.FILLED_INPUT_REF.current?.value ?? 0; let udFilledValue = UP_DOWN_REF.FILLED_INPUT_REF.current?.value ?? 0
udPointValue = udFilledValue > 0 ? udFilledValue : udPointValue; udPointValue = udFilledValue > 0 ? udFilledValue : udPointValue
const moveUpDown = typeRef.current === TYPE.UP_DOWN ? udPointValue : 0 const moveUpDown = typeRef.current === TYPE.UP_DOWN ? udPointValue : 0
roof.moveFlowLine = parseInt(moveFlowLine, 10) || 0; roof.moveFlowLine = parseInt(moveFlowLine, 10) || 0
roof.moveUpDown = parseInt(moveUpDown, 10) || 0; roof.moveUpDown = parseInt(moveUpDown, 10) || 0
roof.moveDirect = ""; roof.moveDirect = ''
roof.moveSelectLine = target roof.moveSelectLine = target
//console.log("target::::", target, roof.moveSelectLine) //console.log("target::::", target, roof.moveSelectLine)
const wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId) const wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId)
const baseLines = wall.baseLines const baseLines = wall.baseLines
let centerPoint = wall.getCenterPoint(); let centerPoint = wall.getCenterPoint()
let targetBaseLines = [] let targetBaseLines = []
let isGableRoof let isGableRoof
if (typeRef.current === TYPE.FLOW_LINE) { if (typeRef.current === TYPE.FLOW_LINE) {
@ -522,9 +525,19 @@ export function useMovementSetting(id) {
return minX <= line.x1 && line.x1 <= maxX && minX <= line.x2 && line.x2 <= maxX return minX <= line.x1 && line.x1 <= maxX && minX <= line.x2 && line.x2 <= maxX
}) })
if (isGableRoof && currentBaseLines.length > 0) { if (isGableRoof && currentBaseLines.length > 0) {
currentBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(line.y1).minus(target.y1).abs().toNumber() })) currentBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(line.y1).minus(target.y1).abs().toNumber(),
}),
)
} else { } else {
checkBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(target.y1).minus(line.y1).abs().toNumber() })) checkBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(target.y1).minus(line.y1).abs().toNumber(),
}),
)
} }
baseLines baseLines
.filter((line) => line.y1 === line.y2 && line.y1 < target.y1) .filter((line) => line.y1 === line.y2 && line.y1 < target.y1)
@ -538,9 +551,19 @@ export function useMovementSetting(id) {
return minX <= line.x1 && line.x1 <= maxX && minX <= line.x2 && line.x2 <= maxX return minX <= line.x1 && line.x1 <= maxX && minX <= line.x2 && line.x2 <= maxX
}) })
if (isGableRoof && currentBaseLines.length > 0) { if (isGableRoof && currentBaseLines.length > 0) {
currentBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(line.y1).minus(target.y1).abs().toNumber() })) currentBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(line.y1).minus(target.y1).abs().toNumber(),
}),
)
} else { } else {
checkBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(line.y1).minus(target.y1).abs().toNumber() })) checkBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(line.y1).minus(target.y1).abs().toNumber(),
}),
)
} }
break break
case 'right': case 'right':
@ -551,9 +574,19 @@ export function useMovementSetting(id) {
return minY <= line.y1 && line.y1 <= maxY && minY <= line.y2 && line.y2 <= maxY return minY <= line.y1 && line.y1 <= maxY && minY <= line.y2 && line.y2 <= maxY
}) })
if (isGableRoof && currentBaseLines.length > 0) { if (isGableRoof && currentBaseLines.length > 0) {
currentBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(line.x1).minus(target.x1).abs().toNumber() })) currentBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(line.x1).minus(target.x1).abs().toNumber(),
}),
)
} else { } else {
checkBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(target.x1).minus(line.x1).abs().toNumber() })) checkBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(target.x1).minus(line.x1).abs().toNumber(),
}),
)
} }
break break
case 'left': case 'left':
@ -564,9 +597,19 @@ export function useMovementSetting(id) {
return minY <= line.y1 && line.y1 <= maxY && minY <= line.y2 && line.y2 <= maxY return minY <= line.y1 && line.y1 <= maxY && minY <= line.y2 && line.y2 <= maxY
}) })
if (isGableRoof && currentBaseLines.length > 0) { if (isGableRoof && currentBaseLines.length > 0) {
currentBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(line.x1).minus(target.x1).abs().toNumber() })) currentBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(line.x1).minus(target.x1).abs().toNumber(),
}),
)
} else { } else {
checkBaseLines.forEach((line) => targetBaseLines.push({ line, distance: Big(target.x1).minus(line.x1).abs().toNumber() })) checkBaseLines.forEach((line) =>
targetBaseLines.push({
line,
distance: Big(target.x1).minus(line.x1).abs().toNumber(),
}),
)
} }
break break
} }
@ -576,18 +619,18 @@ export function useMovementSetting(id) {
} }
// Remove duplicate lines // Remove duplicate lines
const uniqueLines = new Map(); const uniqueLines = new Map()
targetBaseLines = targetBaseLines.filter(item => { targetBaseLines = targetBaseLines.filter((item) => {
const key = `${item.line.x1},${item.line.y1},${item.line.x2},${item.line.y2}`; const key = `${item.line.x1},${item.line.y1},${item.line.x2},${item.line.y2}`
if (!uniqueLines.has(key)) { if (!uniqueLines.has(key)) {
uniqueLines.set(key, true); uniqueLines.set(key, true)
return true; return true
} }
return false; return false
}); })
// Sort by distance // Sort by distance
targetBaseLines.sort((a, b) => a.distance - b.distance); targetBaseLines.sort((a, b) => a.distance - b.distance)
targetBaseLines = targetBaseLines.filter((line) => line.distance === targetBaseLines[0].distance) targetBaseLines = targetBaseLines.filter((line) => line.distance === targetBaseLines[0].distance)
if (isGableRoof) { if (isGableRoof) {
@ -621,27 +664,22 @@ export function useMovementSetting(id) {
let value let value
if (typeRef.current === TYPE.FLOW_LINE) { if (typeRef.current === TYPE.FLOW_LINE) {
value = (() => { value = (() => {
const filledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value; const filledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value
const pointerValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value; const pointerValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value
if (filledValue && !isNaN(filledValue) && filledValue.trim() !== '') { if (filledValue && !isNaN(filledValue) && filledValue.trim() !== '') {
return Big(filledValue).times(2); return Big(filledValue).times(2)
} else if (pointerValue && !isNaN(pointerValue) && pointerValue.trim() !== '') { } else if (pointerValue && !isNaN(pointerValue) && pointerValue.trim() !== '') {
return Big(pointerValue).times(2); return Big(pointerValue).times(2)
} }
return Big(0); // 기본값으로 0 반환 또는 다른 적절한 기본값 return Big(0) // 기본값으로 0 반환 또는 다른 적절한 기본값
})(); })()
if (Math.abs(target.y1 - target.y2) < 0.5) { if (Math.abs(target.y1 - target.y2) < 0.5) {
value = value.neg() value = value.neg()
} }
} else { } else {
console.log("error::", UP_DOWN_REF.POINTER_INPUT_REF.current.value) console.log('error::', UP_DOWN_REF.POINTER_INPUT_REF.current.value)
value = Big( value = Big(UP_DOWN_REF?.FILLED_INPUT_REF?.current?.value?.trim() || UP_DOWN_REF?.POINTER_INPUT_REF?.current?.value?.trim() || '0')
(UP_DOWN_REF?.FILLED_INPUT_REF?.current?.value?.trim() ||
UP_DOWN_REF?.POINTER_INPUT_REF?.current?.value?.trim() ||
'0'
)
);
const midX = Big(target.x1).plus(target.x2).div(2) const midX = Big(target.x1).plus(target.x2).div(2)
const midY = Big(target.y1).plus(target.y2).div(2) const midY = Big(target.y1).plus(target.y2).div(2)
@ -665,17 +703,16 @@ export function useMovementSetting(id) {
// console.log("2222저장된 moveSelectLine:", roof.moveSelectLine); // console.log("2222저장된 moveSelectLine:", roof.moveSelectLine);
// console.log("222wall::::", wall.points) // console.log("222wall::::", wall.points)
const result = getSelectLinePosition(wall, target, { const result = getSelectLinePosition(wall, target, {
testDistance: 5, // 테스트 거리 testDistance: 5, // 테스트 거리
debug: true // 디버깅 로그 출력 debug: true, // 디버깅 로그 출력
}); })
//console.log("2222linePosition:::::", result.position); //console.log("2222linePosition:::::", result.position);
//console.log("222moveDirect:::::", roof.moveDirect); //console.log("222moveDirect:::::", roof.moveDirect);
// 디버깅용 분류 결과 확인
// 디버깅용 분류 결과 확인 let linePosition = result.position
let linePosition = result.position;
roof.movePosition = linePosition roof.movePosition = linePosition
value = value.div(10) value = value.div(10)
targetBaseLines targetBaseLines
@ -684,15 +721,14 @@ export function useMovementSetting(id) {
const currentLine = target.line const currentLine = target.line
//console.log("linePosition::::::::::::::", linePosition) //console.log("linePosition::::::::::::::", linePosition)
if (UP_DOWN_REF?.DOWN_RADIO_REF?.current?.checked ){ if (UP_DOWN_REF?.DOWN_RADIO_REF?.current?.checked) {
//position확인 //position확인
if(linePosition === 'bottom' || linePosition === 'right') { if (linePosition === 'bottom' || linePosition === 'right') {
//console.log("1value::::::::::::::", value.toString()) //console.log("1value::::::::::::::", value.toString())
value = value.neg() value = value.neg()
} }
}else { } else {
if(linePosition === 'top' || linePosition === 'left') { if (linePosition === 'top' || linePosition === 'left') {
//console.log("1value::::::::::::::", value.toString()) //console.log("1value::::::::::::::", value.toString())
value = value.neg() value = value.neg()
} }
@ -753,7 +789,6 @@ export function useMovementSetting(id) {
// javascript // javascript
return { return {
TYPE, TYPE,
closePopup, closePopup,
@ -765,4 +800,3 @@ export function useMovementSetting(id) {
handleSave, handleSave,
} }
} }

View File

@ -251,6 +251,7 @@ export function useOuterLineWall(id, propertiesId) {
removeAllDocumentEventListeners() removeAllDocumentEventListeners()
canvas?.renderAll() canvas?.renderAll()
setOuterLineFix(true) setOuterLineFix(true)
canvas.outerLineFix = true
closePopup(id) closePopup(id)
ccwCheck() ccwCheck()
addPopup(propertiesId, 1, <RoofShapeSetting id={propertiesId} pos={{ x: 50, y: 230 }} />) addPopup(propertiesId, 1, <RoofShapeSetting id={propertiesId} pos={{ x: 50, y: 230 }} />)

View File

@ -7,7 +7,6 @@ import { useEvent } from '@/hooks/useEvent'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import { useMode } from '@/hooks/useMode' import { useMode } from '@/hooks/useMode'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { outerLineFixState } from '@/store/outerLineAtom'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { getChonByDegree } from '@/util/canvas-util' import { getChonByDegree } from '@/util/canvas-util'
@ -46,11 +45,9 @@ export function useRoofShapePassivitySetting(id) {
{ id: 3, name: getMessage('windage'), type: TYPES.SHED }, { id: 3, name: getMessage('windage'), type: TYPES.SHED },
] ]
const outerLineFix = useRecoilValue(outerLineFixState)
useEffect(() => { useEffect(() => {
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
if (!outerLineFix || outerLines.length === 0) { if (!canvas.outerLineFix || outerLines.length === 0) {
swalFire({ text: getMessage('wall.line.not.found') }) swalFire({ text: getMessage('wall.line.not.found') })
closePopup(id) closePopup(id)
return return

View File

@ -81,6 +81,12 @@ export function useRoofShapeSetting(id) {
}, [jerkinHeadPitch]) }, [jerkinHeadPitch])
useEffect(() => { useEffect(() => {
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
if (!canvas.outerLineFix || outerLines.length === 0) {
swalFire({ text: getMessage('wall.line.not.found') })
closePopup(id)
return
}
return () => { return () => {
if (!isFixRef.current) { if (!isFixRef.current) {
return return

View File

@ -755,6 +755,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
type: 'confirm', type: 'confirm',
confirmFn: () => { confirmFn: () => {
canvas.clear() canvas.clear()
delete canvas.outerLineFix
if (backgroundImage) { if (backgroundImage) {
fabric.Image.fromURL(`${backgroundImage.path}`, function (img) { fabric.Image.fromURL(`${backgroundImage.path}`, function (img) {