From 24bc9480a5698697cde432d1b97dadf7d8772ab7 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Wed, 26 Aug 2026 18:10:50 +0900 Subject: [PATCH] =?UTF-8?q?fix(B05):=20=EC=84=B8=EC=9B=94=EA=B5=90=20?= =?UTF-8?q?=EB=82=A0=EA=B0=9C=EB=B2=BD=EC=9D=B4=20=EC=98=A4=EB=AF=80?= =?UTF-8?q?=EB=9D=BC=EB=93=A4=EB=8D=98=20=EA=B2=83=EC=9D=84=20=EB=B2=8C?= =?UTF-8?q?=EC=96=B4=EC=A7=80=EA=B2=8C=20=EC=A0=95=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 위에서 봤을 때 아령처럼 유입·유출부가 커져야 물을 받는다(사용자). 그런데 노선 프레임 경로에서 앞뒤 기준이 뒤집혀 세월교 날개가 오므라들었다. 뿌리는 frameAt(측점 + along × 반폭)으로 누가거리 기준으로 잡는데, 벌어지는 방향은 dir × along으로 측점 로컬 기준을 쓴다. 이 프레임의 dir은 누가거리가 줄어드는 쪽을 향해 둘이 반대였다 — 뿌리가 벌어짐 방향의 반대편에 앉는다. 실측: 149.73 날개가 (−3.65, 종 3.88) → (−4.48, 종 2.06)으로 종방향이 0에 가까워졌다. BOX암거는 뿌리·방향이 같은 기준이라 영향이 없었다. 부호를 가정하지 않는다. 측점 ± 반폭 두 자리를 다 뽑아 `along` 방향에 놓인 쪽을 고른다(`endFrameOf`) — 누가거리 부호와 진행 방향 부호가 반대인 노선에도 맞는다. `BUILD_VERSION` 34 → 35. 실측: 같은 측 두 날개의 종방향 간격이 뿌리 → 끝으로 커진다. 149.73 좌 10.89 → 14.19m, 우 8.74 → 10.92m. BOX 200.92는 2.40 → 5.22m로 정정 전과 동일(무변화). 파생물 회귀 없음 — 에이프런 4장(기준 직선 이탈 0.0000m), 성토끝 박스 4/4·4/4. Co-Authored-By: Claude Opus 5 (1M context) --- B05_Profile/B05_Profile_UI_Corridor.ts | 2 +- ...B05_Profile_UI_Corridor_Structures_Wing.ts | 37 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_Corridor.ts b/B05_Profile/B05_Profile_UI_Corridor.ts index f85530d0..43cc3bfd 100644 --- a/B05_Profile/B05_Profile_UI_Corridor.ts +++ b/B05_Profile/B05_Profile_UI_Corridor.ts @@ -84,7 +84,7 @@ function fnv1a(text: string): string { * (2026-08-23 사용자 보고: "원복이 안 된 것 같다가 갑자기 반영됨"). 판번호를 해시에 * 섞어 두면 배포와 동시에 저장본이 만료된다. */ -const BUILD_VERSION = 34; // 세월교 날개벽 노선 추종 + 바닥 에이프런(2026-08-26). +const BUILD_VERSION = 35; // 세월교 날개벽 벌어짐 방향 정정(2026-08-26). /** 종횡단 정본에서 코리도에 영향을 주는 입력만 요약해 해시 — 갱신 감지 기준. */ export function corridorHash(detail: SectionDetailResponse, routePoints: RoutePoint[]): string { diff --git a/B05_Profile/B05_Profile_UI_Corridor_Structures_Wing.ts b/B05_Profile/B05_Profile_UI_Corridor_Structures_Wing.ts index b51c7a20..84ee9c78 100644 --- a/B05_Profile/B05_Profile_UI_Corridor_Structures_Wing.ts +++ b/B05_Profile/B05_Profile_UI_Corridor_Structures_Wing.ts @@ -46,6 +46,35 @@ export interface WingAnchor { /** 날개 축 방향 분할 수 — 높이 체감을 담을 최소 해상도. */ const WING_STEPS = 4; +/** + * 측벽 끝단부 프레임 — 측점 ± 반폭 두 자리 중 **`along` 방향에 놓인 쪽**을 고른다. + * 누가거리 부호와 진행 방향 부호가 반대인 노선이 있어 부호를 가정하면 안 된다. + */ +function endFrameOf( + frame: StructureFrame, + endFrameAt: ((chainageM: number) => RouteFrame | null) | undefined, + chainageM: number, + halfSpanM: number, + along: number, +): RouteFrame | null { + if (!endFrameAt) return null; + const dirX = -frame.leftY; + const dirY = frame.leftX; + let best: RouteFrame | null = null; + let bestReach = 0; + for (const step of [halfSpanM, -halfSpanM]) { + const candidate = endFrameAt(chainageM + step); + if (!candidate) continue; + // 기준 측점에서 그 자리까지의 진행 방향 성분 — `along`과 부호가 같아야 한다. + const reach = ((candidate.cx - frame.cx) * dirX + (candidate.cy - frame.cy) * dirY) * along; + if (reach > bestReach) { + bestReach = reach; + best = candidate; + } + } + return best; +} + /** * 날개벽 4매(좌·우 × 전·후). `anchors`가 빈 배열이거나 제원이 꺼져 있으면 안 만든다. * @@ -79,7 +108,13 @@ export function buildWingSolids( const height1 = Math.max(wing.height_m ?? height0, 0.3); for (const along of [1, -1]) { // 뿌리를 낼 프레임 — 세월교는 측벽 끝단 자리의 노선 프레임, BOX는 기준 측점. - const end = endFrameAt?.(chainageM + along * halfSpanM) ?? null; + // + // 누가거리 부호와 `dir`(좌향을 90° 돌린 진행 방향) 부호가 같다는 보장이 없다. + // 실제로 이 프레임의 `dir`은 누가거리가 **줄어드는** 쪽을 향해, 그냥 + // `chainageM + along * halfSpanM`으로 잡으면 뿌리가 벌어짐 방향의 반대편에 + // 앉아 날개가 오므라든다(2026-08-26 사용자: "아령같이 커져야 물을 받는다"). + // 그래서 앞뒤 두 자리를 다 뽑아 **`along` 방향에 놓인 쪽**을 고른다. + const end = endFrameOf(frame, endFrameAt, chainageM, halfSpanM, along); const base = end ?? frame; // 노선 진행 방향 = 좌향 벡터를 90° 돌린 것. const dirX = -base.leftY;