feat(B04): 지표면 3D 뷰어에 방위 콤파스 추가
뷰어 좌표 규약이 `x, 높이, -y` 라 세계 북쪽은 -z 다. 카메라 오프셋(카메라 − 타깃)의 수평 성분으로 도북이 화면에서 몇 도 돌아갔는지 계산해(atan2(offset.x, offset.z)) 바늘을 돌린다. 뷰어 우하단 — 축척 막대(좌하단)의 반대편에 둔다. 뷰어 파일이 이미 946줄이라 콤파스는 별도 모듈로 분리(700줄 제한). 애니메이션 루프에서 0.5° 이상 움직였을 때만 transform 을 다시 쓴다. 검증: typecheck 통과. 공용 브라우저 실측 — [상단] 시점 0°(바늘이 북쪽=화면 위), [사시도] 41.6°, 캔버스 220px 드래그 시 218.6° 로 카메라와 함께 회전. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import { fetchCachedBytes, fetchCachedJson } from "../A00_Common/b_asset_cache";
|
||||
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
|
||||
import { createProgressCircle } from "@ui/ui_template_progress";
|
||||
// 계획선 색은 2D 지도·B05 배수유역도와 한 곳에서 나온다 — 같은 선을 다른 색으로 그리지 않는다.
|
||||
import { createTerrainCompass } from "./B04_PreProcess_UI_Compass";
|
||||
import { routeLineColor } from "./B04_PreProcess_UI_MapRender";
|
||||
import type { SurfaceBounds, SurfaceModelSummary } from "./B04_PreProcess_Api_Fetch";
|
||||
import {
|
||||
@@ -166,6 +167,10 @@ export function createSurfaceTerrainViewer(): SurfaceTerrainViewer {
|
||||
scaleBar.append(scaleLabel);
|
||||
viewerArea.append(scaleBar);
|
||||
|
||||
// 방위 콤파스 — 축척 막대 반대편(우하단). 바늘 각도는 애니메이션 루프가 맞춘다.
|
||||
const compass = createTerrainCompass();
|
||||
viewerArea.append(compass.root);
|
||||
|
||||
// Elevation bounds legend bar overlay (I-403)
|
||||
const legendBar = document.createElement("div");
|
||||
legendBar.style.position = "absolute";
|
||||
@@ -794,6 +799,8 @@ export function createSurfaceTerrainViewer(): SurfaceTerrainViewer {
|
||||
// Render scale bar dynamically
|
||||
if (terrainMesh && terrainMesh.visible) {
|
||||
scaleBar.hidden = false;
|
||||
compass.setVisible(true);
|
||||
compass.update(camera.position.x - controls.target.x, camera.position.z - controls.target.z);
|
||||
const dist = camera.position.distanceTo(controls.target);
|
||||
const metersPerPixel = targetPlaneMetersPerPixel(dist, viewerArea.clientHeight);
|
||||
const roughMeters = 100 * metersPerPixel;
|
||||
@@ -803,6 +810,7 @@ export function createSurfaceTerrainViewer(): SurfaceTerrainViewer {
|
||||
prettyMeters >= 1000 ? `${(prettyMeters / 1000).toFixed(0)} km` : `${prettyMeters} m`;
|
||||
} else {
|
||||
scaleBar.hidden = true;
|
||||
compass.setVisible(false);
|
||||
}
|
||||
|
||||
// 등고 라벨 위치 — 화면이 실제로 움직였을 때만 다시 계산한다(매 프레임 재계산은 낭비).
|
||||
|
||||
Reference in New Issue
Block a user