qcast-front/.claude/memory/project_index_master_roofLines.md

38 lines
3.3 KiB
Markdown

---
name: 페어링 인덱스 master = roofLines 정책
description: skeleton-utils.js 라인 페어링 정렬 master 를 wallLines→roofLines 로 변경한 정책 (2026-04-27)
type: project
---
**정책**: `src/util/skeleton-utils.js` (~1342~1359) 의 라인 페어링 정렬에서 **roofLines 를 단일 master** 로 사용. wall.lines / wall.baseLines 는 roofLines 의 raw 인덱스 1:1 매핑으로 정렬.
**Why**:
- 사용자 원칙: "인덱스가 여기에는 생명이다. leftTop(최저 좌표) 꼭짓점에서 시작해 CCW 로 그려 나간다."
- **사용자가 다각형을 시계방향(CW)으로 그릴 수도 있음** → 그래서 인덱스를 다시 세워야 한다. 항상 **최저 좌표(leftTop, min-Y → min-X)**#1 로 놓고 CCW 로 재정렬해 정규화. 사용자의 그리는 방향(CW/CCW)에 무관하게 고유한 시작점/순서를 보장.
- 종전 master 였던 `wallLines (= wall.lines)``useMode.js:1880`, `usePropertiesSetting.js:165`, `useRoofShapePassivitySetting.js:242` 에서 재할당 가능 → 시작점 산정이 흔들릴 위험.
- `roofLines` 는 외곽(처마) 경계라 사용자 mutation 영향 없음 → 시작점 안정.
- B-7 OVER 시 보조라인이 B-5/B-3 위치에 그려진 간헐 버그가 정렬 master 흔들림에서 비롯됐을 가능성.
**How to apply**:
- ensureCounterClockwiseLines 의 입력은 roofLines (master). leftTop = min-Y → tiebreak min-X 꼭짓점에서 CCW.
- wall.lines, wall.baseLines 는 raw 인덱스 보존이 전제 (코드상 페어링 1:1 가정).
- `_keyOfEdge` 는 좌표를 0.1 단위로 라운드 후 양 끝점 정렬 키 생성 → 부동소수점 drift 흡수.
- `ensureCounterClockwiseLines` 내부 graph 키도 0.1 단위 round (2026-05-06 추가) — caller `_keyOfEdge` 와 동일 정책으로 통일.
- 매핑 실패 시 fallback 으로 sortRoofLines 항목 자체를 사용 (안전망).
- 추후 wall.* 가 수정될 때 raw 인덱스가 보존되는지 검증 필요. 만약 깨진다면 매핑 키를 좌표 대신 라인 ID 기반으로 변경 검토.
**ensureCounterClockwiseLines drift 보강 (2026-05-06)**:
- 증상: 같은 도형인데 간헐적으로 인덱스 시작점/순서가 바뀌는 현상 (사용자가 다시 그리면 정상화).
- 원인: 함수 내부 `graph` Map 키가 raw 좌표 (`${line.x1},${line.y1}`) 라서 drift (e.g. 100.0 vs 100.0000001) 로 같은 점이 별개 노드로 등록 → graph 끊어짐 → traversal 중도 break → result.length < lines.length 페어링 어긋남.
- 수정 위치 (`skeleton-utils.js:3463`):
1. `:3469-3480` graph 빌드 endpoint 좌표 `Math.round(v*10)/10` round, 이웃 객체 `{x,y}` rounded 저장 (후속 `${n.x},${n.y}` 키가 graph 키와 일치)
2. `:3528` `isReversed` 비교를 정확비교 `Math.abs(line.x1 - next.x) > 0.05` approx (round 절반 임계). raw line.x1 vs rounded next.x 불일치 false-positive 차단
- 영역 보존: atan2 / area 부호 / result 라인 좌표는 raw 그대로 (다운스트림 정확도 유지).
- 정상 케이스 (drift 없음) 동작 변화 없음. 100.0 round = 100.0.
**관련**:
- `feedback_over_move_silent_skip.md` (OVER 클램핑 정책)
- `project_over_move_red_helper_deferred.md` (빨강 보조선 별건 이슈)
- `project_parallel_collapse_fix.md` (평행 이동 SK 붕괴)
- `feedback_same_point_tolerance.md` (좌표 매칭 tolerance)