sk line angle

This commit is contained in:
ysCha 2025-11-20 19:19:27 +09:00
parent 9527e6cf0c
commit b6f6fd7128

View File

@ -431,8 +431,8 @@ export const skeletonBuilder = (roofId, canvas, textMode) => {
*/
const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
if (!skeleton?.Edges) return []
const roof = canvas?.getObjects().find((object) => object.id === roofId)
const wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId)
let roof = canvas?.getObjects().find((object) => object.id === roofId)
let wall = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.WALL && obj.attributes.roofId === roofId)
let skeletonLines = []
const processedInnerEdges = new Set()
@ -513,7 +513,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
//벽라인
const wallLines = wall.lines
skeletonLines.forEach(sktLine => {
skeletonLines.forEach((sktLine, skIndex) => {
let { p1, p2, attributes, lineStyle } = sktLine;
// 중복방지 - 라인을 고유하게 식별할 수 있는 키 생성 (정규화된 좌표로 정렬하여 비교)
@ -532,6 +532,8 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
{ x: sktLine.p2.x, y: sktLine.p2.y }
);
//그림을 그릴때 idx 가 필요함 roof는 왼쪽부터 시작됨 - 그림그리는 순서가 필요함
const skeletonLine = new QLine([p1.x, p1.y, p2.x, p2.y], {
parentId: roof.id,
fontSize: roof.fontSize,
@ -543,7 +545,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
isBaseLine: sktLine.attributes.isOuterEdge,
lineName: (sktLine.attributes.isOuterEdge)?'roofLine': attributes.type,
selectable:(!sktLine.attributes.isOuterEdge),
roofId: roofId,
});
@ -552,7 +554,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
existingLines.add(lineKey); // 추가된 라인을 추적
//skeleton 라인에서 처마선은 삭제
if(skeletonLine.lineName === 'roofLine'){
const coordinateText = new fabric.Text(`(${Math.round(skeletonLine.x1)}, ${Math.round(skeletonLine.y1)})`, {
@ -596,11 +598,12 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
//wall.lines 는 기본 벽 라인
//wall.baseLine은 움직인라인
wall.lines.forEach((wallLine, index) => {
console.log("wallLine:::::", wallLine, index)
let p1,p2,p3, p4
let idx = 0;
let isMoveLine = true;
let isMoveLine = false;
if (wallLine.startPoint.x !== wallLine.x1) wallLine.startPoint.x = wallLine.x1
if (wallLine.startPoint.y !== wallLine.y1) wallLine.startPoint.y = wallLine.y1
@ -611,24 +614,72 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
const wallLineEndPoint = {x:wallLine.x2, y:wallLine.y2}
const moveLine = wall.baseLines[index] //이동한 wall 존재여부 (초기 wall line = base line)
if(isSamePoint(moveLine.startPoint, wallLineStartPoint) && isSamePoint(moveLine.endPoint, wallLineEndPoint)){
console.log("outerLine1:::::", wallLine, idx)
isMoveLine = false;
let testLine = new QLine([moveLine.x1, moveLine.y1, moveLine.x2, moveLine.y2], {
stroke: 'yellow',
strokeWidth: 10,
property: 'normal',
fontSize: 14,
});
// Then in your code:
if (doLinesIntersect(moveLine, wallLine)) {
// Lines intersect, don't add the test line
if (testLine) {
canvas.remove(testLine);
canvas.renderAll();
}
} else {
// Lines don't intersect, safe to add test line
if (testLine) {
canvas.remove(testLine);
}
canvas.add(testLine);
canvas.renderAll();
}
if(isMoveLine){
//wallLine 의 index는 맨 왼쪽 부터 0으로 변경
const roofIndex = (wallLine.idx === 0)? wall.lines.length : wallLine.idx //(0-6, 1-1, 2-2, 3-3
const roofLines = canvas.getObjects().filter(obj => obj.name === 'roof' && obj.id === roofId).map(obj => obj.lines).flat();
const roofLine = roofLines[roofIndex-1];
//현재 움직인 처마라인
const currentRoofLines = canvas
.getObjects()
.filter((obj) => obj.lineName === 'roofLine' && obj.roofId === roofId)
.filter((obj) => obj.lineName === 'roofLine' && obj.parentId === roofId)
const currentRoofLine = findClosestParallelLine(roofLine, currentRoofLines);
const testLine2 = new QLine([roofLine.x1, roofLine.y1, roofLine.x2, roofLine.y2], {
stroke: 'red',
strokeWidth: 10,
property: 'normal',
fontSize: 14,
})
const testLine3 = new QLine([currentRoofLine.x1, currentRoofLine.y1, currentRoofLine.x2, currentRoofLine.y2], {
stroke: 'blue',
strokeWidth: 10,
property: 'normal',
fontSize: 14,
})
//canvas.add(testLine2);
canvas.add(testLine);
//canvas.add(testLine3);
canvas.renderAll()
const moveLine = wall.baseLines[index]
const roofLine = roof.lines[index]
//roof 접점
@ -638,21 +689,21 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
const p1wallLine = findClosestRoofLine(wallLineStartPoint,wall.lines)
const p2wallLine = findClosestRoofLine(wallLineEndPoint,wall.lines)
//move 접점
const p1moveLine = findClosestRoofLine(moveLine.startPoint, currentRoofLines)
const p1moveLine = findClosestRoofLine(moveLine.startPoint, wall.l)
const p2moveLine = findClosestRoofLine(moveLine.endPoint, currentRoofLines)
//wall move 접점
const p1outerLine = findClosestRoofLine(wallLineStartPoint, currentRoofLines)
const p2outerLine = findClosestRoofLine(wallLineEndPoint, currentRoofLines)
console.log("p1RoofLineV",p1RoofLine)
console.log("p2RoofLineV",p2RoofLine)
console.log("p1wallLineV",p1wallLine)
console.log("p2wallLineV",p2wallLine)
console.log("p1moveLineV",p1moveLine)
console.log("p2moveLineV",p2moveLine)
console.log("p1outerLine",p1outerLine)
console.log("p2outerLine",p2outerLine)
// console.log("p1RoofLineV",p1RoofLine)
// console.log("p2RoofLineV",p2RoofLine)
// console.log("p1wallLineV",p1wallLine)
// console.log("p2wallLineV",p2wallLine)
// console.log("p1moveLineV",p1moveLine)
// console.log("p2moveLineV",p2moveLine)
// console.log("p1outerLine",p1outerLine)
// console.log("p2outerLine",p2outerLine)
// const outerLines= canvas.getObjects().filter((obj) => obj.name === 'outerLine' && obj.attributes.roofId === roofId)
// const outerLine = outerLines[index]
// canvas.remove(outerLine)
@ -1080,7 +1131,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
if(isPolygon){
drawPolygon( p1,p2,p3, p4)
}
// const wallLine = wall.baseLines[roofLine.idx - 1];
@ -1098,7 +1149,7 @@ const createInnerLinesFromSkeleton = (roofId, canvas, skeleton, textMode) => {
//wallLine이 baseLine의 위 또는 오른쪽에 있을때
// let outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine' && obj.attributes.roofId === roofId)
// outerLines.forEach((outerLine) => {
@ -3286,4 +3337,131 @@ function getMovementInfo(p1, p2, newP1, newP2) {
dx: dx1,
dy: dy1
};
}
}
function getLineAngleDirection(line, isLeftSide = true) {
const dx = line.x2 - line.x1;
const dy = line.y2 - line.y1;
// 수평선인 경우 (y 좌표가 거의 같은 경우)
if (Math.abs(dy) < 0.1) {
// x 좌표 비교로 좌우 방향 결정
return line.x2 > line.x1 ? 'right' : 'left';
}
// 수직선인 경우 (x 좌표가 거의 같은 경우)
if (Math.abs(dx) < 0.1) {
// y 좌표 비교로 상하 방향 결정
return line.y2 > line.y1 ? 'down' : 'up';
}
// 대각선의 경우 기존 로직 유지
const angle = Math.atan2(dy, dx) * (180 / Math.PI);
const normalizedAngle = (angle + 360) % 360;
if (normalizedAngle >= 45 && normalizedAngle < 135) {
return 'up';
} else if (normalizedAngle >= 135 && normalizedAngle < 225) {
return 'left';
} else if (normalizedAngle >= 225 && normalizedAngle < 315) {
return 'down';
} else {
return 'right';
}
}
function findRoofLineIndex(roof, p1, p2) {
if (!roof || !roof.lines || !Array.isArray(roof.lines)) {
console.error("Invalid roof object or lines array");
return -1;
}
// Create a tolerance for floating point comparison
const TOLERANCE = 0.1;
// Try to find a line that matches either (p1,p2) or (p2,p1)
const index = roof.lines.findIndex(line => {
// Check if points match in order
const matchOrder =
(Math.abs(line.x1 - p1.x) < TOLERANCE &&
Math.abs(line.y1 - p1.y) < TOLERANCE &&
Math.abs(line.x2 - p2.x) < TOLERANCE &&
Math.abs(line.y2 - p2.y) < TOLERANCE);
// Check if points match in reverse order
const matchReverse =
(Math.abs(line.x1 - p2.x) < TOLERANCE &&
Math.abs(line.y1 - p2.y) < TOLERANCE &&
Math.abs(line.x2 - p1.x) < TOLERANCE &&
Math.abs(line.y2 - p1.y) < TOLERANCE);
return matchOrder || matchReverse;
});
if (index === -1) {
console.warn("No matching roof line found for points:", p1, p2);
}
return index;
}
function findClosestParallelLine(roofLine, currentRoofLines) {
// Determine if the line is horizontal or vertical
const isHorizontal = Math.abs(roofLine.y2 - roofLine.y1) < 0.001; // Using a small threshold for floating point comparison
const isVertical = Math.abs(roofLine.x2 - roofLine.x1) < 0.001;
if (!isHorizontal && !isVertical) {
console.warn('Line is neither perfectly horizontal nor vertical');
return null;
}
// Calculate the reference point (midpoint of the line)
const refX = (roofLine.x1 + roofLine.x2) / 2;
const refY = (roofLine.y1 + roofLine.y2) / 2;
let closestLine = null;
let minDistance = Infinity;
currentRoofLines.forEach(line => {
// Skip the same line
if (line === roofLine) return;
// Check if the line is parallel (same orientation)
const lineIsHorizontal = Math.abs(line.y2 - line.y1) < 0.001;
const lineIsVertical = Math.abs(line.x2 - line.x1) < 0.001;
if ((isHorizontal && lineIsHorizontal) || (isVertical && lineIsVertical)) {
// Calculate midpoint of the current line
const lineMidX = (line.x1 + line.x2) / 2;
const lineMidY = (line.y1 + line.y2) / 2;
// Calculate distance between midpoints
const distance = Math.sqrt(
Math.pow(lineMidX - refX, 2) +
Math.pow(lineMidY - refY, 2)
);
// Update closest line if this one is closer
if (distance < minDistance) {
minDistance = distance;
closestLine = line;
}
}
});
return closestLine;
}
function doLinesIntersect(line1, line2) {
const x1 = line1.x1, y1 = line1.y1;
const x2 = line1.x2, y2 = line1.y2;
const x3 = line2.x1, y3 = line2.y1;
const x4 = line2.x2, y4 = line2.y2;
// Calculate the direction of the lines
const uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
const uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
// If uA and uB are between 0-1, lines are colliding
return (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1);
}