소스정리1
This commit is contained in:
parent
273f62bd0c
commit
4d2b872183
@ -2017,6 +2017,7 @@ export {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds the opposite line in a polygon based on the given line
|
||||
* @param {Array} edges - The polygon edges from canvas.skeleton.Edges
|
||||
@ -2267,7 +2268,6 @@ function clipLineToRoofBoundary(p1, p2, roofLines, selectLine) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function isPointInsidePolygon(point, roofLines) {
|
||||
// 1. 먼저 경계선 위에 있는지 확인 (방향 무관)
|
||||
if (isOnBoundaryDirectionIndependent(point, roofLines)) {
|
||||
@ -2387,6 +2387,81 @@ function getLineDirection(p1, p2) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 점이 선분 위에 있는지 확인하는 헬퍼 함수
|
||||
* @param {Object} point - 확인할 점 {x, y}
|
||||
* @param {Object} lineStart - 선분의 시작점 {x, y}
|
||||
* @param {Object} lineEnd - 선분의 끝점 {x, y}
|
||||
* @param {number} epsilon - 허용 오차
|
||||
* @returns {boolean}
|
||||
*/
|
||||
// function isPointOnLineSegment(point, lineStart, lineEnd, epsilon = 0.1) {
|
||||
// const dx = lineEnd.x - lineStart.x;
|
||||
// const dy = lineEnd.y - lineStart.y;
|
||||
// const length = Math.sqrt(dx * dx + dy * dy);
|
||||
//
|
||||
// if (length === 0) {
|
||||
// // 선분의 길이가 0이면 시작점과의 거리만 확인
|
||||
// return Math.abs(point.x - lineStart.x) < epsilon && Math.abs(point.y - lineStart.y) < epsilon;
|
||||
// }
|
||||
//
|
||||
// // 점에서 선분의 시작점까지의 벡터
|
||||
// const toPoint = { x: point.x - lineStart.x, y: point.y - lineStart.y };
|
||||
//
|
||||
// // 선분 방향으로의 투영 길이
|
||||
// const t = (toPoint.x * dx + toPoint.y * dy) / (length * length);
|
||||
//
|
||||
// // t가 0과 1 사이에 있어야 선분 위에 있음
|
||||
// if (t < 0 || t > 1) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// // 선분 위의 가장 가까운 점
|
||||
// const closestPoint = {
|
||||
// x: lineStart.x + t * dx,
|
||||
// y: lineStart.y + t * dy
|
||||
// };
|
||||
//
|
||||
// // 점과 가장 가까운 점 사이의 거리
|
||||
// const dist = Math.sqrt(
|
||||
// Math.pow(point.x - closestPoint.x, 2) +
|
||||
// Math.pow(point.y - closestPoint.y, 2)
|
||||
// );
|
||||
//
|
||||
// return dist < epsilon;
|
||||
// }
|
||||
|
||||
// selectLine과 baseLines 비교하여 방향 찾기
|
||||
function findLineDirection(selectLine, baseLines) {
|
||||
for (const baseLine of baseLines) {
|
||||
// baseLine의 시작점과 끝점
|
||||
const baseStart = baseLine.startPoint;
|
||||
const baseEnd = baseLine.endPoint;
|
||||
|
||||
// selectLine의 시작점과 끝점
|
||||
const selectStart = selectLine.startPoint;
|
||||
const selectEnd = selectLine.endPoint;
|
||||
|
||||
// 정방향 또는 역방향으로 일치하는지 확인
|
||||
if ((isSamePoint(baseStart, selectStart) && isSamePoint(baseEnd, selectEnd)) ||
|
||||
(isSamePoint(baseStart, selectEnd) && isSamePoint(baseEnd, selectStart))) {
|
||||
|
||||
// baseLine의 방향 계산
|
||||
const dx = baseEnd.x - baseStart.x;
|
||||
const dy = baseEnd.y - baseStart.y;
|
||||
|
||||
// 기울기를 바탕으로 방향 판단
|
||||
if (Math.abs(dx) > Math.abs(dy)) {
|
||||
return dx > 0 ? 'right' : 'left';
|
||||
} else {
|
||||
return dy > 0 ? 'down' : 'up';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null; // 일치하는 라인이 없는 경우
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* baseLines를 연결하여 다각형 순서로 정렬된 점들 반환
|
||||
@ -2709,89 +2784,54 @@ const analyzeLineOrientation = (x1, y1, x2, y2, epsilon = 0.5) => {
|
||||
};
|
||||
};
|
||||
|
||||
function extendLineToBoundary(p1, p2, roofLines) {
|
||||
// 1. Calculate line direction and length
|
||||
const dx = p2.x - p1.x;
|
||||
const dy = p2.y - p1.y;
|
||||
const length = Math.sqrt(dx * dx + dy * dy);
|
||||
if (length === 0) return { p1: { ...p1 }, p2: { ...p2 } };
|
||||
|
||||
// 2. Get all polygon points
|
||||
const points = [];
|
||||
const seen = new Set();
|
||||
// 점에서 선분까지의 최단 거리를 계산하는 도우미 함수
|
||||
function pointToLineDistance(point, lineP1, lineP2) {
|
||||
const A = point.x - lineP1.x;
|
||||
const B = point.y - lineP1.y;
|
||||
const C = lineP2.x - lineP1.x;
|
||||
const D = lineP2.y - lineP1.y;
|
||||
|
||||
for (const line of roofLines) {
|
||||
const p1 = { x: line.x1, y: line.y1 };
|
||||
const p2 = { x: line.x2, y: line.y2 };
|
||||
const dot = A * C + B * D;
|
||||
const lenSq = C * C + D * D;
|
||||
let param = -1;
|
||||
|
||||
const key1 = `${p1.x},${p1.y}`;
|
||||
const key2 = `${p2.x},${p2.y}`;
|
||||
|
||||
if (!seen.has(key1)) {
|
||||
points.push(p1);
|
||||
seen.add(key1);
|
||||
}
|
||||
if (!seen.has(key2)) {
|
||||
points.push(p2);
|
||||
seen.add(key2);
|
||||
}
|
||||
if (lenSq !== 0) {
|
||||
param = dot / lenSq;
|
||||
}
|
||||
|
||||
// 3. Find the bounding box
|
||||
let minX = Infinity, minY = Infinity;
|
||||
let maxX = -Infinity, maxY = -Infinity;
|
||||
let xx, yy;
|
||||
|
||||
for (const p of points) {
|
||||
minX = Math.min(minX, p.x);
|
||||
minY = Math.min(minY, p.y);
|
||||
maxX = Math.max(maxX, p.x);
|
||||
maxY = Math.max(maxY, p.y);
|
||||
if (param < 0) {
|
||||
xx = lineP1.x;
|
||||
yy = lineP1.y;
|
||||
} else if (param > 1) {
|
||||
xx = lineP2.x;
|
||||
yy = lineP2.y;
|
||||
} else {
|
||||
xx = lineP1.x + param * C;
|
||||
yy = lineP1.y + param * D;
|
||||
}
|
||||
|
||||
// 4. Extend line to bounding box
|
||||
const bboxLines = [
|
||||
{ x1: minX, y1: minY, x2: maxX, y2: minY }, // top
|
||||
{ x1: maxX, y1: minY, x2: maxX, y2: maxY }, // right
|
||||
{ x1: maxX, y1: maxY, x2: minX, y2: maxY }, // bottom
|
||||
{ x1: minX, y1: maxY, x2: minX, y2: minY } // left
|
||||
];
|
||||
|
||||
const intersections = [];
|
||||
|
||||
// 5. Find intersections with bounding box
|
||||
for (const line of bboxLines) {
|
||||
const intersect = getLineIntersection(
|
||||
p1, p2,
|
||||
{ x: line.x1, y: line.y1 },
|
||||
{ x: line.x2, y: line.y2 }
|
||||
);
|
||||
|
||||
if (intersect) {
|
||||
const t = ((intersect.x - p1.x) * dx + (intersect.y - p1.y) * dy) / (length * length);
|
||||
if (t >= 0 && t <= 1) {
|
||||
intersections.push({ x: intersect.x, y: intersect.y, t });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 6. If we have two intersections, use them
|
||||
if (intersections.length >= 2) {
|
||||
// Sort by t value
|
||||
intersections.sort((a, b) => a.t - b.t);
|
||||
return {
|
||||
p1: { x: intersections[0].x, y: intersections[0].y },
|
||||
p2: {
|
||||
x: intersections[intersections.length - 1].x,
|
||||
y: intersections[intersections.length - 1].y
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 7. Fallback to original points
|
||||
return { p1: { ...p1 }, p2: { ...p2 } };
|
||||
const dx = point.x - xx;
|
||||
const dy = point.y - yy;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
|
||||
const getOrientation = (line, eps = 0.1) => {
|
||||
const x1 = line.get('x1')
|
||||
const y1 = line.get('y1')
|
||||
const x2 = line.get('x2')
|
||||
const y2 = line.get('y2')
|
||||
const dx = Math.abs(x2 - x1)
|
||||
const dy = Math.abs(y2 - y1)
|
||||
|
||||
if (dx < eps && dy >= eps) return 'vertical'
|
||||
if (dy < eps && dx >= eps) return 'horizontal'
|
||||
if (dx < eps && dy < eps) return 'point'
|
||||
return 'diagonal'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2975,9 +3015,35 @@ function updateAndAddLine(innerLines, targetPoint) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 점이 선분 위에 있는지 확인
|
||||
* @param {Object} point - 확인할 점 {x, y}
|
||||
* @param {Object} lineStart - 선분의 시작점 {x, y}
|
||||
* @param {Object} lineEnd - 선분의 끝점 {x, y}
|
||||
* @param {number} tolerance - 오차 허용 범위
|
||||
* @returns {boolean} - 점이 선분 위에 있으면 true, 아니면 false
|
||||
*/
|
||||
function isPointOnLineSegment2(point, lineStart, lineEnd, tolerance = 0.1) {
|
||||
const { x: px, y: py } = point;
|
||||
const { x: x1, y: y1 } = lineStart;
|
||||
const { x: x2, y: y2 } = lineEnd;
|
||||
|
||||
// 선분의 길이
|
||||
const lineLength = Math.hypot(x2 - x1, y2 - y1);
|
||||
|
||||
// 점에서 선분의 양 끝점까지의 거리
|
||||
const dist1 = Math.hypot(px - x1, py - y1);
|
||||
const dist2 = Math.hypot(px - x2, py - y2);
|
||||
|
||||
// 점이 선분 위에 있는지 확인 (오차 허용 범위 내에서)
|
||||
const isOnSegment = Math.abs((dist1 + dist2) - lineLength) <= tolerance;
|
||||
|
||||
if (isOnSegment) {
|
||||
console.log(`점 (${px}, ${py})은 선분 [(${x1}, ${y1}), (${x2}, ${y2})] 위에 있습니다.`);
|
||||
}
|
||||
|
||||
return isOnSegment;
|
||||
}
|
||||
|
||||
/**
|
||||
* 세 점(p1 -> p2 -> p3)의 방향성을 계산합니다. (2D 외적)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user