From a6e935bc15db88e0a9aee467cf49bc74241124fa Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 12 Dec 2025 15:20:28 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EB=8F=84=EB=A8=B8=20=EC=98=A4=ED=94=84?= =?UTF-8?q?=EC=85=8B=20=EC=84=A0=ED=83=9D=20=EC=8B=9C=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/object/DormerOffset.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/floor-plan/modal/object/DormerOffset.jsx b/src/components/floor-plan/modal/object/DormerOffset.jsx index fd3eb70a..1881b18e 100644 --- a/src/components/floor-plan/modal/object/DormerOffset.jsx +++ b/src/components/floor-plan/modal/object/DormerOffset.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import { useRecoilValue } from 'recoil' @@ -15,8 +15,8 @@ export default function DormerOffset(props) { const { closePopup } = usePopup() const [arrow1, setArrow1] = useState(null) const [arrow2, setArrow2] = useState(null) - const arrow1LengthRef = useRef() - const arrow2LengthRef = useRef() + const arrow1LengthRef = useRef(0) + const arrow2LengthRef = useRef(0) const [arrow1Length, setArrow1Length] = useState(0) const [arrow2Length, setArrow2Length] = useState(0) @@ -59,12 +59,12 @@ export default function DormerOffset(props) { name="" label="" className="input-origin block" - value={arrow1LengthRef.current.value} + value={arrow1LengthRef.current.value ?? 0} ref={arrow1LengthRef} onChange={(value) => setArrow1Length(value)} options={{ allowNegative: false, - allowDecimal: false + allowDecimal: false, }} /> From 53a1f4ed0053b7833e49f71f25cbf506309da6f3 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 12 Dec 2025 15:27:26 +0900 Subject: [PATCH 2/3] =?UTF-8?q?group=20object=20=EC=A2=8C=ED=91=9C=20?= =?UTF-8?q?=EC=9E=AC=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/fabric-extensions.js | 37 +++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/util/fabric-extensions.js b/src/util/fabric-extensions.js index 9410f764..acccc601 100644 --- a/src/util/fabric-extensions.js +++ b/src/util/fabric-extensions.js @@ -29,22 +29,39 @@ fabric.Rect.prototype.getCurrentPoints = function () { /** * fabric.Group에 getCurrentPoints 메서드를 추가 (도머 그룹용) - * 그룹의 groupPoints를 다시 계산하여 반환 + * 그룹 내 객체들의 점들을 수집하여 현재 월드 좌표를 반환 */ fabric.Group.prototype.getCurrentPoints = function () { - // groupPoints를 다시 계산 + // 그룹 내 객체들로부터 실시간으로 점들을 계산 + if (this._objects && this._objects.length > 0) { + let allPoints = [] - // 그룹에 groupPoints가 있으면 해당 점들을 사용 (도머의 경우) - if (this.groupPoints && Array.isArray(this.groupPoints)) { - const matrix = this.calcTransformMatrix() - console.log('this.groupPoints', this.groupPoints) - return this.groupPoints.map(function (p) { - const point = new fabric.Point(p.x, p.y) - return fabric.util.transformPoint(point, matrix) + // 그룹 내 모든 객체의 점들을 수집 + this._objects.forEach(function (obj) { + if (obj.getCurrentPoints && typeof obj.getCurrentPoints === 'function') { + const objPoints = obj.getCurrentPoints() + allPoints = allPoints.concat(objPoints) + } else if (obj.points && Array.isArray(obj.points)) { + const pathOffset = obj.pathOffset || { x: 0, y: 0 } + const matrix = obj.calcTransformMatrix() + const transformedPoints = obj.points + .map(function (p) { + return new fabric.Point(p.x - pathOffset.x, p.y - pathOffset.y) + }) + .map(function (p) { + return fabric.util.transformPoint(p, matrix) + }) + allPoints = allPoints.concat(transformedPoints) + } }) + + if (allPoints.length > 0) { + // Convex Hull 알고리즘을 사용하여 외곽 점들만 반환 + return this.getConvexHull(allPoints) + } } - // groupPoints가 없으면 바운딩 박스를 사용 + // 객체가 없으면 바운딩 박스를 사용 const bounds = this.getBoundingRect() const points = [ { x: bounds.left, y: bounds.top }, From be6fdce63c06282c7f29e535de68a28893cbc63e Mon Sep 17 00:00:00 2001 From: yscha Date: Sat, 13 Dec 2025 17:04:59 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=ED=95=A0=EB=8B=B9=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/skeleton-utils.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index c9a905d7..cbbc4127 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -766,15 +766,19 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { }); }; - const sortedWallLines = sortCurrentRoofLines(wall.lines); + // const sortedWallLines = sortCurrentRoofLines(wall.lines); // roofLines의 방향에 맞춰 currentRoofLines 조정 후 정렬 const alignedCurrentRoofLines = alignLineDirection(currentRoofLines, roofLines); const sortedCurrentRoofLines = sortCurrentRoofLines(alignedCurrentRoofLines); - const sortedRoofLines = sortCurrentRoofLines(roofLines); + // const sortedRoofLines = sortCurrentRoofLines(roofLines); const sortedWallBaseLines = sortCurrentRoofLines(wall.baseLines); - const sortedBaseLines = sortBaseLinesByWallLines(wall.baseLines, wallLines); + // const sortedBaseLines = sortBaseLinesByWallLines(wall.baseLines, wallLines); const sortRoofLines = sortBaseLinesByWallLines(roofLines, wallLines); + // 원본 wallLines를 복사하여 사용 + const sortedWallLines = [...wallLines]; + const sortedBaseLines = sortBaseLinesByWallLines(wall.baseLines, sortedWallLines); + const sortedRoofLines = sortBaseLinesByWallLines(roofLines, sortedWallLines); //wall.lines 는 기본 벽 라인 //wall.baseLine은 움직인라인 @@ -802,7 +806,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { const currentRoofLine = currentRoofLines[index]; const moveLine = sortedBaseLines[index] const wallBaseLine = sortedBaseLines[index] - console.log("wallBaseLine", wallBaseLine); + //console.log("wallBaseLine", wallBaseLine); //roofline 외곽선 설정 @@ -876,7 +880,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { return line } - getAddLine(roofLine.startPoint, roofLine.endPoint, ) + //getAddLine(roofLine.startPoint, roofLine.endPoint, ) //외곽선을 그린다 newPStart = { x: roofLine.x1, y: roofLine.y1 } newPEnd = { x: roofLine.x2, y: roofLine.y2 } @@ -1228,6 +1232,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { getAddLine({ x: pLineX, y: newPointY }, { x: sPoint.x, y: sPoint.y }, 'pink') } //getAddLine({ x: roofLine.x2, y: roofLine.y2 }, { x: roofLine.x2, y: newPointY }, 'orange') + } if(isStartEnd.end){ @@ -1479,6 +1484,8 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => { getAddLine(newPStart, newPEnd, 'red') //canvas.remove(roofLine) + }else{ + getAddLine(roofLine.startPoint, roofLine.endPoint, ) } canvas.renderAll() });