refactor(종단보기): 345-4 정리 — 빈 saveCorridorIfDirty 와 부르는 곳 지움 · B05 등고선 주소 두 곳 = contourAssetUrl(미리 받기와 같은 파일)

- 3D 뷰어 · 노선 편집 바탕 등고선이 같은 주소 한 벌(recalculate=false 붙음 · 보관함 한 칸)
- 시험: test_345_4_contour_one_url 2 · 관련 250 통과

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
2026-10-16 11:39:56 +09:00
co-authored by Claude Opus 5.5
parent 8a2060ffbd
commit 593ee198aa
7 changed files with 40 additions and 21 deletions
-5
View File
@@ -53,7 +53,6 @@ import {
structureAnchorM,
} from "../../B05_Profile/B05_Profile_Api_Structures";
import { pipeToFacilityItem } from "../../B05_Profile/B05_Profile_UI_Structures_Panel_Types";
import { saveCorridorIfDirty } from "../../B05_Profile/B05_Profile_UI_Corridor";
import {
profileSaveParts,
type PageActionContext,
@@ -404,10 +403,6 @@ export async function mountProfileView(
}
profilePick.paint();
},
// 보기를 떠나는 자리 = 코리도 영구저장 시점(2026-08-23 사용자 확정) — 이동은 막지 않는다.
onHide: () => {
if (state.latest?.route?.id) void saveCorridorIfDirty(activeProjectId, state.latest.route.id);
},
});
/** [노선 반영] 끝 — 서버가 배수유역부터 다시 셌고 그 결과가 새 초기값이다. 새로고침 대신 페이지를
+1 -3
View File
@@ -7,7 +7,7 @@
import { showToast } from "@ui/ui_template_elements";
import { updateContourInterval } from "../../B05_Profile/B05_Profile_Api_Fetch";
import { refreshCorridor, saveCorridorIfDirty } from "../../B05_Profile/B05_Profile_UI_Corridor";
import { refreshCorridor } from "../../B05_Profile/B05_Profile_UI_Corridor";
import type { createLatestSource } from "../../B05_Profile/B05_Profile_UI_Page_Latest";
import { toBounds } from "../../B05_Profile/B05_Profile_UI_Page_Helpers";
import type { ViewControlCallbacks } from "../../B05_Profile/B05_Profile_UI_Panel_View";
@@ -64,8 +64,6 @@ export function createProfile3d(deps: Profile3dDeps) {
);
// 측점 바·라벨·램프도 계획고를 따라 움직여야 한다(2026-08-23 지적 ③).
deps.sections().renderStationLines(detail);
// 만든 것을 **바로 올려 둔다**(2026-09-06) — 다음 진입이 네트워크 없이 선다.
void saveCorridorIfDirty(projectId, latest.route.id);
},
};
-3
View File
@@ -184,9 +184,6 @@ export async function ensureCorridor(
return build;
}
/** 옛 올림 자리 — 3D 길 모형은 서버가 [저장]·[확정] 때 지음(342-2). 부르는 곳이 지워지면 함께 지움. */
export async function saveCorridorIfDirty(_projectId: string, _routeId: number): Promise<void> {}
/** ③ 사면이 읽을 측점 단면을 얹는다(115-1 · 저장본에는 안 담긴다). */
function withSections(
build: CorridorBuildResult | null,
@@ -13,7 +13,6 @@ import {
invalidateSectionDetail,
saveCachedCrossPatches,
} from "../B06_Section/B06_Section_Section_Store";
import { saveCorridorIfDirty } from "./B05_Profile_UI_Corridor";
import type { createRoutePanel } from "./B05_Profile_UI_Panel";
import type { createRouteProfilePanel } from "./B05_Profile_UI_Profile_Panel";
import type { createStructuresBridge } from "./B05_Profile_UI_Page_Structures";
@@ -87,9 +86,6 @@ export function profileSaveParts(ctx: PageActionContext): DesignViewSave {
// 서버가 종단 정본의 계획선을 다시 썼다 — 공유 캐시를 비워 횡단 보기가 옛 계획선을 못 보게 한다.
invalidateSectionDetail(projectId);
ctx.renderLatest(await ctx.loadLatest(true));
// 저장 = 코리도 영구저장 시점(2026-08-23) — 실패해도 저장은 성공 처리.
const routeId = ctx.latest()?.route?.id;
if (routeId) void saveCorridorIfDirty(projectId, routeId);
},
};
}
@@ -11,8 +11,7 @@
* 그리기·라벨·집기가 출처를 안 가리게 한다.
* ========================================================================== */
import { API_BASE_URL } from "@config/config_frontend";
import { fetchCachedJson } from "../A00_Common/b_asset_cache";
import { contourAssetUrl, fetchCachedJson } from "../A00_Common/b_asset_cache";
import {
createNormalizer,
type GeoJsonCollection,
@@ -71,8 +70,7 @@ export async function loadRouteEditContours(
// 3D 뷰어가 쓰는 것과 **같은 파일**이다 — 보관함에 있으면 다시 내려받지 않는다.
const data = await fetchCachedJson<ContourResponse>(
projectId,
`${API_BASE_URL}/projects/${projectId}/surface/models/${options.surfaceModelId}` +
`/contour?interval=${interval}&smooth=${options.smooth}`,
contourAssetUrl(projectId, options.surfaceModelId, interval, options.smooth),
);
const all = data.contours ?? [];
const onUnit = (level: number): boolean => Math.abs(level % LAS_CONTOUR_UNIT_M) < 1e-6;
+2 -2
View File
@@ -4,7 +4,7 @@ import { createTerrainCompass } from "@ui/ui_template_compass";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";
import { API_BASE_URL } from "@config/config_frontend";
import { fetchCachedBytes, fetchCachedJson } from "../A00_Common/b_asset_cache";
import { contourAssetUrl, fetchCachedBytes, fetchCachedJson } from "../A00_Common/b_asset_cache";
import { bindCursorPivotControls, TOP_VIEW_TILT } from "../B04_PreProcess/B04_PreProcess_UI_Camera";
import {
createRouteMarkers,
@@ -325,7 +325,7 @@ export function createRouteViewer(): RouteViewer {
contours: Array<{ level: number; coordinates: [number, number, number][] }>;
}>(
current.projectId,
`${API_BASE_URL}/projects/${current.projectId}/surface/models/${current.modelId}/contour?interval=${interval}&smooth=${current.smooth}`,
contourAssetUrl(current.projectId, current.modelId, interval, current.smooth),
);
clearContours();
// 등고선 한 가닥마다 3D 객체를 만들면 수백 개가 된다. 주곡선·보조곡선 두 덩어리로 합친다.
@@ -0,0 +1,35 @@
"""345-4 정리 — B05 등고선 주소 한 벌(`contourAssetUrl` · 미리 받기와 같은 파일) · 빈 saveCorridorIfDirty 지움."""
from __future__ import annotations
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def _read(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
def test_B05_등고선_주소는_한_벌():
for rel in (
"B05_Profile/B05_Profile_UI_Viewer.ts",
"B05_Profile/B05_Profile_UI_RouteEdit_Contour.ts",
):
source = _read(rel)
assert "contourAssetUrl(" in source, rel
assert "/contour?interval" not in source, rel
# 미리 받기(b_asset_cache)도 같은 함수 — 주소가 같아야 보관함 한 칸을 같이 씀
assert "contourAssetUrl(projectId, confirmed.model_id, interval, smooth)" in _read(
"A00_Common/b_asset_cache.ts"
)
def test_빈_코리도_올림_함수_지움():
for rel in (
"B05_Profile/B05_Profile_UI_Corridor.ts",
"B05_Profile/B05_Profile_UI_Page_Actions.ts",
"A00_Common/design/design_view_profile.ts",
"A00_Common/design/design_view_profile_3d.ts",
):
assert "saveCorridorIfDirty" not in _read(rel), rel