From e9908f397691c2bc5061d6c5e5e8f44633d0c3a4 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 17 Oct 2026 15:59:27 +0900 Subject: [PATCH] =?UTF-8?q?fix(B06=20=ED=9A=A1=EB=8B=A8):=20=EB=A9=88?= =?UTF-8?q?=EC=B6=A4=20=EC=9E=90=EB=A6=AC=EC=97=90=EC=84=9C=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=8C=20=EA=B1=B8=EC=9D=8C=20=EB=84=98=EC=96=B4=EA=B0=90=20?= =?UTF-8?q?=E2=80=94=20=EB=A9=88=EC=B6=A4=20=ED=8C=90=EC=A0=95=20=C2=B15?= =?UTF-8?q?=20mm=20=ED=95=9C=20=EC=9E=A3=EB=8C=80=20(370-4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - extendStop 「이미 멈춤 자리」 = |틈| ≤ 5 mm(옛 1e-4) — 0.001 m 반올림이 교차 앞에 떨어져도 같은 교차에 다시 안 섬 - 잣대 상수 ON_GROUND_M 하나 = extendStop · edgeOnGround(「절·성토 없음」) 같이 씀 - 시험: helper_370_2 「반올림이 교차 앞」 사례(2.736 → 2.836) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL --- B06_Section/logic/B06_Section_UI_Cross_Fit.ts | 7 +++++-- resources/tester/helper_370_2_toe_stop.cjs | 15 +++++++++++++++ resources/tester/test_370_2_toe_stop.py | 8 ++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/B06_Section/logic/B06_Section_UI_Cross_Fit.ts b/B06_Section/logic/B06_Section_UI_Cross_Fit.ts index d30b011af..5560101a3 100644 --- a/B06_Section/logic/B06_Section_UI_Cross_Fit.ts +++ b/B06_Section/logic/B06_Section_UI_Cross_Fit.ts @@ -72,6 +72,8 @@ export function toePoints( /** 멈춤 탐색 간격(m) — 사면 이동 걸음(0.1 m)보다 촘촘하게. */ const STOP_SCAN_M = 0.01; +/** 노견 끝 = 원지반 잣대(m) — 멈춤 자리(`extendStop`) · 「절·성토 없음」(`edgeOnGround`) 한 벌(370-4). */ +const ON_GROUND_M = 0.005; /** * 사면 이동 멈춤(370-2) — 그 쪽 노견 확장 `now` → `next` 사이에서 옮긴 노견 끝이 원지반과 딱 만나는 @@ -99,7 +101,8 @@ export function extendStop( return groundAt(o) - plane(o); }; let previous = gapAt(now); - if (Math.abs(previous) < 1e-4) return next; + // 이미 멈춤 자리(0.001 m 반올림이 교차 앞에 떨어져도) — 같은 교차를 다시 찾지 않고 넘어감(370-4) + if (Math.abs(previous) <= ON_GROUND_M) return next; const steps = Math.max(1, Math.ceil(Math.abs(next - now) / STOP_SCAN_M)); for (let i = 1; i <= steps; i += 1) { const a = now + ((next - now) * (i - 1)) / steps; @@ -121,7 +124,7 @@ export function edgeOnGround( const on = (side: "left" | "right") => !!groundAt && !!edges && - Math.abs(groundAt(edges[side].offset_m) - edges[side].elevation_m) <= 0.005; + Math.abs(groundAt(edges[side].offset_m) - edges[side].elevation_m) <= ON_GROUND_M; return { left: on("left"), right: on("right") }; } diff --git a/resources/tester/helper_370_2_toe_stop.cjs b/resources/tester/helper_370_2_toe_stop.cjs index c62046e96..2b121d995 100644 --- a/resources/tester/helper_370_2_toe_stop.cjs +++ b/resources/tester/helper_370_2_toe_stop.cjs @@ -225,6 +225,21 @@ out.stop = { ), leftNoGround: fit.extendStop([], base.road_edges, "left", 0, 0.1), }; +// 370-4 — 0.001 m 반올림이 교차 **앞**에 떨어진 멈춤(54+0 0.936 꼴) → 다음 걸음은 넘어감(같은 교차에 다시 안 섬) +{ + const [ga, gb] = crossing.map((e) => gapAt(base, e)); + const exact = crossing[0] + ((crossing[1] - crossing[0]) * ga) / (ga - gb); + let before = Math.floor(exact * 1000) / 1000; + if (before === exact) before -= 0.001; + const next = Math.round((before + 0.1) * 1000) / 1000; + out.before = { + exact, + before, + gapMm: Math.abs(gapAt(base, before)) * 1000, + next, + got: fit.extendStop(samples, designOf(before).road_edges, "right", before, next), + }; +} // ② 교차점 손잡이 — 쪽마다 원 · 늘 보임 · 키 toe:left|right · 고르면 ◀▶ 가 멈춤 자리로 보냄 const x = (o) => 300 - o * 20; diff --git a/resources/tester/test_370_2_toe_stop.py b/resources/tester/test_370_2_toe_stop.py index 42e9f4e94..fe501353e 100644 --- a/resources/tester/test_370_2_toe_stop.py +++ b/resources/tester/test_370_2_toe_stop.py @@ -52,6 +52,14 @@ def test_노견_끝이_원지반을_지나면_그_자리에_한_번_섬(out) -> assert stop["leftNoGround"] == 0.1 # 지반 없으면 그대로 +def test_반올림이_교차_앞이어도_다음_걸음은_넘어감(out) -> None: + """370-4 — 멈춤값(0.001 m 반올림)이 참 교차 앞이면 남은 틈 > 1e-4 · 그래도 ±5 mm 안 = 멈춤 자리.""" + got = out["before"] + assert got["before"] < got["exact"] # 교차 앞 + assert 0.1 < got["gapMm"] <= 5 # 옛 잣대(0.1 mm) 밖 · 새 잣대(5 mm) 안 + assert abs(got["got"] - got["next"]) < 1e-9 # 0.936 → 1.036 꼴(제자리 아님) + + def test_교차점_손잡이_쪽마다_늘_보임(out) -> None: toe = out["toe"] assert toe["count"] == len(toe["sides"]) == 2