diff --git a/src/common/common.js b/src/common/common.js index 76632014..c0fe3701 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -222,6 +222,7 @@ export const SAVE_KEY = [ 'skeletonLines', 'skeleton', 'viewportTransform', + 'outerLineFix', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype] diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 1ee73892..720845f5 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -122,6 +122,21 @@ export default function PassivityCircuitAllocation(props) { return } + // targetModule중 북면 설치 여부가 Y인 것과 N인 것이 혼합이면 안됨. + const targetModuleGroup = [...new Set(canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE && targetModules.includes(obj.id)) + .map((obj) => obj.moduleInfo.northModuleYn))] + + if (targetModuleGroup.length > 1) { + swalFire({ + text: getMessage('module.circuit.fix.not.same.roof.error'), + type: 'alert', + icon: 'warning', + }) + return + } + switch (pcsTpCd) { case 'INDFCS': { const originHaveThisPcsModules = canvas diff --git a/src/components/floor-plan/modal/module/PanelEdit.jsx b/src/components/floor-plan/modal/module/PanelEdit.jsx index 97b02112..baf4b101 100644 --- a/src/components/floor-plan/modal/module/PanelEdit.jsx +++ b/src/components/floor-plan/modal/module/PanelEdit.jsx @@ -104,14 +104,16 @@ export default function PanelEdit(props) { closePopup(id)} />
{getMessage( - [PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.MOVE_ALL, PANEL_EDIT_TYPE.COLUMN_MOVE].includes(type) + [PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.MOVE_ALL, PANEL_EDIT_TYPE.COLUMN_MOVE, PANEL_EDIT_TYPE.ROW_MOVE].includes(type) ? 'modal.move.setting.info' : 'modal.copy.setting.info', )} diff --git a/src/hooks/roofcover/useMovementSetting.js b/src/hooks/roofcover/useMovementSetting.js index e74a59e3..92f2e2c0 100644 --- a/src/hooks/roofcover/useMovementSetting.js +++ b/src/hooks/roofcover/useMovementSetting.js @@ -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 선택이 변경될 때 처리*/ useEffect(() => { if (FOLLOW_LINE_REF.current != null) { @@ -186,7 +195,6 @@ export function useMovementSetting(id) { canvas.renderAll() }, [currentObject]) - const clearRef = () => { if (type === TYPE.FLOW_LINE) { // 안전한 ref 접근 @@ -258,23 +266,25 @@ export function useMovementSetting(id) { let value = '' 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) // 방향 감지 if (value.toNumber() > 0) { - direction = 'up' // 마우스가 라인 위쪽에 있음 (위로 움직임) + direction = 'up' // 마우스가 라인 위쪽에 있음 (위로 움직임) } else if (value.toNumber() < 0) { - direction = 'down' // 마우스가 라인 아래쪽에 있음 (아래로 움직임) + direction = 'down' // 마우스가 라인 아래쪽에 있음 (아래로 움직임) } - } else { // 수직 라인 + } else { + // 수직 라인 value = Big(targetLeft).minus(currentX).times(10).round(0).neg() // 방향 감지 if (value.toNumber() > 0) { - direction = 'right' // 마우스가 라인 오른쪽에 있음 (오른쪽으로 움직임) + direction = 'right' // 마우스가 라인 오른쪽에 있음 (오른쪽으로 움직임) } 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 wall = canvas.getObjects().find((obj) => obj.id === target.attributes.wallId) - - const result = getSelectLinePosition(wall, target, { - testDistance: 5, // 테스트 거리 - debug: true // 디버깅 로그 출력 - }); + testDistance: 5, // 테스트 거리 + debug: true, // 디버깅 로그 출력 + }) //console.log("1111litarget:::::", target); //console.log("1111linePosition:::::", result.position); // 'top', 'bottom', 'left', 'right' - let linePosition = result.position; -//console.log("1111linePosition:::::", direction, linePosition); + let linePosition = result.position + //console.log("1111linePosition:::::", direction, linePosition); - if (target.y1 === target.y2) { //수평벽 + if (target.y1 === target.y2) { + //수평벽 const setRadioStates = (isUp) => { 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) { - 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() } @@ -367,20 +375,19 @@ export function useMovementSetting(id) { } */ } else { - const setRadioStates = (isUp) => { 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) { - UP_DOWN_REF.DOWN_RADIO_REF.current.checked = !isUp; + UP_DOWN_REF.DOWN_RADIO_REF.current.checked = !isUp } - }; + } if (linePosition === 'left') { - setRadioStates(value.s !== 1); + setRadioStates(value.s !== 1) } else if (linePosition === 'right') { - setRadioStates(value.s !== -1); + setRadioStates(value.s !== -1) } /* checkPoint = { x: midX.plus(10).toNumber(), y: midY.toNumber() } @@ -407,11 +414,8 @@ export function useMovementSetting(id) { */ } } - } - - const mouseDownEvent = (e) => { canvas .getObjects() @@ -460,7 +464,6 @@ export function useMovementSetting(id) { canvas.renderAll() } - const target = selectedObject.current !== null ? selectedObject.current : CONFIRM_LINE_REF.current?.target if (!target) return @@ -468,23 +471,23 @@ export function useMovementSetting(id) { const roof = canvas.getObjects().find((obj) => obj.id === roofId) // 현이동, 동이동 추가 - let flPointValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value ?? 0; - let flFilledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value ?? 0; - flPointValue = (flFilledValue > 0 || flFilledValue < 0) ? flFilledValue : flPointValue; + let flPointValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value ?? 0 + let flFilledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value ?? 0 + flPointValue = flFilledValue > 0 || flFilledValue < 0 ? flFilledValue : flPointValue const moveFlowLine = typeRef.current === TYPE.FLOW_LINE ? flPointValue : 0 - let udPointValue = UP_DOWN_REF.POINTER_INPUT_REF.current?.value ?? 0; - let udFilledValue = UP_DOWN_REF.FILLED_INPUT_REF.current?.value ?? 0; - udPointValue = udFilledValue > 0 ? udFilledValue : udPointValue; + let udPointValue = UP_DOWN_REF.POINTER_INPUT_REF.current?.value ?? 0 + let udFilledValue = UP_DOWN_REF.FILLED_INPUT_REF.current?.value ?? 0 + udPointValue = udFilledValue > 0 ? udFilledValue : udPointValue const moveUpDown = typeRef.current === TYPE.UP_DOWN ? udPointValue : 0 - roof.moveFlowLine = parseInt(moveFlowLine, 10) || 0; - roof.moveUpDown = parseInt(moveUpDown, 10) || 0; - roof.moveDirect = ""; + roof.moveFlowLine = parseInt(moveFlowLine, 10) || 0 + roof.moveUpDown = parseInt(moveUpDown, 10) || 0 + roof.moveDirect = '' roof.moveSelectLine = target //console.log("target::::", target, roof.moveSelectLine) const wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId) const baseLines = wall.baseLines - let centerPoint = wall.getCenterPoint(); + let centerPoint = wall.getCenterPoint() let targetBaseLines = [] let isGableRoof 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 }) 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 { - 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 .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 }) 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 { - 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 case 'right': @@ -551,9 +574,19 @@ export function useMovementSetting(id) { return minY <= line.y1 && line.y1 <= maxY && minY <= line.y2 && line.y2 <= maxY }) 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 { - 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 case 'left': @@ -564,9 +597,19 @@ export function useMovementSetting(id) { return minY <= line.y1 && line.y1 <= maxY && minY <= line.y2 && line.y2 <= maxY }) 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 { - 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 } @@ -576,18 +619,18 @@ export function useMovementSetting(id) { } // Remove duplicate lines - const uniqueLines = new Map(); - targetBaseLines = targetBaseLines.filter(item => { - const key = `${item.line.x1},${item.line.y1},${item.line.x2},${item.line.y2}`; + const uniqueLines = new Map() + targetBaseLines = targetBaseLines.filter((item) => { + const key = `${item.line.x1},${item.line.y1},${item.line.x2},${item.line.y2}` if (!uniqueLines.has(key)) { - uniqueLines.set(key, true); - return true; + uniqueLines.set(key, true) + return true } - return false; - }); + return false + }) // 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) if (isGableRoof) { @@ -621,27 +664,22 @@ export function useMovementSetting(id) { let value if (typeRef.current === TYPE.FLOW_LINE) { value = (() => { - const filledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value; - const pointerValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value; + const filledValue = FLOW_LINE_REF.FILLED_INPUT_REF.current?.value + const pointerValue = FLOW_LINE_REF.POINTER_INPUT_REF.current?.value if (filledValue && !isNaN(filledValue) && filledValue.trim() !== '') { - return Big(filledValue).times(2); + return Big(filledValue).times(2) } 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) { value = value.neg() } } else { - console.log("error::", UP_DOWN_REF.POINTER_INPUT_REF.current.value) - value = Big( - (UP_DOWN_REF?.FILLED_INPUT_REF?.current?.value?.trim() || - UP_DOWN_REF?.POINTER_INPUT_REF?.current?.value?.trim() || - '0' - ) - ); + console.log('error::', UP_DOWN_REF.POINTER_INPUT_REF.current.value) + value = Big(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 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("222wall::::", wall.points) const result = getSelectLinePosition(wall, target, { - testDistance: 5, // 테스트 거리 - debug: true // 디버깅 로그 출력 - }); + testDistance: 5, // 테스트 거리 + debug: true, // 디버깅 로그 출력 + }) //console.log("2222linePosition:::::", result.position); //console.log("222moveDirect:::::", roof.moveDirect); + // 디버깅용 분류 결과 확인 -// 디버깅용 분류 결과 확인 - - let linePosition = result.position; + let linePosition = result.position roof.movePosition = linePosition value = value.div(10) targetBaseLines @@ -684,15 +721,14 @@ export function useMovementSetting(id) { const currentLine = target.line //console.log("linePosition::::::::::::::", linePosition) - if (UP_DOWN_REF?.DOWN_RADIO_REF?.current?.checked ){ + if (UP_DOWN_REF?.DOWN_RADIO_REF?.current?.checked) { //position확인 - if(linePosition === 'bottom' || linePosition === 'right') { + if (linePosition === 'bottom' || linePosition === 'right') { //console.log("1value::::::::::::::", value.toString()) value = value.neg() - } - }else { - if(linePosition === 'top' || linePosition === 'left') { + } else { + if (linePosition === 'top' || linePosition === 'left') { //console.log("1value::::::::::::::", value.toString()) value = value.neg() } @@ -753,7 +789,6 @@ export function useMovementSetting(id) { // javascript - return { TYPE, closePopup, @@ -765,4 +800,3 @@ export function useMovementSetting(id) { handleSave, } } - diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index ebe1d8ad..dd304865 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -251,6 +251,7 @@ export function useOuterLineWall(id, propertiesId) { removeAllDocumentEventListeners() canvas?.renderAll() setOuterLineFix(true) + canvas.outerLineFix = true closePopup(id) ccwCheck() addPopup(propertiesId, 1, ) diff --git a/src/hooks/roofcover/useRoofShapePassivitySetting.js b/src/hooks/roofcover/useRoofShapePassivitySetting.js index 241d2fac..ac36779c 100644 --- a/src/hooks/roofcover/useRoofShapePassivitySetting.js +++ b/src/hooks/roofcover/useRoofShapePassivitySetting.js @@ -7,7 +7,6 @@ import { useEvent } from '@/hooks/useEvent' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { useMode } from '@/hooks/useMode' import { usePolygon } from '@/hooks/usePolygon' -import { outerLineFixState } from '@/store/outerLineAtom' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { getChonByDegree } from '@/util/canvas-util' @@ -46,11 +45,9 @@ export function useRoofShapePassivitySetting(id) { { id: 3, name: getMessage('windage'), type: TYPES.SHED }, ] - const outerLineFix = useRecoilValue(outerLineFixState) - useEffect(() => { 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') }) closePopup(id) return diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 9e1d00ff..f5c84f5b 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -81,6 +81,12 @@ export function useRoofShapeSetting(id) { }, [jerkinHeadPitch]) 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 () => { if (!isFixRef.current) { return diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index b26ee195..06474da0 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -755,6 +755,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { type: 'confirm', confirmFn: () => { canvas.clear() + delete canvas.outerLineFix if (backgroundImage) { fabric.Image.fromURL(`${backgroundImage.path}`, function (img) { diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 58857ee2..82ad62df 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -2690,13 +2690,8 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { let proceedRidges = [] // left: 이전, right:다음, point:그려지는 포인트, length:길이 let hipLines = [] ridgeEaves.forEach((currentLine) => { - const checkLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkLine).renderAll() + /*const checkLine = createArrow(currentLine, 'blue', roofId) + canvas.add(checkLine).renderAll()*/ let prevLine, nextLine, currentI, prevI, nextI baseLines.forEach((baseLine, index) => { if (baseLine === currentLine) { @@ -2741,7 +2736,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const prevCheckPoint = [currentLine.x1, currentLine.y1, currentLine.x1 + pHipVector.x * 1000, currentLine.y1 + pHipVector.y * 1000] const nextCheckPoint = [currentLine.x2, currentLine.y2, currentLine.x2 + nHipVector.x * 1000, currentLine.y2 + nHipVector.y * 1000] - /* const checkLine1 = new fabric.Line(prevCheckPoint, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' }) + /*const checkLine1 = new fabric.Line(prevCheckPoint, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' }) const checkLine2 = new fabric.Line(nextCheckPoint, { stroke: 'green', strokeWidth: 4, parentID: roofId, name: 'check' }) canvas.add(checkLine1, checkLine2).renderAll()*/ @@ -2807,7 +2802,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { let minPrevDist = Infinity let minNextDist = Infinity proceedRidges.forEach((ridge) => { - console.log('ridge : ', ridge) const ridgeEdge = { vertex1: { x: ridge.point.x1, y: ridge.point.y1 }, vertex2: { x: ridge.point.x2, y: ridge.point.y2 } } const isPrev = edgesIntersection(ridgeEdge, prevEdge) const isNext = edgesIntersection(ridgeEdge, nextEdge) @@ -3001,31 +2995,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { if (!alreadyRidge) { proceedRidges.push({ prev: prevI, next: nextI, point: ridgePoint }) } - - /*const checkRidgeStart = new fabric.Circle({ left: ridgePoint.x1, top: ridgePoint.y1, radius: 4, parentId: roofId, name: 'check' }) - const checkRidgeLine = new fabric.Line([ridgePoint.x1, ridgePoint.y1, ridgePoint.x2, ridgePoint.y2], { - stroke: 'yellow', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkRidgeLine, checkRidgeStart).renderAll()*/ } - - /*const checkLine1 = new fabric.Line([prevHipPoint.x1, prevHipPoint.y1, prevHipPoint.x2, prevHipPoint.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - const checkLine2 = new fabric.Line([nextHipPoint.x1, nextHipPoint.y1, nextHipPoint.x2, nextHipPoint.y2], { - stroke: 'blue', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkLine1, checkLine2).renderAll() -*/ canvas .getObjects() .filter((o) => o.name === 'check') @@ -3033,7 +3003,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { canvas.renderAll() }) - console.log('hipedEaves', hipedEaves) hipedEaves.forEach((currentLine) => { let prevLine baseLines.forEach((baseLine, index) => { @@ -3155,7 +3124,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { innerLines.push(drawHipLine([point.x1, point.y1, point.x2, point.y2], canvas, roof, textMode, currentDegree, currentDegree)) pIndexEaves.push(index) } else if (jointEaves.length === 2) { - console.log('jointEaves : ', jointEaves) const jointIndex = [index] let jointLines = [] jointEaves.forEach((e) => jointIndex.push(proceedEaves.findIndex((p) => p === e))) @@ -3172,11 +3140,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { //연결된 지점에서 파생된 마루선 제거 const removeRidge = proceedRidges.filter((ridge) => almostEqual(ridge.point.x1, eaves.point.x2) && almostEqual(ridge.point.y1, eaves.point.y2)) proceedRidges = proceedRidges.filter((ridge) => !removeRidge.includes(ridge)) - console.log('pIndexEaves : ', pIndexEaves) - console.log('jointLines : ', jointLines) - console.log('jointVectors : ', jointVectors) let dneVector = jointVectors.find((v) => !jointVectors.find((v2) => v2.x === -v.x && v2.y === -v.y)) - console.log('dneVector : ', dneVector) const findRoofEdge = { vertex1: { x: eaves.point.x2, y: eaves.point.y2 }, vertex2: { x: eaves.point.x2 + dneVector.x, y: eaves.point.y2 + dneVector.y }, @@ -3201,7 +3165,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { }) const uniqueLine = jointLines.filter((value) => countMap.get(value) === 1) - console.log('uniqueLine : ', uniqueLine) linesAnalysis.push({ start: { x: eaves.point.x2, y: eaves.point.y2 }, end: { x: isPoint.x, y: isPoint.y }, @@ -3211,7 +3174,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { degree: currentDegree, }) } - console.log('=============') } else { linesAnalysis.push({ start: { x: point.x1, y: point.y1 }, @@ -3235,9 +3197,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { }), ) - console.log('proceedEaves :', proceedEaves) - console.log('proceedRidges :', proceedRidges) - //4. 반절처(반절마루) 판단, 반절마루는 양옆이 처마여야 한다. jerkinHeads.forEach((currentLine) => { let prevLine, nextLine @@ -3748,8 +3707,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { parentId: roofId, name: 'check', }) - canvas.add(checkLine, checkLine2).renderAll() -*/ + canvas.add(checkLine, checkLine2).renderAll()*/ //기준지붕선의 반대쪽선 const oppositeLine = [] @@ -3807,7 +3765,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } }) - console.log('oppositeLine', oppositeLine) + if (oppositeLine.length > 0) { const ridgePoints = [] //지붕선 출발 지점 확인을 위한 기준 포인트 @@ -4190,9 +4148,27 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const ridgeLength = Math.sqrt(Math.pow(point[2] - point[0], 2) + Math.pow(point[3] - point[1], 2)) if (ridgeLength > EPSILON) { + //마루 포인트 중 1개만 지붕선에 붙어있을경우 해당 포인트를 시작점으로 한다. + const isPointOnRoof1 = roof.lines.find((line) => isPointOnLineNew(line, { x: point[0], y: point[1] })) !== undefined + const isPointOnRoof2 = roof.lines.find((line) => isPointOnLineNew(line, { x: point[2], y: point[3] })) !== undefined + + let startPoint, endPoint + if ((isPointOnRoof1 && isPointOnRoof2) || (!isPointOnRoof1 && !isPointOnRoof2)) { + startPoint = { x: point[0], y: point[1] } + endPoint = { x: point[2], y: point[3] } + } else { + if (isPointOnRoof1) { + startPoint = { x: point[0], y: point[1] } + endPoint = { x: point[2], y: point[3] } + } + if (isPointOnRoof2) { + startPoint = { x: point[2], y: point[3] } + endPoint = { x: point[0], y: point[1] } + } + } linesAnalysis.push({ - start: { x: point[0], y: point[1] }, - end: { x: point[2], y: point[3] }, + start: startPoint, + end: endPoint, left: baseLines.findIndex((line) => line === r.left), right: baseLines.findIndex((line) => line === r.right), type: TYPES.RIDGE, @@ -4305,13 +4281,8 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { iterations++ /*linesAnalysis.forEach((line) => { - const point = [line.start.x, line.start.y, line.end.x, line.end.y] - const checkLine = new fabric.Line(point, { - stroke: 'red', - strokeWidth: 2, - parentId: roofId, - name: 'check', - }) + const point = { x1: line.start.x, y1: line.start.y, x2: line.end.x, y2: line.end.y } + const checkLine = createArrow(point, 'red', roofId) canvas.add(checkLine).renderAll() // canvas.remove(checkLine).renderAll() })*/ @@ -4521,22 +4492,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const gableLine = cLine.type === TYPES.GABLE_LINE ? cLine : pLine gableLine.connectCnt++ - /*const checkLine = new fabric.Line([gableLine.start.x, gableLine.start.y, gableLine.end.x, gableLine.end.y], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - const checkCircle = new fabric.Circle({ - left: intersect.x, - top: intersect.y, - radius: 5, - parentId: roofId, - name: 'check', - }) - canvas.add(checkLine, checkCircle) - canvas.renderAll()*/ - const uniqueBaseLines = [...new Set(relationBaseLines)] // 연결점에서 새로운 가선분을 생성 if (uniqueBaseLines.length > 2) { @@ -4600,9 +4555,25 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { let bisector console.log('isParallel(baseLine1, baseLine2)', isParallel(baseLine1, baseLine2)) if (isParallel(baseLine1, baseLine2)) { + let cPoint = [cLine.start.x, cLine.start.y, cLine.end.x, cLine.end.y] + let pPoint = [pLine.start.x, pLine.start.y, pLine.end.x, pLine.end.y] + const length1 = Math.sqrt(Math.pow(intersect.x - cPoint[2], 2) + Math.pow(intersect.y - cPoint[3], 2)) + const length2 = Math.sqrt(Math.pow(intersect.x - pPoint[2], 2) + Math.pow(intersect.y - pPoint[3], 2)) + + //교점 밖으로 뻗어나가는 선의 길이가 다를 경우 이등분선 계산이 틀어져서 조정 + if (!almostEqual(length1, length2)) { + const vector1 = { x: Math.sign(clamp01(cPoint[2] - cPoint[0])), y: Math.sign(clamp01(cPoint[3] - cPoint[1])) } + const vector2 = { x: Math.sign(clamp01(pPoint[2] - pPoint[0])), y: Math.sign(clamp01(pPoint[3] - pPoint[1])) } + const addLength = 100 + cPoint[2] = intersect.x + vector1.x * addLength + cPoint[3] = intersect.y + vector1.y * addLength + pPoint[2] = intersect.x + vector2.x * addLength + pPoint[3] = intersect.y + vector2.y * addLength + } + bisector = getBisectLines( - { x1: cLine.start.x, x2: cLine.end.x, y1: cLine.start.y, y2: cLine.end.y }, - { x1: pLine.start.x, y1: pLine.start.y, x2: pLine.end.x, y2: pLine.end.y }, + { x1: cPoint[0], y1: cPoint[1], x2: cPoint[2], y2: cPoint[3] }, + { x1: pPoint[0], y1: pPoint[1], x2: pPoint[2], y2: pPoint[3] }, ) } else { bisector = getBisectBaseLines(baseLine1, baseLine2, intersect, canvas) @@ -4868,8 +4839,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { prevLineVector.x === nextLineVector.x && prevLineVector.y === nextLineVector.y && baseLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && - prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE && - nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE + (prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE || nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE) ) { downRoofGable.push({ currLine: baseLine, currIndex: index, type: 'A' }) } @@ -4954,6 +4924,8 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } + if (gableLine.attributes.type !== LINE_TYPE.WALLLINE.GABLE) return + //기준점 let stdPoint = [] //반대쪽 라인을 찾기위한 vector @@ -5493,7 +5465,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } }) - // canvas.renderAll() //추가된 하단 지붕 라인 innerLines에 추가. innerLines.push(...downRoofLines) @@ -5563,7 +5534,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } }) - console.log('innerLines : ', innerLines) //지붕 innerLines에 추가. roof.innerLines = innerLines @@ -5574,6 +5544,43 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { canvas.renderAll() } +/** + * 라인 방향 확인 용 + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @param color + * @param roofId + * @returns {*} + */ +export const createArrow = ({ x1, y1, x2, y2 }, color, roofId) => { + const angle = Math.atan2(y2 - y1, x2 - x1) + const headLength = 15 + + const points = [ + { x: x1, y: y1 }, + { x: x2, y: y2 }, + { + x: x2 - headLength * Math.cos(angle - Math.PI / 7), + y: y2 - headLength * Math.sin(angle - Math.PI / 7), + }, + { x: x2, y: y2 }, + { + x: x2 - headLength * Math.cos(angle + Math.PI / 7), + y: y2 - headLength * Math.sin(angle + Math.PI / 7), + }, + ] + + return new fabric.Polyline(points, { + fill: 'transparent', + stroke: color, + strokeWidth: 3, + selectable: false, + parentId: roofId, + name: 'check', + }) +} /** * 선분과 선분의 교점을 구한다. * @param line1Start