feat(B04): 지표면 3D 방위 표시를 3축 트라이어드로 교체

옛 콤파스는 방위각(`atan2(ox, oz)`)만 써서 경사에 따른 남북 압축이 빠졌음 —
사시도 프리셋(오프셋 120·95·135, 앙각 27.7°)에서 바늘 41.6°, 화면 실제 북쪽 62.4°로
20.8° 어긋났음(2026-09-03 사용자 지적).

세계 축 N(−z)·E(+x)·Z(+y)를 카메라 화면 기저(오른쪽 r, 위 u)에 투영해 선과 글자를
그림. 기저는 카메라 오프셋만으로 구함(up = +y 고정). 뒤로 누운 축(깊이 > 0.25)과
정면으로 와 짧아진 축은 흐리게 그려 겹침을 줄임.

검증: typecheck 통과. 기본 시점에서 DOM 좌표가 해석값과 일치 —
N (28.0, 11.0) · E (45.0, 28.0) · Z (28.0, 27.4). 회전 중 거동은 사용자 화면 검증 대기.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-03 19:54:13 +09:00
co-authored by Claude Opus 5
parent b908a0b10d
commit dcabce147e
3 changed files with 93 additions and 39 deletions
@@ -800,7 +800,11 @@ export function createSurfaceTerrainViewer(): SurfaceTerrainViewer {
if (terrainMesh && terrainMesh.visible) {
scaleBar.hidden = false;
compass.setVisible(true);
compass.update(camera.position.x - controls.target.x, camera.position.z - controls.target.z);
compass.update(
camera.position.x - controls.target.x,
camera.position.y - controls.target.y,
camera.position.z - controls.target.z,
);
const dist = camera.position.distanceTo(controls.target);
const metersPerPixel = targetPlaneMetersPerPixel(dist, viewerArea.clientHeight);
const roughMeters = 100 * metersPerPixel;