From 3a3afe9b3bf978b7e3baf478a0ba6820ee84f78c Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 8 Jan 2026 10:26:24 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EC=8B=A4=EB=82=B4=EC=A7=91=EC=A4=91?= =?UTF-8?q?=ED=98=95=20=EB=B6=81=EB=A9=B4=EB=AA=A8=EB=93=88=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/type/PassivityCircuitAllocation.jsx | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) 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 a25a1a37..b3c38c8e 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -123,10 +123,14 @@ export default function PassivityCircuitAllocation(props) { } // 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))] + 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({ @@ -142,16 +146,12 @@ export default function PassivityCircuitAllocation(props) { const originHaveThisPcsModules = canvas .getObjects() .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.pcs && obj.pcs.id === selectedPcs.id) - // 이미 해당 pcs로 설치된 모듈의 surface의 방향을 구한다. - const originSurfaceList = canvas - .getObjects() - .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && originHaveThisPcsModules.map((obj) => obj.surfaceId).includes(obj.id)) + // 1. 북면모듈, 북면외모듈 혼합 여부 체크 + const targetModuleInfos = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && targetModules.includes(obj.id)) + debugger + const newTargetModuleGroup = [...new Set(targetModuleInfos.concat(originHaveThisPcsModules).map((obj) => obj.moduleInfo.northModuleYn))] - originSurfaceList.concat(originSurfaceList).forEach((surface) => { - surfaceType[`${surface.direction}-${surface.roofMaterial.pitch}`] = surface - }) - - if (Object.keys(surfaceType).length > 1) { + if (newTargetModuleGroup.length > 1) { swalFire({ text: getMessage('module.circuit.fix.not.same.roof.error'), type: 'alert', @@ -234,7 +234,6 @@ export default function PassivityCircuitAllocation(props) { setSelectedPcs(tempSelectedPcs) canvas.add(moduleCircuitText) }) - const roofSurfaceList = canvas .getObjects() From ddd3eaf82a65199ebb1de83a6616b73014270e75 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 8 Jan 2026 12:54:00 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EC=B9=98=EC=88=98=20=ED=91=9C=EC=8B=9C=20?= =?UTF-8?q?=EC=84=A0=201=EC=9D=98=20=EC=9E=90=EB=A6=AC=200=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=82=98=EC=98=A4=EB=8A=94=20=ED=98=84=EC=83=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/canvas-util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index b2ee57db..5c51560b 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -80,7 +80,7 @@ export const getCenterPoint = (point1, point2) => { * @returns */ export const getDistance = (x1, y1, x2, y2) => { - return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)).toFixed(0) + return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)).toFixed(1) } // polygon의 각 변에 해당 점과 점 사이의 거리를 나타내는 IText를 추가하는 함수 From 49253b766846709b0ba3ce4427b777227a2ee8df Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 8 Jan 2026 15:04:00 +0900 Subject: [PATCH 3/3] =?UTF-8?q?1390=20=E3=80=90HANASYS=20DESIGN=E3=80=91?= =?UTF-8?q?=EB=B3=B5=EB=8F=84=EC=97=90=EC=84=9C=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20=EC=B9=98=EC=88=98=20=EC=B7=A8?= =?UTF-8?q?=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QLine.js | 14 ++++++---- src/hooks/useLine.js | 6 ++-- src/hooks/usePolygon.js | 51 ++++++++++++++++++++++++++++++++-- src/util/qpolygon-utils.js | 11 ++++++++ 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 02448cd7..d1e1ada3 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -72,13 +72,17 @@ export const QLine = fabric.util.createClass(fabric.Line, { setLength() { // Ensure all required properties are valid numbers - const { x1, y1, x2, y2 } = this; + const { x1, y1, x2, y2 } = this if (isNaN(x1) || isNaN(y1) || isNaN(x2) || isNaN(y2)) { - logger.error('Invalid coordinates in QLine:', { x1, y1, x2, y2 }); - this.length = 0; - return; + logger.error('Invalid coordinates in QLine:', { x1, y1, x2, y2 }) + this.length = 0 + return } - this.length = calcLinePlaneSize({ x1, y1, x2, y2 }) / 10; + this.length = calcLinePlaneSize({ x1, y1, x2, y2 }) / 10 + }, + + setLengthByValue(length) { + this.length = length / 10 }, addLengthText() { diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index 66dff769..c9de0194 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -10,7 +10,7 @@ import { } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' import { basicSettingState } from '@/store/settingAtom' -import { calcLineActualSize } from '@/util/qpolygon-utils' +import { calcLineActualSizeByLineLength } from '@/util/qpolygon-utils' import { getDegreeByChon } from '@/util/canvas-util' import { useText } from '@/hooks/useText' import { fontSelector } from '@/store/fontAtom' @@ -181,7 +181,7 @@ export const useLine = () => { if (isVertical) { line.attributes = { ...line.attributes, - actualSize: calcLineActualSize(line, getDegreeByChon(pitch)), + actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)), } } else if (isDiagonal) { const yLength = Math.abs(y2 - y1) * 10 @@ -195,7 +195,7 @@ export const useLine = () => { if (isHorizontal) { line.attributes = { ...line.attributes, - actualSize: calcLineActualSize(line, getDegreeByChon(pitch)), + actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)), } } else if (isDiagonal) { const xLength = Math.abs(x2 - x1) * 10 diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 011b8852..8822fd5f 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1,7 +1,19 @@ -import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, globalPitchState, pitchTextSelector } from '@/store/canvasAtom' +import { + ANGLE_TYPE, + canvasState, + currentAngleTypeSelector, + globalPitchState, + pitchTextSelector, +} from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' import { fabric } from 'fabric' -import { calculateIntersection, findAndRemoveClosestPoint, getDegreeByChon, getDegreeInOrientation, isPointOnLine } from '@/util/canvas-util' +import { + calculateIntersection, + findAndRemoveClosestPoint, + getDegreeByChon, + getDegreeInOrientation, + isPointOnLine, +} from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils' import { basicSettingState, flowDisplaySelector } from '@/store/settingAtom' @@ -1958,6 +1970,38 @@ export const usePolygon = () => { canvas.renderAll() } + /** + * 폴리곤의 라인 길이가 10 이하로 차이나는 경우 작은 값으로 통일 + * @param polygon + */ + const unifyLineLengths = (polygon) => { + if (!polygon.lines || polygon.lines.length === 0) { + return + } + + const lines = polygon.lines + + for (let i = 0; i < lines.length; i++) { + for (let j = i + 1; j < lines.length; j++) { + const length1 = lines[i].getLength() + const length2 = lines[j].getLength() + const diff = Math.abs(length1 - length2) + + if (diff > 0 && diff <= 10) { + const minLength = Math.min(length1, length2) + if (length1 > length2) { + lines[i].setLengthByValue(minLength) + } else { + lines[j].setLengthByValue(minLength) + } + } + } + } + + addLengthText(polygon) + canvas.renderAll() + } + /** * 폴리곤의 라인 속성을 복도치수, 실제치수에 따라 actualSize 설정 * @param polygon @@ -1966,7 +2010,7 @@ export const usePolygon = () => { if (!polygon.lines || polygon.lines.length === 0 || !polygon.roofMaterial) { return } - + unifyLineLengths(polygon) polygon.lines.forEach((line) => { setActualSize(line, polygon.direction, +polygon.roofMaterial?.pitch) }) @@ -1983,5 +2027,6 @@ export const usePolygon = () => { splitPolygonWithLines, splitPolygonWithSeparate, setPolygonLinesActualSize, + unifyLineLengths, } } diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index abcd66ce..e1ff8575 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -5992,6 +5992,17 @@ export const calcLineActualSize = (points, degree = 0) => { return Big(planeSize).div(theta).round().toNumber() } +/** + * 포인트와 기울기를 기준으로 선의 길이를 구한다. + * @param lineLength + * @param degree + * @returns number + */ +export const calcLineActualSizeByLineLength = (lineLength, degree = 0) => { + const theta = Big(Math.cos(Big(degree).times(Math.PI).div(180))) + return Big(lineLength).div(theta).round().toNumber() +} + export const createLinesFromPolygon = (points) => { const lines = [] for (let i = 0; i < points.length; i++) {