dev #819
@ -3464,19 +3464,27 @@ export function ensureCounterClockwiseLines(lines) {
|
||||
if (!lines || lines.length < 3) return [...(lines || [])];
|
||||
|
||||
// 1. 모든 점을 연결 그래프로 구성
|
||||
// [graph drift fix 2026-05-06]
|
||||
// 좌표 0.1 단위 round 로 부동소수점 drift 흡수 (caller `_keyOfEdge` 정책과 통일).
|
||||
// raw 좌표 그대로 키를 만들면 drift (e.g. 100.0 vs 100.0000001) 로 같은 점이 다른 노드가 되어
|
||||
// graph 가 끊어짐 → traversal 중도 break → 결과 길이 < 입력 길이 → sortRoofLines 인덱스 어긋남
|
||||
// (간헐 발생, 사용자가 다시 그리면 정상화되던 증상의 근본 원인).
|
||||
const _r = (v) => Math.round(v * 10) / 10;
|
||||
const graph = new Map();
|
||||
|
||||
// 각 점에서 연결된 점들을 저장
|
||||
lines.forEach(line => {
|
||||
const p1 = `${line.x1},${line.y1}`;
|
||||
const p2 = `${line.x2},${line.y2}`;
|
||||
const x1r = _r(line.x1), y1r = _r(line.y1);
|
||||
const x2r = _r(line.x2), y2r = _r(line.y2);
|
||||
const p1 = `${x1r},${y1r}`;
|
||||
const p2 = `${x2r},${y2r}`;
|
||||
|
||||
if (!graph.has(p1)) graph.set(p1, []);
|
||||
if (!graph.has(p2)) graph.set(p2, []);
|
||||
|
||||
// 양방향 연결
|
||||
graph.get(p1).push({ x: line.x2, y: line.y2, line });
|
||||
graph.get(p2).push({ x: line.x1, y: line.y1, line });
|
||||
// 양방향 연결 (이웃 좌표도 rounded — 후속 `${n.x},${n.y}` 키가 graph 키와 일치)
|
||||
graph.get(p1).push({ x: x2r, y: y2r, line });
|
||||
graph.get(p2).push({ x: x1r, y: y1r, line });
|
||||
});
|
||||
|
||||
// 2. 왼쪽 상단 점 찾기
|
||||
@ -3524,8 +3532,10 @@ export function ensureCounterClockwiseLines(lines) {
|
||||
}, nextPoints[0]);
|
||||
|
||||
// 라인 추가 (방향 유지)
|
||||
// [graph drift fix 2026-05-06] line.x1/y1 은 raw, next.x/y 는 rounded → 0.05 (round 절반) 임계 approx 비교.
|
||||
// 정확비교 시 raw vs rounded 불일치로 isReversed 가 항상 true 가 될 위험 차단.
|
||||
const line = next.line;
|
||||
const isReversed = (line.x1 !== next.x || line.y1 !== next.y);
|
||||
const isReversed = (Math.abs(line.x1 - next.x) > 0.05 || Math.abs(line.y1 - next.y) > 0.05);
|
||||
|
||||
result.push({
|
||||
...line,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user