skeleton-utils

This commit is contained in:
Cha 2025-09-16 00:14:03 +09:00
parent 7d9b6d5225
commit 99c7759e00

View File

@ -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 } };
};