refactor(472-3 B05 코리도): 코리도 계산 8 파일 logic 이동 · 검사 도구 헛잡음 걷음

- B05 Corridor Build · Envelope · Station · Station_Structure · Structures · _Box · _Chute · _Path
  → B05_Profile/logic/B05_Profile_Corridor_*.ts (본문 그대로 · import 경로만)
- Structures 재수출 줄 걷음(700 줄 한도) · Envelope 는 Structures_Hash 를 바로 부름
- helper_472_3_graph = 줄 머리 import · export 만 셈(주석 속 낱말 안 셈)
- test_472_3 SESSION_PULLS 헛잡음 6 줄 · GEOMETRY_PULLS B05 8 줄 걷음
  (남은 ui_template_locale 10 = Route_Carry_Patch → common_util_svg 진짜 끌림)
- 옮긴 파일을 읽는 시험 · 헬퍼 경로 새 자리로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 19:08:29 +09:00
co-authored by Claude Opus 5.5
parent 1d5d63875b
commit 09a064da37
45 changed files with 121 additions and 138 deletions
+2 -2
View File
@@ -38,8 +38,8 @@ import { computeMassHaul, massHaulPayload } from "@util/common_util_mass_haul";
import type { MassHaulResult } from "@util/common_util_mass_haul";
import { computeHaulPlan, haulPlanPayload } from "@util/common_util_mass_haul_balance";
import type { RoutePoint } from "../../../B05_Profile/B05_Profile_Api_Fetch";
import { buildCorridor } from "../../../B05_Profile/B05_Profile_UI_Corridor_Build";
import { corridorHash, serialize } from "../../../B05_Profile/B05_Profile_UI_Corridor_Envelope";
import { buildCorridor } from "../../../B05_Profile/logic/B05_Profile_Corridor_Build";
import { corridorHash, serialize } from "../../../B05_Profile/logic/B05_Profile_Corridor_Envelope";
import type { SectionDetailResponse } from "../../../B06_Section/B06_Section_Api_Fetch";
import {
facilityAt,
@@ -224,7 +224,7 @@ export const FACILITY_ROWS: readonly CalcEntry[] = [
outputs: ["3D", "file:corridor"],
site: "browser_now",
stage: "corridor",
ts: `${B05}B05_Profile_UI_Corridor_Build.ts#buildCorridor`,
ts: `${B05}logic/B05_Profile_Corridor_Build.ts#buildCorridor`,
runner: "node:corridor.mesh",
pair: null,
mirror: [],
+2 -2
View File
@@ -20,8 +20,8 @@
import { readFileSync, writeFileSync } from "node:fs";
import type { SectionDetailResponse } from "../B06_Section/B06_Section_Api_Fetch";
import type { RoutePoint } from "./B05_Profile_Api_Fetch";
import { buildCorridor } from "./B05_Profile_UI_Corridor_Build";
import { corridorHash, serialize } from "./B05_Profile_UI_Corridor_Envelope";
import { buildCorridor } from "./logic/B05_Profile_Corridor_Build";
import { corridorHash, serialize } from "./logic/B05_Profile_Corridor_Envelope";
interface CorridorNodeInput {
detail: SectionDetailResponse;
+1 -1
View File
@@ -61,7 +61,7 @@ async def _resolve_project_root(project_id: UUID) -> Path | None:
# 저장본 머리에서 열쇠(해시)만 떼어 볼 만큼. 봉투 첫 두 칸이 `version`·`hash` 라
# (`B05_Profile_UI_Corridor_Envelope.serialize`) 이 안에 반드시 들어온다.
# (`logic/B05_Profile_Corridor_Envelope.serialize`) 이 안에 반드시 들어온다.
_HASH_HEAD_BYTES = 4096
_HASH_PATTERN = re.compile(rb'"hash"\s*:\s*"([0-9a-fA-F]+)"')
+2 -2
View File
@@ -25,14 +25,14 @@ import type { SectionDetailResponse } from "../B06_Section/B06_Section_Api_Fetch
import { reconcilePagePipeline } from "../A00_Common/design/design_pipeline_page";
import { calcOnServer } from "../A00_Common/design/design_calc_sites";
import type { RoutePoint } from "./B05_Profile_Api_Fetch";
import type { CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build";
import type { CorridorBuildResult } from "./logic/B05_Profile_Corridor_Build";
import { buildCorridorOffThread } from "./B05_Profile_UI_Corridor_Worker_Client";
import {
corridorHash,
ENVELOPE_VERSION,
deserialize,
type CorridorEnvelope,
} from "./B05_Profile_UI_Corridor_Envelope";
} from "./logic/B05_Profile_Corridor_Envelope";
/** 구조물별 서피스 대체/삽입 훅 — 별도 지침 후 구현 예정(2026-08-23 범위 제외). */
export interface CorridorStructureHook {
@@ -8,8 +8,8 @@
* ========================================================================== */
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import type { CorridorStructure } from "./B05_Profile_UI_Corridor_Structures";
import { structureSilhouettes } from "./B05_Profile_UI_Corridor_Station_Structure";
import type { CorridorStructure } from "./logic/B05_Profile_Corridor_Structures";
import { structureSilhouettes } from "./logic/B05_Profile_Corridor_Station_Structure";
import type { DeformLimit, DeformSide } from "./logic/B05_Profile_UI_Corridor_Deform";
/** 측점 프레임 축(모델 좌표) — 중심 · 좌향 단위 벡터. */
@@ -11,7 +11,7 @@
* ========================================================================== */
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import { classifyStation, pieceKey, type OffsetPoint } from "./B05_Profile_UI_Corridor_Station";
import { classifyStation, pieceKey, type OffsetPoint } from "./logic/B05_Profile_Corridor_Station";
/** 꺾임으로 남길 단면 꺾임각(도) — 새 방식(`_Deform.ts` BEND_DEG)과 같은 값. */
const BEND_DEG = 8;
+1 -1
View File
@@ -19,7 +19,7 @@ import type {
CorridorKind,
CorridorRibbon,
CorridorStructure,
} from "./B05_Profile_UI_Corridor_Build";
} from "./logic/B05_Profile_Corridor_Build";
/**
* 종류별 색 — 지형은 주황~황~녹 고도 램프라 그 대역을 피한다.
@@ -9,7 +9,7 @@
import type { RoutePoint } from "./B05_Profile_Api_Fetch";
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import { buildCorridor, type CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build";
import { buildCorridor, type CorridorBuildResult } from "./logic/B05_Profile_Corridor_Build";
export interface CorridorWorkerRequest {
id: number;
@@ -9,8 +9,8 @@
import { calcOnServer } from "../A00_Common/design/design_calc_sites";
import type { RoutePoint } from "./B05_Profile_Api_Fetch";
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import { buildCorridor, type CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build";
import { deserialize, type CorridorEnvelope } from "./B05_Profile_UI_Corridor_Envelope";
import { buildCorridor, type CorridorBuildResult } from "./logic/B05_Profile_Corridor_Build";
import { deserialize, type CorridorEnvelope } from "./logic/B05_Profile_Corridor_Envelope";
import type {
CorridorWorkerRequest,
CorridorWorkerResponse,
+1 -1
View File
@@ -17,7 +17,7 @@ import {
} from "./B05_Profile_UI_Markers";
import { createCameraRig, type ProjectionKind } from "./B05_Profile_UI_Viewer_Camera";
import { bindMarkerPointerControls } from "./B05_Profile_UI_Viewer_Marker_Input";
import type { CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build";
import type { CorridorBuildResult } from "./logic/B05_Profile_Corridor_Build";
import { createViewerCorridor, disposeObject } from "./B05_Profile_UI_Viewer_Corridor";
import {
bindStructurePick,
@@ -10,7 +10,7 @@
import * as THREE from "three";
import type { ModelBounds } from "./B05_Profile_UI_Markers";
import type { CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build";
import type { CorridorBuildResult } from "./logic/B05_Profile_Corridor_Build";
import { createCorridorGroup } from "./B05_Profile_UI_Corridor_Mesh";
import { setCorridorBuildSummary } from "./B05_Profile_UI_Viewer_Debug";
import type { TerrainHeightIndex } from "./B05_Profile_UI_Corridor_Terrain";
+1 -1
View File
@@ -7,7 +7,7 @@
* 요약 형태만 있으므로 화면 동작에는 영향이 없다.
* ========================================================================== */
import type { CorridorBuildResult } from "./B05_Profile_UI_Corridor_Build";
import type { CorridorBuildResult } from "./logic/B05_Profile_Corridor_Build";
/**
* 격자 재배치·투영선이 리본을 흔들었는지 화면 밖에서 수치로 확인한다(2026-08-26).
+2 -2
View File
@@ -3,7 +3,7 @@
갈래 지도(앞머리 → 하는 일):
- `UI_RouteEdit_*` 노선 편집(노드 · 곡선 · 측점 틀 · 등고선 띠) · `Api_Replan` 그 서버 요청
- `UI_Corridor_*` 3D 길 모형 · `UI_Viewer*` 3D 화면
- `UI_Corridor_*` 3D 길 모형 · `logic/Corridor_*` 그 계산 · `UI_Viewer*` 3D 화면
- `UI_Profile_*` 종단도(계획선 · 끌기 · 표 · 유토곡선) · `UI_Structures_*` · `Structures_*.py` 구조물
- `UI_Drainage_*` 배수유역 칸 · 관 · 시설 · `UI_Page_*` · `UI_Panel_*` 페이지 틀 · 좌측 칸 · `Api_*` 서버 요청
- `Engine_Grade*` 종단 계획선 · `Engine_Sections*` 측점 · 종횡단 생성 · `Engine_RouteInitial*` 노선 추천 · `Engine_AsPlanned` 노선 그대로 · `Router_*` API
@@ -19,7 +19,7 @@
서버 Node 묶음:
- 입구 `B05_Profile_Corridor_Node.ts`(package.json `build:corridor`) · 끌어감 = `UI_Corridor_*`(Build · Envelope · Frames · Station · Structures) · B06 `UI_Cross_*` 구조물(화면 · 세션 안 끔 · `test_472_3_calc_registry.py`)
- 입구 `B05_Profile_Corridor_Node.ts`(package.json `build:corridor`) · 끌어감 = `logic/Corridor_*`(Build · Envelope · Station · Structures) · `logic/UI_Corridor_Frames` · B06 `UI_Cross_*` 구조물(화면 · 세션 안 끔 · `test_472_3_calc_registry.py`)
- `build:b07-extent` · `build:b07-note` 가 `Api_Structures` · `Api_Pipes_Draft` · `UI_Structures_Balloon` · `UI_Structures_Define` 를 끌어감
- 묶음이 끄는 TS 를 고치면 그 build 다시 지어 시험 · 그 파일 모듈 맨 위에 DOM · window · sessionStorage 금지
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Build.ts
* B05_Profile_Corridor_Build.ts
* 계획노선 코리도(3D 예상형상) **순수 기하 빌더** — Three.js 의존 없음.
*
* 입력: 종횡단 상세(SectionDetailResponse)의 측점별 설계선(design_line)과
@@ -12,8 +12,8 @@
* 프레임을 삽입하고 단면을 파라메트릭 보간해 곡선 구간이 각지지 않게 한다.
* ========================================================================== */
import type { RoutePoint } from "./B05_Profile_Api_Fetch";
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import type { RoutePoint } from "../B05_Profile_Api_Fetch";
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import {
classifyStation,
mixedGround,
@@ -26,9 +26,9 @@ import {
type OffsetPoint,
type StationPieces,
type XY,
} from "./B05_Profile_UI_Corridor_Station";
} from "./B05_Profile_Corridor_Station";
export type { CorridorKind, CorridorSide } from "./B05_Profile_UI_Corridor_Station";
export type { CorridorKind, CorridorSide } from "./B05_Profile_Corridor_Station";
import {
bracketControls,
buildPieceControls,
@@ -38,21 +38,21 @@ import {
lerpPoints,
slerpLeft,
type PieceControl,
} from "./logic/B05_Profile_UI_Corridor_Frames";
import { buildCorridorStructures, type RouteFrame } from "./B05_Profile_UI_Corridor_Structures";
export type { CorridorStructure, StructureFrame } from "./B05_Profile_UI_Corridor_Structures";
} from "./B05_Profile_UI_Corridor_Frames";
import { buildCorridorStructures, type RouteFrame } from "./B05_Profile_Corridor_Structures";
export type { CorridorStructure, StructureFrame } from "./B05_Profile_Corridor_Structures";
import type {
CorridorBuildResult,
CorridorCap,
CorridorRibbon,
} from "./logic/B05_Profile_UI_Corridor_Build_Types";
} from "./B05_Profile_UI_Corridor_Build_Types";
// 결과 자료형은 `_Build_Types` 에 있다(2026-09-02 분리) — 호출부 경로 유지를 위해 재수출.
export type {
CorridorBuildResult,
CorridorCap,
CorridorRibbon,
} from "./logic/B05_Profile_UI_Corridor_Build_Types";
import { structureSilhouettes } from "./B05_Profile_UI_Corridor_Station_Structure";
} from "./B05_Profile_UI_Corridor_Build_Types";
import { structureSilhouettes } from "./B05_Profile_Corridor_Station_Structure";
/** 종방향 세분 간격(m) — 곡선 각짐 방지(2026-08-23 사용자: 노선 폴리라인 따라 세분).
* 평면 궤적을 스플라인으로 잇게 되어(2026-08-23) 0.1m까지 쪼갤 이유가 없어졌다 —
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Envelope.ts
* B05_Profile_Corridor_Envelope.ts
* 코리도 저장본 형식 — 버전·해시·직렬화 한 벌. **브라우저와 서버가 같은 것을 쓴다.**
*
* 서버(전처리 체인 끝)가 같은 빌더로 코리도를 미리 만들어 저장하므로(2026-09-04 사용자
@@ -10,13 +10,10 @@
* 원래 `_UI_Corridor.ts` 안에 있던 것을 그대로 옮겼다(2026-09-04 분리, 내용 불변).
* ========================================================================== */
import type { SectionDetailResponse } from "../B06_Section/B06_Section_Api_Fetch";
import type { RoutePoint } from "./B05_Profile_Api_Fetch";
import type {
CorridorBuildResult,
CorridorRibbon,
} from "./logic/B05_Profile_UI_Corridor_Build_Types";
import { structureHashParts } from "./B05_Profile_UI_Corridor_Structures";
import type { SectionDetailResponse } from "../../B06_Section/B06_Section_Api_Fetch";
import type { RoutePoint } from "../B05_Profile_Api_Fetch";
import type { CorridorBuildResult, CorridorRibbon } from "./B05_Profile_UI_Corridor_Build_Types";
import { structureHashParts } from "./B05_Profile_UI_Corridor_Structures_Hash";
/**
* 저장본 **형식(스키마)** 버전 — 담는 필드가 바뀔 때만 올린다.
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Station.ts
* B05_Profile_Corridor_Station.ts
* 코리도 측점 분류 · 행 지반 트림 유틸 (Build에서 분리 — 700줄 제한).
*
* classifyStation: 측점 하나의 design_line을 종류별(차도/노견/측구/절·성토 비탈)
@@ -9,8 +9,8 @@
* (2026-08-23 사용자 지시)의 핵심.
* ========================================================================== */
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import { structureSilhouettes } from "./B05_Profile_UI_Corridor_Station_Structure";
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import { structureSilhouettes } from "./B05_Profile_Corridor_Station_Structure";
export type CorridorKind = "carriageway" | "shoulder" | "ditch" | "cut" | "fill";
export type CorridorSide = "left" | "right" | "center";
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Station_Structure.ts
* B05_Profile_Corridor_Station_Structure.ts
* BOX암거·세월교 측점의 **비탈 실루엣**(성토·절토 한 줄)과 종방향 점유 구간.
* `_Corridor_Station.ts`가 배수관 세트에 쓰던 규칙을 두 구조물에도 그대로 태운다
* (2026-08-25 사용자: 3D에 성토선 반영이 안 돼 탑뷰에서 구조물이 안 보인다).
@@ -12,16 +12,16 @@
* 좌표 규약: +offset = 좌측. 점 배열은 항상 **도로측 → 바깥** 순서다.
* ========================================================================== */
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import type { OffsetPoint } from "./B05_Profile_UI_Corridor_Station";
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import type { OffsetPoint } from "./B05_Profile_Corridor_Station";
import {
basinSpanOf,
boxLayoutOf,
culvertLayoutOf,
fordLayoutOf,
wallSpanOf,
} from "./B05_Profile_UI_Corridor_Structures";
import { groundInterpolator } from "../B06_Section/logic/B06_Section_UI_Cross_Culvert_Solve";
} from "./B05_Profile_Corridor_Structures";
import { groundInterpolator } from "../../B06_Section/logic/B06_Section_UI_Cross_Culvert_Solve";
/** 한 측의 구조물 실루엣 — 비탈 조각을 이걸로 갈아 끼운다. */
export interface StructureSilhouette {
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Structures.ts
* B05_Profile_Corridor_Structures.ts
* 배수관 세트(배관·기슭막이·집수정) **3D 예상형상 솔리드** 계산 — 순수 기하,
* Three.js 무의존(2026-08-23 사용자 지시: 3D가 B06 횡단을 그대로 따르게).
*
@@ -20,41 +20,44 @@
* 폴리곤을 갈아 끼워(`polygons`) 측점 사이를 Catmull-Rom으로 잇는다. 벽은 여전히 하나다.
* ========================================================================== */
import { structureHashParts, wallSweepAt } from "./logic/B05_Profile_UI_Corridor_Structures_Hash";
import type { CrossSection, CulvertSideSpec } from "../B06_Section/B06_Section_Api_Fetch";
import { computeCulvertLayout } from "../B06_Section/B06_Section_UI_Cross_Culvert";
import { structureHashParts, wallSweepAt } from "./B05_Profile_UI_Corridor_Structures_Hash";
import type { CrossSection, CulvertSideSpec } from "../../B06_Section/B06_Section_Api_Fetch";
import { computeCulvertLayout } from "../../B06_Section/B06_Section_UI_Cross_Culvert";
import {
culvertOwnerFor,
ownWallsDrawAt,
restrictToSide,
tierSpanOf,
} from "../B06_Section/B06_Section_UI_Cross_Culvert_Wire";
import { pipeWallThicknessM } from "../B06_Section/logic/B06_Section_UI_Cross_Culvert_Const";
import type { CulvertLayout } from "../B06_Section/B06_Section_UI_Cross_Culvert";
import { computeFordLayout, fordAdjustOf } from "../B06_Section/B06_Section_UI_Cross_Ford";
import type { FordLayout } from "../B06_Section/B06_Section_UI_Cross_Ford";
} from "../../B06_Section/B06_Section_UI_Cross_Culvert_Wire";
import { pipeWallThicknessM } from "../../B06_Section/logic/B06_Section_UI_Cross_Culvert_Const";
import type { CulvertLayout } from "../../B06_Section/B06_Section_UI_Cross_Culvert";
import { computeFordLayout, fordAdjustOf } from "../../B06_Section/B06_Section_UI_Cross_Ford";
import type { FordLayout } from "../../B06_Section/B06_Section_UI_Cross_Ford";
import {
boreBandAt,
boreRingChainages,
boxSolids,
splitByBand,
} from "./B05_Profile_UI_Corridor_Structures_Box";
import type { SectionPolygon } from "./B05_Profile_UI_Corridor_Structures_Box";
import { computeBoxLayout, DEFAULT_BOX_SIDE_ADJUST } from "../B06_Section/B06_Section_UI_Cross_Box";
import type { BoxAdjust, BoxLayout } from "../B06_Section/B06_Section_UI_Cross_Box";
import { buildWingSolids } from "./logic/B05_Profile_UI_Corridor_Structures_Wing";
} from "./B05_Profile_Corridor_Structures_Box";
import type { SectionPolygon } from "./B05_Profile_Corridor_Structures_Box";
import {
computeBoxLayout,
DEFAULT_BOX_SIDE_ADJUST,
} from "../../B06_Section/B06_Section_UI_Cross_Box";
import type { BoxAdjust, BoxLayout } from "../../B06_Section/B06_Section_UI_Cross_Box";
import { buildWingSolids } from "./B05_Profile_UI_Corridor_Structures_Wing";
import {
buildWallPath,
detachedControlsOf,
polygonAt,
storedAdjusts,
type WallPath,
} from "./B05_Profile_UI_Corridor_Structures_Path";
import { computeRevetmentLayout } from "../B06_Section/B06_Section_UI_Cross_Revetment";
import { withoutGuardedFill } from "../B06_Section/B06_Section_UI_Cross_Body_Guard";
import { chuteBands, fordPavementChute } from "./B05_Profile_UI_Corridor_Structures_Chute";
import { isChuteSegment } from "../B06_Section/B06_Section_UI_Cross_Wall_Hatch";
import { builds, culvertBody, ownsBody } from "./logic/B05_Profile_UI_Corridor_Structures_Pick";
} from "./B05_Profile_Corridor_Structures_Path";
import { computeRevetmentLayout } from "../../B06_Section/B06_Section_UI_Cross_Revetment";
import { withoutGuardedFill } from "../../B06_Section/B06_Section_UI_Cross_Body_Guard";
import { chuteBands, fordPavementChute } from "./B05_Profile_Corridor_Structures_Chute";
import { isChuteSegment } from "../../B06_Section/B06_Section_UI_Cross_Wall_Hatch";
import { builds, culvertBody, ownsBody } from "./B05_Profile_UI_Corridor_Structures_Pick";
/** 스윕 프레임 하나 — 노선 위 한 지점의 중심 XY·좌향 단위벡터와 종단 표고 오프셋. */
export interface StructureFrame {
@@ -693,6 +696,3 @@ export function buildCorridorStructures(
}
return solids;
}
// 해시 요약은 `_Structures_Hash.ts` 에 있다(2026-09-02 분리) — 호출부 경로 유지를 위해 재수출.
export { structureHashParts } from "./logic/B05_Profile_UI_Corridor_Structures_Hash";
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Structures_Box.ts
* B05_Profile_Corridor_Structures_Box.ts
* BOX암거 3D 솔리드와 **관통 보어(구멍)** 계산 — 구조물 본체
* (`_UI_Corridor_Structures.ts`)에서 700줄 제한으로 분리했다(2026-08-25).
*
@@ -11,12 +11,12 @@
* 링 토폴로지가 항상 같아 스티칭이 단순하고, 눌린 구간은 면적 0이라 겹침이 없다.
* ========================================================================== */
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import { computeBoxLayout } from "../B06_Section/B06_Section_UI_Cross_Box";
import type { BoxAdjust } from "../B06_Section/B06_Section_UI_Cross_Box";
import type { CorridorStructure, StructureFrame } from "./B05_Profile_UI_Corridor_Structures";
import { buildWingSolids } from "./logic/B05_Profile_UI_Corridor_Structures_Wing";
import { chuteBands } from "./B05_Profile_UI_Corridor_Structures_Chute";
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import { computeBoxLayout } from "../../B06_Section/B06_Section_UI_Cross_Box";
import type { BoxAdjust } from "../../B06_Section/B06_Section_UI_Cross_Box";
import type { CorridorStructure, StructureFrame } from "./B05_Profile_Corridor_Structures";
import { buildWingSolids } from "./B05_Profile_UI_Corridor_Structures_Wing";
import { chuteBands } from "./B05_Profile_Corridor_Structures_Chute";
/** 단면 폴리곤 한 장 — [offset, elevation] 목록. */
export type SectionPolygon = Array<[number, number]>;
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Structures_Chute.ts
* B05_Profile_Corridor_Structures_Chute.ts
* 3D **도수로 · 돌붙임 띠** 단면(계획서 135-3) — 순수 기하, Three.js 무의존.
*
* · 단면 = B06 횡단 띠와 같은 계산(`chuteBandOutline`) — 유출 성토 조각(사면선)을 사면 안쪽으로
@@ -8,14 +8,14 @@
* 물넘이 포장 = 포장 폭. 스윕은 `_Structures.ts` 가 벽과 같은 규칙으로 한다.
* ========================================================================== */
import type { ChuteSpec, CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import type { OffsetPoint } from "../B06_Section/B06_Section_UI_Cross_Culvert_Types";
import type { ChuteSpec, CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import type { OffsetPoint } from "../../B06_Section/B06_Section_UI_Cross_Culvert_Types";
import {
chuteBandOutline,
chuteRun,
groundLine,
} from "../B06_Section/B06_Section_UI_Cross_Wall_Hatch";
import { outletFillLine } from "../B06_Section/B06_Section_UI_Cross_Ford_Pavement";
} from "../../B06_Section/B06_Section_UI_Cross_Wall_Hatch";
import { outletFillLine } from "../../B06_Section/B06_Section_UI_Cross_Ford_Pavement";
/** 성토 조각 하나 — B06 오버레이가 띠를 그리는 선(절토 조각은 뺀다). */
interface FillSegment {
@@ -1,5 +1,5 @@
/* =============================================================================
* B05_Profile_UI_Corridor_Structures_Path.ts
* B05_Profile_Corridor_Structures_Path.ts
* 기슭막이 **벽 경로선** — 연동을 푼 측점이 있을 때 벽이 노선과 평행하지 않고 자기
* 경로를 따라가도록, 측점별 단면 폴리곤을 링마다 보간한다(2026-08-30 사용자 확정:
* "연동은 분리가 아니다 — 하나의 기슭막이가 스플라인 형태의 경로를 따라간다").
@@ -10,17 +10,17 @@
* 소유 측점 폴리곤 하나로 고정(종전 동작)된다.
* ========================================================================== */
import type { CrossSection } from "../B06_Section/B06_Section_Api_Fetch";
import type { CulvertLayout } from "../B06_Section/B06_Section_UI_Cross_Culvert";
import { computeCulvertLayout } from "../B06_Section/B06_Section_UI_Cross_Culvert";
import { bodyAbsolute } from "../B06_Section/B06_Section_UI_Cross_Body_Guard";
import type { WallAdjust } from "../B06_Section/B06_Section_UI_Cross_Culvert_Types";
import { ZERO_ADJUST } from "../B06_Section/B06_Section_UI_Cross_Culvert_Types";
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import type { CulvertLayout } from "../../B06_Section/B06_Section_UI_Cross_Culvert";
import { computeCulvertLayout } from "../../B06_Section/B06_Section_UI_Cross_Culvert";
import { bodyAbsolute } from "../../B06_Section/B06_Section_UI_Cross_Body_Guard";
import type { WallAdjust } from "../../B06_Section/B06_Section_UI_Cross_Culvert_Types";
import { ZERO_ADJUST } from "../../B06_Section/B06_Section_UI_Cross_Culvert_Types";
import {
culvertOwnerFor,
culvertReach,
restrictToSide,
} from "../B06_Section/B06_Section_UI_Cross_Culvert_Wire";
} from "../../B06_Section/B06_Section_UI_Cross_Culvert_Wire";
/** 단면 폴리곤 [offset, 표고][] — 코리도 솔리드가 쓰는 그 형식. */
export type SectionPolygon = Array<[number, number]>;
@@ -2,14 +2,14 @@
* B05_Profile_UI_Corridor_Build_Types.ts
* 코리도 빌더가 내는 **결과 자료형** — 리본·캡·빌드 결과.
*
* `B05_Profile_UI_Corridor_Build` 에서 떼어냈다(700줄 제한, 2026-09-02). 계산은 전혀
* `B05_Profile_Corridor_Build` 에서 떼어냈다(700줄 제한, 2026-09-02). 계산은 전혀
* 없고 모양과 그 뜻(주석)만 있다. 빌더가 그대로 다시 내보내므로 기존 import 경로
* (`... from "./B05_Profile_UI_Corridor_Build"`)는 전부 유효하다.
* (`... from "./B05_Profile_Corridor_Build"`)는 전부 유효하다.
* ========================================================================== */
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
import type { CorridorKind, CorridorSide } from "../B05_Profile_UI_Corridor_Station";
import type { CorridorStructure } from "../B05_Profile_UI_Corridor_Structures";
import type { CorridorKind, CorridorSide } from "./B05_Profile_Corridor_Station";
import type { CorridorStructure } from "./B05_Profile_Corridor_Structures";
export interface CorridorRibbon {
kind: CorridorKind;
@@ -10,7 +10,7 @@
* 테이퍼가 생긴다. 접속 길이 기준 = **인접 측점까지**(2026-08-24 사용자 확정).
* ========================================================================== */
import type { OffsetPoint, StationPieces, XY } from "../B05_Profile_UI_Corridor_Station";
import type { OffsetPoint, StationPieces, XY } from "./B05_Profile_Corridor_Station";
import type { RoutePoint } from "../B05_Profile_Api_Fetch";
/** 제어점 하나 — 그 누가거리에서 쓸 단면과 출처. */
@@ -4,7 +4,7 @@
*
* 지문 = 그 측점 그림 자료(형상 얹기 한 벌 `SHAPE_KEYS` · 카드 · 상세 창 · B07 · 3D 가 같은 목록) + 형상을
* 바꾸는 조작값 통째를 키 차례 고정 글로 — 손으로 고른 칸 목록(빠뜨린 칸 = 「고쳐도 3D 가 안 바뀜」)을 걷음.
* 원래 파일(`B05_Profile_UI_Corridor_Structures`)이 그대로 다시 내보내므로 기존 import 경로는 유효하다.
* 쓰는 곳 = `B05_Profile_Corridor_Structures` · `B05_Profile_Corridor_Envelope`.
* ========================================================================== */
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
@@ -2,7 +2,7 @@
* B05_Profile_UI_Corridor_Structures_Pick.ts
* 3D 몸체 고르기(322-1) — 그림 자료 열쇠(`culvert` · `box` · `ford` · `ford_pavement` · `revetment`)의 주인
* 종류가 구조물 표 3D 부품으로 그 몸체를 세우는가. 지금 처음값 = 지금 결과 그대로(표가 끈 것만 빠짐).
* 쓰는 곳 = `B05_Profile_UI_Corridor_Structures.buildCorridorStructures`.
* 쓰는 곳 = `B05_Profile_Corridor_Structures.buildCorridorStructures`.
* ========================================================================== */
import type { CrossSection } from "../../B06_Section/B06_Section_Api_Fetch";
@@ -17,8 +17,8 @@ import type {
CorridorStructure,
RouteFrame,
StructureFrame,
} from "../B05_Profile_UI_Corridor_Structures";
import type { SectionPolygon } from "../B05_Profile_UI_Corridor_Structures_Box";
} from "./B05_Profile_Corridor_Structures";
import type { SectionPolygon } from "./B05_Profile_Corridor_Structures_Box";
/** 날개벽이 붙는 구조물 한쪽 끝 — 좌·우 각각 하나. */
export interface WingAnchor {
@@ -7,7 +7,7 @@
* 옛 제안 ② 설계(변형 장에서 · buildTinDesign)는 `Old/` 에.
* ========================================================================== */
import type { CorridorStructure } from "../B05_Profile_UI_Corridor_Structures";
import type { CorridorStructure } from "./B05_Profile_Corridor_Structures";
import type { Pslg } from "./B05_Profile_UI_Corridor_Tin_Pslg";
/** 단면 행 걸음(m) — 측점 사이 보간 단면. */
@@ -39,7 +39,7 @@ const { loadTs } = makeLoader({
});
const B05 = (name) => path.join(ROOT, "B05_Profile", `${name}.ts`);
const { buildCorridor } = loadTs(B05("B05_Profile_UI_Corridor_Build"));
const { buildCorridor } = loadTs(B05("logic/B05_Profile_Corridor_Build"));
const { loftTerrain } = loadTs(B05("B05_Profile_UI_Corridor_Loft"));
const { pairProfiles } = loadTs(B05("B05_Profile_UI_Corridor_Loft_Profile"));
const { selfCrossings } = loadTs(B05("logic/B05_Profile_UI_Corridor_Loft_Toe"));
@@ -29,7 +29,7 @@ const { loadTs } = makeLoader({
const B05 = (f) => path.join(ROOT, "B05_Profile", `${f}.ts`);
const B06 = (f) => path.join(ROOT, "B06_Section", `${f}.ts`);
const { buildCorridorStructures } = loadTs(B05("B05_Profile_UI_Corridor_Structures"));
const { buildCorridorStructures } = loadTs(B05("logic/B05_Profile_Corridor_Structures"));
const { structureHashParts } = loadTs(B05("logic/B05_Profile_UI_Corridor_Structures_Hash"));
const { structureTopLoops } = loadTs(B05("logic/B05_Profile_UI_Corridor_Tin_Design"));
const { chuteBandOutline, isChuteSegment } = loadTs(B06("B06_Section_UI_Cross_Wall_Hatch"));
@@ -161,7 +161,7 @@ function check(name, section, expectedBands, expectedLength, strip) {
delete s.culvert.body;
s.culvert.hidden_pipe = false;
s.culvert.chute = CHUTE;
const { culvertLayoutOf } = loadTs(B05("B05_Profile_UI_Corridor_Structures"));
const { culvertLayoutOf } = loadTs(B05("logic/B05_Profile_Corridor_Structures"));
const layout = culvertLayoutOf(s);
const bands = (layout?.outletFill.segments ?? [])
.filter(isChuteSegment) // 묻힌 끝 3도 절토 조각도(152-3)
+1 -1
View File
@@ -32,7 +32,7 @@ const B06 = (f) => path.join(ROOT, "B06_Section", `${f}.ts`);
const { computeStoredLayouts } = loadTs(B06("B06_Section_Structure_Layouts"));
const { isChuteSegment, chuteBandOutline } = loadTs(B06("B06_Section_UI_Cross_Wall_Hatch"));
const { chuteBands } = loadTs(
path.join(ROOT, "B05_Profile", "B05_Profile_UI_Corridor_Structures_Chute.ts"),
path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Corridor_Structures_Chute.ts"),
);
const fixture = (name) =>
JSON.parse(fs.readFileSync(path.join(__dirname, "fixtures", name), "utf8")).cross_sections;
@@ -37,7 +37,7 @@ const { loadTs } = makeLoader({
});
const B05 = (name) => path.join(ROOT, "B05_Profile", `${name}.ts`);
const { buildCorridor } = loadTs(B05("B05_Profile_UI_Corridor_Build"));
const { buildCorridor } = loadTs(B05("logic/B05_Profile_Corridor_Build"));
const { loftTerrain } = loadTs(B05("B05_Profile_UI_Corridor_Loft"));
const { TerrainBandSplit } = loadTs(B05("B05_Profile_UI_Corridor_Split"));
const { TerrainHeightIndex } = loadTs(B05("B05_Profile_UI_Corridor_Terrain"));
+1 -1
View File
@@ -37,7 +37,7 @@ const { loadTs } = makeLoader({
});
const B05 = (name) => path.join(ROOT, "B05_Profile", `${name}.ts`);
const { buildCorridor } = loadTs(B05("B05_Profile_UI_Corridor_Build"));
const { buildCorridor } = loadTs(B05("logic/B05_Profile_Corridor_Build"));
const { loftTerrain } = loadTs(B05("B05_Profile_UI_Corridor_Loft"));
const { TerrainBandSplit } = loadTs(B05("B05_Profile_UI_Corridor_Split"));
const { TerrainHeightIndex } = loadTs(B05("B05_Profile_UI_Corridor_Terrain"));
+1 -1
View File
@@ -211,7 +211,7 @@ const {
} = loadTs(B05("B05_Profile_Api_Structures"));
const { loadSectionDetail } = loadTs(B06("B06_Section_Section_Store"));
const { forgetDraftStations } = loadTs(B06("B06_Section_Section_Drafts"));
const { buildCorridorStructures } = loadTs(B05("B05_Profile_UI_Corridor_Structures"));
const { buildCorridorStructures } = loadTs(B05("logic/B05_Profile_Corridor_Structures"));
const { computeRevetmentLayout } = loadTs(B06("B06_Section_UI_Cross_Revetment"));
const { buildStructureLane } = loadTs(B05("B05_Profile_UI_Structures_Marks"));
const { pickGroups } = loadTs(B05("B05_Profile_UI_Structures_Panel_Types"));
@@ -29,7 +29,7 @@ const { loadTs } = makeLoader({
});
const { buildCorridorStructures } = loadTs(
path.join(ROOT, "B05_Profile", "B05_Profile_UI_Corridor_Structures.ts"),
path.join(ROOT, "B05_Profile", "logic", "B05_Profile_Corridor_Structures.ts"),
);
const fixture = JSON.parse(
fs.readFileSync(path.join(__dirname, "fixtures", "b06_73_4_body_guard_sections.json"), "utf8"),
@@ -22,7 +22,7 @@ const { loadTs } = makeLoader({
});
const B05 = (name) => path.join(ROOT, "B05_Profile", `${name}.ts`);
const { buildCorridor } = loadTs(B05("B05_Profile_UI_Corridor_Build"));
const { buildCorridor } = loadTs(B05("logic/B05_Profile_Corridor_Build"));
const { handleCorridorRequest, corridorTransfers } = loadTs(B05("B05_Profile_UI_Corridor_Worker"));
const { buildCorridorOffThread } = loadTs(B05("B05_Profile_UI_Corridor_Worker_Client"));
+4 -3
View File
@@ -1,7 +1,8 @@
/* 472-3 헬퍼 — TS import 도달 집합(472-0 g472/graph.mjs 꼴 · 읽기만).
* node helper_472_3_graph.mjs <저장소 뿌리> <입구.ts> [<입구.ts> …]
* 입구마다 도달 파일(뿌리 상대 · `/`)을 JSON 한 벌로 표준출력 — 정적 import · export from · 동적
* import() · new URL(…, import.meta.url)(워커) · `import type` · `export type` 은 뺌(지워짐). */
* import() · new URL(…, import.meta.url)(워커) · `import type` · `export type` 은 뺌(지워짐) · 정적 import ·
* export 는 줄 머리만(주석 속 「import」 낱말 안 셈). */
import fs from "node:fs";
import path from "node:path";
@@ -24,13 +25,13 @@ function resolve(from, spec) {
return exists(base.replace(/\.js$/, ""));
}
const re =
/(?:import|export)\s+(?:type\s+)?(?:[^;"'`]*?\sfrom\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)|new URL\(\s*["']([^"']+)["']\s*,\s*import\.meta\.url/g;
/^\s*(?:import|export)\s+(?:type\s+)?(?:[^;"'`]*?\sfrom\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)|new URL\(\s*["']([^"']+)["']\s*,\s*import\.meta\.url/gm;
function deps(file) {
if (!/\.(ts|mts)$/.test(file)) return [];
const src = fs.readFileSync(file, "utf8");
const out = [];
for (const m of src.matchAll(re)) {
if (/^(?:import|export)\s+type\s/.test(m[0])) continue;
if (/^\s*(?:import|export)\s+type\s/.test(m[0])) continue;
const target = resolve(file, m[1] || m[2] || m[3]);
if (target) out.push(target);
}
@@ -45,8 +45,8 @@ const { loadTs } = makeLoader({
rewrite: (js) => js.replace(/import\.meta\.url/g, '"file:///x.js"'),
});
const B05 = (name) => path.join(ROOT, "B05_Profile", `${name}.ts`);
const { buildCorridor } = loadTs(B05("B05_Profile_UI_Corridor_Build"));
const { serialize, corridorHash } = loadTs(B05("B05_Profile_UI_Corridor_Envelope"));
const { buildCorridor } = loadTs(B05("logic/B05_Profile_Corridor_Build"));
const { serialize, corridorHash } = loadTs(B05("logic/B05_Profile_Corridor_Envelope"));
const corridor = loadTs(B05("B05_Profile_UI_Corridor"));
const HALF = 3;
+1 -1
View File
@@ -57,7 +57,7 @@ def test_성토만인_측점은_그대로(out: dict) -> None:
def test_거름_한_벌_배선() -> None:
culvert = _src("B06_Section/B06_Section_UI_Cross_Culvert.ts")
assert "layout.outletFill.segments.filter(isChuteSegment)," in culvert
corridor = _src("B05_Profile/B05_Profile_UI_Corridor_Structures.ts")
corridor = _src("B05_Profile/logic/B05_Profile_Corridor_Structures.ts")
flat = " ".join(corridor.split())
assert "chuteBands( layout.outletFill.segments, section.culvert?.chute, isChuteSegment," in flat
hatch = _src("B06_Section/B06_Section_UI_Cross_Wall_Hatch.ts")
@@ -77,7 +77,7 @@ def test_카드_서버_3D_가_가드_한_벌을_쓴다():
files = {
"카드": ROOT / "B06_Section" / "B06_Section_UI_Cross_View.ts",
"서버 면적 · B07": ROOT / "B06_Section" / "B06_Section_Structure_Layouts.ts",
"3D": ROOT / "B05_Profile" / "B05_Profile_UI_Corridor_Structures.ts",
"3D": ROOT / "B05_Profile" / "logic" / "B05_Profile_Corridor_Structures.ts",
}
for where, path in files.items():
source = path.read_text(encoding="utf-8")
@@ -83,7 +83,7 @@ def test_포장층_노견까지_점선은_노면_위(ts):
def test_3D_노면을_파지_않고_옛_파임_그림을_걷음():
station = _read("B05_Profile", "B05_Profile_UI_Corridor_Station.ts")
station = _read("B05_Profile", "logic", "B05_Profile_Corridor_Station.ts")
assert "fordDeckElevationAt" not in station
pave = _read("B06_Section", "B06_Section_UI_Cross_Ford_Pavement.ts")
assert "hideFordPavedRoad" not in pave and "fordDeckElevationAt" not in pave
+2 -17
View File
@@ -64,16 +64,9 @@ pytestmark = pytest.mark.skipif(
reason="프론트엔드 의존성 미설치",
)
# 화면 · 세션 끌림(목록 1.3) — 472-2 2-B 가 걷음. 남은 줄 = 헬퍼 정규식 헛잡음
# (Corridor_Structures_Hash 머리 주석 속 「import」부터 잡아 아래 `import type` 을 값으로 셈) —
# 헬퍼를 고치면 빈 목록.
# 화면 · 세션 끌림(목록 1.3) — 472-2 2-B 가 걷음. 남은 줄 = `B06_Section_Route_Carry_Patch` →
# `common_util_svg`(측점 간격) → 화면 글(`ui_template_locale`) 값 import.
SESSION_PULLS = (
"B06_Section/B06_Section_Api_Fetch.ts",
"config/config_frontend.ts",
"ui_template/ui_template_elements.ts",
"ui_template/ui_template_elements_base.ts",
"ui_template/ui_template_elements_chart.ts",
"ui_template/ui_template_elements_styles.ts",
"ui_template/ui_template_locale.ts",
"ui_template/ui_template_locale_a.ts",
"ui_template/ui_template_locale_b1.ts",
@@ -87,14 +80,6 @@ SESSION_PULLS = (
)
# 기하가 logic 밖(구조물 그림 · 3D 빌더 파일 안) — 472-4 가 logic · common_util 로.
GEOMETRY_PULLS = (
"B05_Profile/B05_Profile_UI_Corridor_Build.ts",
"B05_Profile/B05_Profile_UI_Corridor_Envelope.ts",
"B05_Profile/B05_Profile_UI_Corridor_Station.ts",
"B05_Profile/B05_Profile_UI_Corridor_Station_Structure.ts",
"B05_Profile/B05_Profile_UI_Corridor_Structures.ts",
"B05_Profile/B05_Profile_UI_Corridor_Structures_Box.ts",
"B05_Profile/B05_Profile_UI_Corridor_Structures_Chute.ts",
"B05_Profile/B05_Profile_UI_Corridor_Structures_Path.ts",
"B06_Section/B06_Section_Structure_Layouts.ts",
"B06_Section/B06_Section_UI_Cross_Body_Guard.ts",
"B06_Section/B06_Section_UI_Cross_Box.ts",
@@ -15,10 +15,10 @@ PROJECT_ROOT = Path(__file__).resolve().parents[2]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
BUILD = (PROJECT_ROOT / "B05_Profile" / "B05_Profile_UI_Corridor_Build.ts").read_text(
BUILD = (PROJECT_ROOT / "B05_Profile" / "logic" / "B05_Profile_Corridor_Build.ts").read_text(
encoding="utf-8"
)
STATION = (PROJECT_ROOT / "B05_Profile" / "B05_Profile_UI_Corridor_Station.ts").read_text(
STATION = (PROJECT_ROOT / "B05_Profile" / "logic" / "B05_Profile_Corridor_Station.ts").read_text(
encoding="utf-8"
)
@@ -14,7 +14,7 @@ if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
# 2026-08-23 700줄 분리로 측점 분류부가 Station 파일로 이사했다.
BUILD_SOURCE = (PROJECT_ROOT / "B05_Profile" / "B05_Profile_UI_Corridor_Station.ts").read_text(
BUILD_SOURCE = (PROJECT_ROOT / "B05_Profile" / "logic" / "B05_Profile_Corridor_Station.ts").read_text(
encoding="utf-8"
)
+1 -1
View File
@@ -1,4 +1,4 @@
// 기슭막이 벽 경로선(B05_Profile_UI_Corridor_Structures_Path) 자체검증 — 로직 복제.
// 기슭막이 벽 경로선(logic/B05_Profile_Corridor_Structures_Path) 자체검증 — 로직 복제.
// 연동을 푼 측점이 있으면 벽이 노선과 평행이 아니라 자기 경로를 따라간다(2026-08-30).
// 실행: node tmp/tests/test_revet_wall_path.mjs
import assert from "node:assert/strict";