From 99c7759e00c9597098786769606c49404046476d Mon Sep 17 00:00:00 2001 From: Cha Date: Tue, 16 Sep 2025 00:14:03 +0900 Subject: [PATCH] skeleton-utils --- src/util/skeleton-utils.js | 89 ++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/util/skeleton-utils.js b/src/util/skeleton-utils.js index 6ec643a4..77ce3412 100644 --- a/src/util/skeleton-utils.js +++ b/src/util/skeleton-utils.js @@ -4,8 +4,8 @@ */ import SkeletonBuilder from '@/lib/skeletons/SkeletonBuilder'; -import { fabric } from 'fabric'; -import { LINE_TYPE } from '@/common/common'; +import { fabric } from 'fabric' +import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { QLine } from '@/components/fabric/QLine'; import { calcLinePlaneSize } from '@/util/qpolygon-utils'; @@ -93,11 +93,14 @@ const extractUniqueLinesFromEdges = (skeletonEdges) => { export const drawSkeletonRidgeRoof = (roofId, canvas, textMode) => { try { const roof = canvas?.getObjects().find((object) => object.id === roofId); + const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) + if (!roof) { console.error(`Roof with id "${roofId}" not found.`); return; } + // 1. 기존 스켈레톤 라인 제거 const existingSkeletonLines = canvas.getObjects().filter(obj => obj.parentId === roofId && obj.attributes?.type === 'skeleton' @@ -111,6 +114,11 @@ export const drawSkeletonRidgeRoof = (roofId, canvas, textMode) => { return; } + /** 외벽선 */ + const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0) + const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 })) + + // 3. 스켈레톤 생성 const multiPolygon = [[coordinates]]; // GeoJSON MultiPolygon 형식 const skeleton = SkeletonBuilder.BuildFromGeoJSON(multiPolygon); @@ -127,15 +135,65 @@ export const drawSkeletonRidgeRoof = (roofId, canvas, textMode) => { const skeletonLines = []; const outerLines = pointsToLines(coordinates); + for (const baseLine of baseLines) { + const { type } = baseLine.get("attributes"); + + if(type === LINE_TYPE.WALLLINE.EAVES) { + + + + }else if(type === LINE_TYPE.WALLLINE.RIDGE) { + + } + } + linesToDraw.forEach((line, index) => { // 외곽선과 겹치는 스켈레톤 라인은 그리지 않음 const isOverlapping = outerLines.some(outerLine => linesOverlap(line, outerLine)); if (isOverlapping) { + // Array.find()를 사용하여 baseLines 배열에서 일치하는 라인을 찾습니다. + const foundBaseLine = baseLines.filter(baseLine => { + // baseLine (fabric.QLine)에서 좌표를 추출합니다. + const { p1: baseP1, p2: baseP2 } = getPointsFromQLine(baseLine); + + const attributes = baseLine.get('attributes'); + + // 2. 속성 객체에서 type 값을 추출합니다. + const type = attributes.type; + + // 이제 'type' 변수를 조건문 등에서 사용할 수 있습니다. + console.log('라인 타입:', type); + + // lineToDraw의 좌표 (p1, p2)와 baseLine의 좌표를 비교합니다. + // 라인 방향이 다를 수 있으므로 정방향과 역방향 모두 확인합니다. + + // 정방향 일치: (p1 -> p2) == (baseP1 -> baseP2) + const forwardMatch = + line.x1 === baseP1.x && line.y1 === baseP1.y && + line.x2 === baseP2.x && line.y2 === baseP2.y; + + // 역방향 일치: (p1 -> p2) == (baseP2 -> baseP1) + const reverseMatch = + line.x1 === baseP2.x && line.y1 === baseP2.y && + line.x2 === baseP1.x && line.y2 === baseP1.y; + + return forwardMatch || reverseMatch; + }); + + // 일치하는 라인을 찾았는지 확인 + if (foundBaseLine) { + console.log(`linesToDraw[${index}]와 일치하는 라인을 찾았습니다:`, foundBaseLine); + // 여기서 foundBaseLine을 사용하여 필요한 작업을 수행할 수 있습니다. + } else { + + console.log(`linesToDraw[${index}]에 대한 일치하는 라인을 찾지 못했습니다.`); + } console.log(`Skeleton line (edge ${line.edgeIndex}) is overlapping with a baseLine. It will not be drawn.`); return; } const isDiagonal = Math.abs(line.x1 - line.x2) > 1e-6 && Math.abs(line.y1 - line.y2) > 1e-6; + const isEaves = baseLinePoints.some(point => linesOverlap(line, point)); const skeletonLine = new QLine([line.x1, line.y1, line.x2, line.y2], { parentId: roofId, @@ -147,7 +205,7 @@ export const drawSkeletonRidgeRoof = (roofId, canvas, textMode) => { textMode: textMode, attributes: { roofId: roofId, - type: 'skeleton', // 스켈레톤 타입 식별자 + type: LINE_TYPE.WALLLINE.EAVES, // 스켈레톤 타입 식별자 skeletonIndex: line.edgeIndex, lineIndex: index, planeSize: calcLinePlaneSize(line), @@ -160,14 +218,19 @@ export const drawSkeletonRidgeRoof = (roofId, canvas, textMode) => { skeletonLines.push(skeletonLine); canvas.add(skeletonLine); + + // 6. roof 객체에 스켈레톤 라인 정보 업데이트 + roof.innerLines = [...(roof.innerLines || []), ...skeletonLines]; + skeletonLines.forEach(line => line.bringToFront()); + + canvas.renderAll(); + console.log(`Successfully drew ${linesToDraw.length} unique skeleton lines from ${skeleton.Edges.length} polygons.`); + + + }); - // 6. roof 객체에 스켈레톤 라인 정보 업데이트 - roof.innerLines = [...(roof.innerLines || []), ...skeletonLines]; - skeletonLines.forEach(line => line.bringToFront()); - canvas.renderAll(); - console.log(`Successfully drew ${linesToDraw.length} unique skeleton lines from ${skeleton.Edges.length} polygons.`); } catch (error) { console.error('An error occurred while generating the skeleton:', error); @@ -227,3 +290,13 @@ function pointsToLines(points) { return lines; } + + +/** + * fabric.QLine에서 시작점과 끝점을 가져옵니다. + * @param {fabric.QLine} line + * @returns {{p1: {x: number, y: number}, p2: {x: number, y: number}}} + */ +export const getPointsFromQLine = (line) => { + return { p1: { x: line.x1, y: line.y1 }, p2: { x: line.x2, y: line.y2 } }; +}; \ No newline at end of file