Compare commits

..

No commits in common. "3c094b3c5ad2550dc5e3861b2f760591e50032e2" and "ee79c0e680bc8be74f3137e0e525921a89d38f2e" have entirely different histories.

4 changed files with 39 additions and 168 deletions

View File

@ -16,7 +16,6 @@ export const QLine = fabric.util.createClass(fabric.Line, {
children: [],
padding: 5,
textVisible: true,
textBaseline: 'alphabetic',
initialize: function (points, options, length = 0) {
// 소수점 전부 제거

View File

@ -6,7 +6,6 @@ import { calculateAngle, drawGableRoof, drawRidgeRoof, drawShedRoof, toGeoJSON }
import * as turf from '@turf/turf'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import Big from 'big.js'
import { drawSkeletonRidgeRoof } from '@/util/skeleton-utils'
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
type: 'QPolygon',
@ -336,8 +335,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
if (types.every((type) => type === LINE_TYPE.WALLLINE.EAVES)) {
// 용마루 -- straight-skeleton
console.log('용마루 지붕')
//drawRidgeRoof(this.id, this.canvas, textMode)
drawSkeletonRidgeRoof(this.id, this.canvas, textMode);
drawRidgeRoof(this.id, this.canvas, textMode)
//drawSkeletonRidgeRoof(this.id, this.canvas, textMode);
} else if (isGableRoof(types)) {
// A형, B형 박공 지붕
console.log('패턴 지붕')

View File

@ -370,7 +370,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
}}
options={{
allowNegative: false,
allowDecimal: true //(index !== 0),
allowDecimal: false //(index !== 0),
}}
/>
</div>

View File

@ -470,7 +470,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
}
});
/*
//2. 연결이 끊어진 스켈레톤 선을 찾아 연장합니다.
const { disconnectedLines } = findDisconnectedSkeletonLines(skeletonLines, roof.lines);
@ -492,9 +492,8 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
trimIntersectingExtendedLines(skeletonLines, disconnectedLines);
}
*/
//2. 연결이 끊어진 라인이 있을경우 찾아서 추가한다(동 이동일때)
// 3. 최종적으로 정리된 스켈레톤 선들을 QLine 객체로 변환하여 캔버스에 추가합니다.
const innerLines = [];
@ -533,142 +532,15 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
selectable:(!line.attributes.isOuterEdge),
roofId: roofId,
});
canvas.add(innerLine);
innerLine.bringToFront();
existingLines.add(lineKey); // 추가된 라인을 추적
//skeleton 라인에서 처마선은 삭제
if(innerLine.lineName !== 'outerLine'){
canvas.add(innerLine);
innerLine.bringToFront();
existingLines.add(lineKey); // 추가된 라인을 추적
// canvas.add(innerLine);
// innerLine.bringToFront();
// existingLines.add(lineKey); // 추가된 라인을 추적
}else{
const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
const wallLines = wall.baseLines
// 현재 지점과 다음 지점을 비교하기 위한 변수
let changedLine = roof.moveSelectLine;
const roofLines = [];
if (!wall.lines || !wall.baseLines) {
return wall.baseLines || wall.lines || [];
}
// 길이가 다른 경우 baseLines 반환
if (wall.lines.length !== wall.baseLines.length) {
return wall.baseLines;
}
for (let i = 0; i < wall.baseLines.length; i++) {
const baseLine = wall.baseLines[i];
const line = wall.lines[i];
if (!line ||
((!isSamePoint(baseLine.startPoint, line.startPoint)) && // 시작점이 다르고
(!isSamePoint(baseLine.endPoint, line.endPoint)))) { // 끝점도 다른 경우
}
}
const startClosest = findClosestRoofLine(p1, roof.lines);
const endClosest = findClosestRoofLine(p2, roof.lines);
const { point, closest, selectPoint, otherPoint } =
startClosest.distance > endClosest.distance
? {
point : p2,
closest : endClosest,
otherPoint: p1
}
: {
point : p1,
closest : startClosest,
otherPoint: p2
};
// Log the relevant information
console.log("Point:", point);
console.log("Closest intersection:", closest);
console.log("moveSelectLinePoint:", selectPoint);
let isTarget = false;
for(const roofLine of roof.lines){
if( isSamePoint(p1, roofLine.startPoint) ||
isSamePoint(p2, roofLine.endPoint) ||
isSamePoint(p1, roofLine.endPoint) ||
isSamePoint(p2, roofLine.startPoint) ) {
isTarget = true ;
break
}
}
if (isTarget) {
console.warn("matching line found in roof.lines");
return; // 또는 적절한 오류 처리
}
const innerLine2 = new QLine([p1.x, p1.y, p2.x, p2.y], {
parentId: roof.id,
fontSize: roof.fontSize,
stroke: 'red',
strokeWidth: lineStyle.width,
name: (line.attributes.isOuterEdge)?'eaves': attributes.type,
attributes: attributes,
direction: direction,
isBaseLine: line.attributes.isOuterEdge,
lineName: (line.attributes.isOuterEdge)?'addLine': attributes.type,
selectable:(!line.attributes.isOuterEdge),
roofId: roofId,
});
canvas.add(innerLine2);
//existingLines.add(lineKey); // 추가된 라인을 추적
/*
//라인추가(까지 못할때때) 외벽선에서 추가
const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
const wallLines = wall.baseLines
// 현재 지점과 다음 지점을 비교하기 위한 변수
let changedLine = roof.moveSelectLine;
const roofLines = [];
if (!wall.lines || !wall.baseLines) {
return wall.baseLines || wall.lines || [];
}
// 길이가 다른 경우 baseLines 반환
if (wall.lines.length !== wall.baseLines.length) {
return wall.baseLines;
}
//그려지는 처마라인이 처마 && 포인터모두가 wall.baseLine에 들어가 있는 경우
const checkPoint = {x1:line.x1, y1:line.y1, x2:line.x2, y2:line.y2}
if(line.attributes.type === 'hip' && !checkPointInPolygon(checkPoint, wall)) {
const startClosest = findClosestRoofLine(p1, roof.lines);
const endClosest = findClosestRoofLine(p2, roof.lines);
console.log("Lindd::::",line)
const { point, closest, selectPoint, otherPoint } =
startClosest.distance > endClosest.distance
? {
point : p2,
closest : endClosest,
//selectPoint : changedLine.endPoint,
otherPoint: p1
}
: {
point : p1,
closest : startClosest,
//selectPoint : changedLine.startPoint,
otherPoint: p2
};
// Log the relevant information
console.log("Point:", point);
console.log("Closest intersection:", closest);
console.log("moveSelectLinePoint:", selectPoint);
}
*/
const coordinateText = new fabric.Text(`(${Math.round(p1.x)}, ${Math.round(p1.y)})`, {
left: p1.x + 5, // 좌표점에서 약간 오른쪽으로 이동
top: p1.y - 20, // 좌표점에서 약간 위로 이동
@ -712,8 +584,8 @@ function processEavesEdge(roofId, canvas, skeleton, edgeResult, skeletonLines) {
);
if(!outerLine) {
outerLine = findMatchingLine(edgeResult.Polygon, roof, roof.points);
console.log('Has matching line:', outerLine);
outerLine = findMatchingLine(edgeResult.Polygon, roof, roof.points);
//console.log('Has matching line:', outerLine);
}
let pitch = outerLine?.attributes?.pitch??0
@ -864,13 +736,13 @@ function isOuterEdge(p1, p2, edges) {
* 스켈레톤 라인 배열에 새로운 라인을 추가합니다. (중복 방지)
* @param id
* @param {Array} skeletonLines - 스켈레톤 라인 배열
* @param {Set} processedInnerEdges - 처리된 Edge Set
* @param {object} p1 - 시작점
* @param {object} p2 - 끝점
* @param {string} lineType - 라인 타입
* @param {string} color - 색상
* @param {number} width - 두께
* @param pitch
* @param isOuterLine
* @param currentDegree
*/
function addRawLine(id, skeletonLines, p1, p2, lineType, color, width, pitch, isOuterLine) {
// const edgeKey = [`${p1.x.toFixed(1)},${p1.y.toFixed(1)}`, `${p2.x.toFixed(1)},${p2.y.toFixed(1)}`].sort().join('|');
@ -1690,14 +1562,14 @@ function clipLineToRoofBoundary(p1, p2, roofLines, selectLine) {
// p2가 다각형 내부에 있는지 확인
const p2Inside = isPointInsidePolygon(p2, roofLines);
//console.log('p1Inside:', p1Inside, 'p2Inside:', p2Inside);
console.log('p1Inside:', p1Inside, 'p2Inside:', p2Inside);
// 두 점 모두 내부에 있으면 그대로 반환
if (p1Inside && p2Inside) {
if(!selectLine || isDiagonal){
return { p1: clippedP1, p2: clippedP2 };
}
//console.log('평행선::', clippedP1, clippedP2)
console.log('평행선::', clippedP1, clippedP2)
return { p1: clippedP1, p2: clippedP2 };
}
@ -1730,20 +1602,20 @@ function clipLineToRoofBoundary(p1, p2, roofLines, selectLine) {
if (!p1Inside && !p2Inside) {
// 두 점 모두 외부에 있는 경우
if (intersections.length >= 2) {
//console.log('Both outside, using intersection points');
console.log('Both outside, using intersection points');
clippedP1.x = intersections[0].point.x;
clippedP1.y = intersections[0].point.y;
clippedP2.x = intersections[1].point.x;
clippedP2.y = intersections[1].point.y;
} else {
//console.log('Both outside, no valid intersections - returning original');
console.log('Both outside, no valid intersections - returning original');
// 교차점이 충분하지 않으면 원본 반환
return { p1: clippedP1, p2: clippedP2 };
}
} else if (!p1Inside && p2Inside) {
// p1이 외부, p2가 내부
if (intersections.length > 0) {
//console.log('p1 outside, p2 inside - moving p1 to intersection');
console.log('p1 outside, p2 inside - moving p1 to intersection');
clippedP1.x = intersections[0].point.x;
clippedP1.y = intersections[0].point.y;
// p2는 이미 내부에 있으므로 원본 유지
@ -1753,7 +1625,7 @@ function clipLineToRoofBoundary(p1, p2, roofLines, selectLine) {
} else if (p1Inside && !p2Inside) {
// p1이 내부, p2가 외부
if (intersections.length > 0) {
//console.log('p1 inside, p2 outside - moving p2 to intersection');
console.log('p1 inside, p2 outside - moving p2 to intersection');
// p1은 이미 내부에 있으므로 원본 유지
clippedP1.x = p1.x;
clippedP1.y = p1.y;
@ -1786,6 +1658,7 @@ function isPointInsidePolygon2(point, roofLines) {
if (((y1 > y) !== (y2 > y)) && (x < (x2 - x1) * (y - y1) / (y2 - y1) + x1)) {
inside = !inside;
}
}
return inside;
@ -2185,19 +2058,19 @@ export const getSelectLinePosition = (wall, selectLine, options = {}) => {
const { x1, y1, x2, y2 } = lineCoords;
//console.log('wall.points', wall.baseLines);
console.log('wall.points', wall.baseLines);
for(const line of wall.baseLines) {
//console.log('line', line);
console.log('line', line);
const basePoint = extractLineCoords(line);
const { x1: bx1, y1: by1, x2: bx2, y2: by2 } = basePoint;
//console.log('x1, y1, x2, y2', bx1, by1, bx2, by2);
console.log('x1, y1, x2, y2', bx1, by1, bx2, by2);
// 객체 비교 대신 좌표값 비교
if (Math.abs(bx1 - x1) < 0.1 &&
Math.abs(by1 - y1) < 0.1 &&
Math.abs(bx2 - x2) < 0.1 &&
Math.abs(by2 - y2) < 0.1) {
//console.log('basePoint 일치!!!', basePoint);
console.log('basePoint 일치!!!', basePoint);
}
}
@ -2205,11 +2078,11 @@ export const getSelectLinePosition = (wall, selectLine, options = {}) => {
// 라인 방향 분석
const lineInfo = analyzeLineOrientation(x1, y1, x2, y2, epsilon);
// if (debug) {
// console.log('=== getSelectLinePosition ===');
// console.log('selectLine 좌표:', lineCoords);
// console.log('라인 방향:', lineInfo.orientation);
// }
if (debug) {
console.log('=== getSelectLinePosition ===');
console.log('selectLine 좌표:', lineCoords);
console.log('라인 방향:', lineInfo.orientation);
}
// 라인의 중점
const midX = (x1 + x2) / 2;
@ -2228,11 +2101,11 @@ export const getSelectLinePosition = (wall, selectLine, options = {}) => {
const topIsInside = checkPointInPolygon(topTestPoint, wall);
const bottomIsInside = checkPointInPolygon(bottomTestPoint, wall);
// if (debug) {
// console.log('수평선 테스트:');
// console.log(' 위쪽 포인트:', topTestPoint, '-> 내부:', topIsInside);
// console.log(' 아래쪽 포인트:', bottomTestPoint, '-> 내부:', bottomIsInside);
// }
if (debug) {
console.log('수평선 테스트:');
console.log(' 위쪽 포인트:', topTestPoint, '-> 내부:', topIsInside);
console.log(' 아래쪽 포인트:', bottomTestPoint, '-> 내부:', bottomIsInside);
}
// top 조건: 위쪽이 외부, 아래쪽이 내부
if (!topIsInside && bottomIsInside) {
@ -2290,9 +2163,9 @@ export const getSelectLinePosition = (wall, selectLine, options = {}) => {
midPoint: { x: midX, y: midY }
};
// if (debug) {
// console.log('최종 결과:', result);
// }
if (debug) {
console.log('최종 결과:', result);
}
return result;
};