diff --git a/B05_Profile/B05_Profile_Api_Replan.ts b/B05_Profile/B05_Profile_Api_Replan.ts index 90e775521..fcfcd16e7 100644 --- a/B05_Profile/B05_Profile_Api_Replan.ts +++ b/B05_Profile/B05_Profile_Api_Replan.ts @@ -5,10 +5,9 @@ * GET /projects/{id}/route/plan → 예상노선·계획노선 정점(사업지 좌표계 m) * POST /projects/{id}/route/replan → 고친 계획노선으로 갈아 끼우고 재계산 * POST /projects/{id}/route/replan/reset → 계획노선을 예상노선으로 되돌리고 재계산 - * POST /projects/{id}/route/profile-preview → 지금 노드의 균형 종단(편집 창 종단 띠) * GET /projects/{id}/route/terrain-sources → 고를 수 있는 분석 지형(라이다 · 수치지형도) * - * 편집 창 분석(지반고 · 횡단 미리보기 · 종단 띠 · 추천)은 **고른 분석 지형**(`terrain`)을 실어 + * 편집 창 분석(지반고 · 횡단 미리보기 · 추천)은 **고른 분석 지형**(`terrain`)을 실어 * 보낸다(PLAN 133-1) — [확인] 재계산은 확정 지표면 그대로라 안 실음. * * 재계산은 배수유역부터 전 단계를 다시 도는 무거운 작업이라(용화 67측점 기준 3분대) @@ -260,21 +259,3 @@ export async function resetRoutePlan(projectId: string): Promise { - const payload = await requestJson<{ profile: unknown }>( - `/projects/${projectId}/route/profile-preview`, - { - method: "POST", - body: JSON.stringify({ vertices, criteria, terrain: analysisTerrain(projectId) }), - }, - 120000, - ); - return payload.profile; -} diff --git a/B05_Profile/B05_Profile_Router_RouteInitial.py b/B05_Profile/B05_Profile_Router_RouteInitial.py index 2da4ffe04..7a7de9076 100644 --- a/B05_Profile/B05_Profile_Router_RouteInitial.py +++ b/B05_Profile/B05_Profile_Router_RouteInitial.py @@ -9,11 +9,10 @@ import functools import logging import time from pathlib import Path -from typing import Any, Literal +from typing import Any from uuid import UUID from fastapi.responses import JSONResponse -from pydantic import BaseModel, Field from B05_Profile import B05_Profile_Router_Replan as replan from B05_Profile.B05_Profile_Engine_RouteInitial import read_initial_choice @@ -277,19 +276,12 @@ async def balanced_profile_of( points: list[dict[str, float]], criteria: Any, design_curves: list[dict[str, Any]] | None = None, - terrain: Literal["las", "sheet"] | None = None, ) -> dict[str, Any] | None: - """노선 정점의 균형 종단 한 벌(`route_profile`) — [확인] 체인 · 편집 창 종단 띠가 함께 씀. - - `terrain` 은 편집 창 종단 띠만 바꿈(PLAN 133-1) — None = 지금 설계 지형([확인] 체인). - """ + """노선 정점의 균형 종단 한 벌(`route_profile`) — [확인] 체인 몫(지금 설계 지형).""" from B05_Profile.B05_Profile_Engine_Grade import legal_grade_limit_pct from B05_Profile.B05_Profile_Engine_RouteInitial_Profile import route_profile from B05_Profile.B05_Profile_Engine_Solver import _MODELS_SUBDIR - from common_util.common_util_surface_confirmation import ( - analysis_terrain_params, - get_surface_confirmation_params, - ) + from common_util.common_util_surface_confirmation import get_surface_confirmation_params from common_util.common_util_surface_sampler import build_surface_sampler grade_class, design_speed, terrain_type = await replan._road_settings(project_id) @@ -299,9 +291,8 @@ async def balanced_profile_of( pool = get_db_pool() async with pool.acquire() as connection: selection = await get_surface_confirmation_params(connection, str(project_id)) - selection = analysis_terrain_params(selection, terrain) try: - # 측점 생성과 같은 1 m 쌍선형 표본(추천 점수의 2 m 비용면 아님) — 띠 값 = [확인] 뒤 값 + # 측점 생성과 같은 1 m 쌍선형 표본(추천 점수의 2 m 비용면 아님) surface = await asyncio.to_thread( build_surface_sampler, project_root / _MODELS_SUBDIR, @@ -358,47 +349,3 @@ async def refresh_initial_snapshot( logger.info("노선 [확인] 초기값 다시 뜸: project_id=%s route_id=%s", project_id, route_id) except Exception: # noqa: BLE001 — 계산 결과는 그대로 남는다 logger.exception("노선 [확인] 초기값 스냅샷 실패: project_id=%s", project_id) - - -class ProfilePreviewRequest(BaseModel): - """편집 창 종단 띠(PLAN 75-1) — 지금 노드 · 지금 추천 제약.""" - - vertices: list[replan.RouteVertexInput] = Field(..., min_length=2) - criteria: replan.RouteInitialCriteria | None = None - terrain: Literal["las", "sheet"] | None = None - - -@replan.router.post("/{project_id}/route/profile-preview", response_model=None) -async def profile_preview( - project_id: UUID, request: ProfilePreviewRequest -) -> dict[str, Any] | JSONResponse: - """지금 노드의 균형 종단 — [확인]과 같은 폴리라인(같은 R · CSV 자릿수) · 같은 셈. - - 파일 · DB 를 쓰지 않는다. 「종단 반영」 켬일 때 편집 창 띠가 노드를 놓을 때마다 부른다. - """ - from common_util.common_util_route_polyline import build_planned_polyline - - paths = await replan._project_paths(project_id) - if paths is None: - return JSONResponse(status_code=404, content=replan._PROJECT_PATH_MISSING) - project_root, _ = paths - radius_m, _, _ = await replan._plan_criteria(project_id) - built = build_planned_polyline( - [(v.x, v.y) for v in request.vertices], - min_radius_m=radius_m, - simplify=False, - curve_flags=[bool(v.curve) for v in request.vertices], - radii=[v.radius_m for v in request.vertices], - ) - # [확인]은 CSV(소수 4자리)로 적은 뒤 읽는다 — 같은 점을 셈하게 같은 자릿수로. - points = [{"x": round(float(x), 4), "y": round(float(y), 4)} for x, y in built.vertices] - curves = [curve.as_dict() for curve in built.curves] - profile = await balanced_profile_of( - project_id, project_root, points, request.criteria, curves, request.terrain - ) - if profile is None: - return JSONResponse( - status_code=409, - content={"status": "error", "message": "이 노선으로 균형 종단을 세우지 못했습니다."}, - ) - return {"status": "success", "project_id": str(project_id), "profile": profile} diff --git a/B05_Profile/B05_Profile_UI_RouteEdit.ts b/B05_Profile/B05_Profile_UI_RouteEdit.ts index b2a88106c..84143a10a 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit.ts @@ -68,7 +68,6 @@ import { writeRouteLocks, } from "./B05_Profile_UI_RouteEdit_Lock"; import { createInitialPanel, type InitialPanelParams } from "./B05_Profile_UI_RouteEdit_Initial"; -import { createProfileStrip } from "./B05_Profile_UI_RouteEdit_ProfileStrip"; import { applyArcLocks, applyCurveLimits, @@ -277,22 +276,6 @@ export async function mountRouteEditor( planMinRadiusM: () => minRadiusM, apply: (snapshot, message) => restoreSnapshot(snapshot, message, true), }); - /** 지도 아래 종단 띠 — 노드를 놓을 때마다 다시 묻는다(PLAN 75-1). 셈은 `_ProfileStrip` 몫. */ - const strip = createProfileStrip({ - root: overlay.querySelector("[data-strip]")!, - projectId, - withProfile: initial.withProfile, - now: () => ({ - vertices: planned.map(([x, y], index) => ({ - x, - y, - curve: curveOn[index] !== false, - radius_m: curveRadius[index] ?? null, - })), - line: plannedLine.length ? plannedLine : planned, - criteria: initial.current().criteria, - }), - }); // [반영 전으로] — 마지막 반영(페이지를 세운 때) 노선 · 그 걸음의 「현재 추천」으로. 되돌리기로 다시 살림. overlay.querySelector('[data-act="cancel"]')!.addEventListener("click", () => { const snapshot = history?.reset(); @@ -463,7 +446,6 @@ export async function mountRouteEditor( draw(); if (record) history?.commit(snapshotNow()); historyControls.sync(); - strip.refresh(); } /** 지금 편집값을 사진 한 벌로 담는다 — 되돌리기가 쌓아 두는 것. */ @@ -544,7 +526,6 @@ export async function mountRouteEditor( commit: () => { history?.commit(snapshotNow()); historyControls.sync(); - strip.refresh(); }, }); @@ -594,7 +575,7 @@ export async function mountRouteEditor( terrain: pickedTerrain, stationSnap: () => stationSnap, initial, - profileShown: strip.settle, + profileShown: async () => initial.withProfile(), // 띠 없음(345-5) — 지금 추천 갈래가 정함 onApplied, }); @@ -682,7 +663,6 @@ export async function mountRouteEditor( useBackground(background); measure.clear(); slope.refresh(); - strip.refresh(); void crossPreview.refresh(); showStatus(); draw(); @@ -692,7 +672,6 @@ export async function mountRouteEditor( resize(); // 칸 크기가 서 있으면 여기서 보던 화면을 연다(아니면 처음 보일 때). showStatus(); draw(); - strip.refresh(); } catch (error) { status.textContent = error instanceof Error ? error.message : "노선을 읽지 못했습니다."; } diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts index 08f3e7d91..cf85dcb7a 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts @@ -59,7 +59,7 @@ export function createRouteEditChrome(