diff --git a/B06_Section/B06_Section_UI_Cross_Underdrain.ts b/B06_Section/B06_Section_UI_Cross_Underdrain.ts index 743c564ef..cb41c0033 100644 --- a/B06_Section/B06_Section_UI_Cross_Underdrain.ts +++ b/B06_Section/B06_Section_UI_Cross_Underdrain.ts @@ -5,6 +5,7 @@ * · 노면 = 설계 노면 — 서버 · TS 짝이 암거 경사로 지대 낮은 쪽 한 경사로 기울여 냄 · 측구 없음. * · 옵셋선 = 노면을 암거 높이만큼 아래로 같은 각도. * · 성토 쪽 = 옵셋선을 성토 사면과 만날 때까지 · 절토 쪽 = 절토 사면을 아래로 늘여 옵셋선과 만남. + * · 양측절토(낮은 쪽 늘인 노면 `tilt_reach`) = 늘인 노면이 원지반과 만나는 점에서 수직으로 끊음(356-1). * · 노면 · 양쪽 선 · 옵셋선이 둘러싼 안 = 돌 무늬(306-1) — 켜마다 반 칸 엇갈리고 이웃과 겹친 돌 · * 기울기를 번갈아 서로 교차 · 그림 전용(누름 안 받음 · CSS `.b06-chart__underdrain`). * 높이가 비면 그리지 않음(수치를 지어내지 않음). @@ -93,7 +94,12 @@ export function underdrainOutline( const span = left.offset_m - right.offset_m; if (!(Math.abs(span) > 1e-9)) return null; const grade = (left.elevation_m - right.elevation_m) / span; - const line = design.design_line ?? []; + // 양측절토(356-1) — 낮은 쪽 늘인 노면이 원지반과 만나는 점(tilt_reach)에서 끊음 · 너머 점 거름 → 꼬리가 수직으로 닫음 + const reach = design.tilt_reach; + const outward = reach?.side === "left" ? 1 : -1; + const line = (design.design_line ?? []).filter( + (p) => !reach || (p.offset_m - reach.offset_m) * outward <= 1e-6, + ); const leftPath = sidePath(left, 1, line, grade, heightM); const rightPath = sidePath(right, -1, line, grade, heightM); return [ diff --git a/B06_Section/B06_Section_UI_Cross_View.ts b/B06_Section/B06_Section_UI_Cross_View.ts index cda48dec7..9cea10b17 100644 --- a/B06_Section/B06_Section_UI_Cross_View.ts +++ b/B06_Section/B06_Section_UI_Cross_View.ts @@ -183,11 +183,8 @@ export function createCrossSectionCard( const card: CrossCardElement = document.createElement("article"); card.id = `cross-${section.station_id}`; card.className = `b06-cross-card${selected ? " b06-cross-card--selected" : ""}`; - card.tabIndex = 0; + // 초점 없음(356-2) — 마우스로 고른 뒤 키를 눌러도 초점 테두리 안 뜸 · ▲▼ 계획고는 창 듣개(219-1) card.addEventListener("click", () => onSelect(section.station_id)); - card.addEventListener("keydown", (event) => { - if (event.key === "Enter" || event.key === " ") onSelect(section.station_id); - }); // 선택 표시·면적 강조는 **DOM만 갈아 끼운다**. 카드를 새로 만들면 휠 줌·팬(viewBox)이 // 초기화돼 사용자가 맞춰 둔 배율이 날아간다(2026-08-02 사용자 지적). diff --git a/resources/tester/helper_288_underdrain.cjs b/resources/tester/helper_288_underdrain.cjs index 5a81ab179..eaf9c50ed 100644 --- a/resources/tester/helper_288_underdrain.cjs +++ b/resources/tester/helper_288_underdrain.cjs @@ -65,6 +65,17 @@ const design = { { offset_m: -7, elevation_m: 97.2 }, ], }; +// 356-1 양측절토 — 우(낮은 쪽) 노면 끝도 절토 → 노면을 늘여 원지반과 만난 점(tilt_reach) · 그 너머 원지반 오름 +const bothCut = { + ...design, + design_line: [ + ...design.design_line.slice(0, 3), + { offset_m: -4, elevation_m: 99.8 }, + { offset_m: -4.5, elevation_m: 99.775 }, + { offset_m: -6, elevation_m: 100.5 }, + ], + tilt_reach: { side: "right", offset_m: -4.5, elevation_m: 99.775 }, +}; const svg = new Node("g"); const group = draw.appendUnderdrainOverlay( svg, @@ -96,6 +107,7 @@ process.stdout.write( attached, sections: sections.map((s) => s.underdrain ?? null), outline: draw.underdrainOutline(design, 1), + bothCut: draw.underdrainOutline(bothCut, 1), noHeight: draw.underdrainOutline(design, null), drew: !!group, bodyId: body?.attrs["data-structure-id"] ?? null, diff --git a/resources/tester/test_288_underdrain_cross.py b/resources/tester/test_288_underdrain_cross.py index 51107f608..50c5526c8 100644 --- a/resources/tester/test_288_underdrain_cross.py +++ b/resources/tester/test_288_underdrain_cross.py @@ -131,6 +131,22 @@ def test_형상_옵셋선_성토_절토와_만남(ts): assert ts["drew"] is True and ts["stones"] > 0 +def test_양측절토_늘인_노면_원지반_교점에서_끊음(ts): + """356-1 — 낮은 쪽 노면 끝도 절토(tilt_reach) = reach 에서 수직으로 끊음 · 너머 원지반 따라가지 않음.""" + outline = [(p["offset"], p["elevation"]) for p in ts["bothCut"]] + expected = [ + (3, 100.15), + (-3, 99.85), + (-4, 99.8), + (-4.5, 99.775), # 늘인 노면 ∩ 원지반(tilt_reach) + (-4.5, 98.775), # reach 아래 옵셋선 + (1.846154, 99.092308), + ] + assert len(outline) == len(expected) + for got, want in zip(outline, expected): + assert got == pytest.approx(want, abs=1e-5) + + def test_횡단도_B07_이_맹암거를_그림(): view = (ROOT / "B06_Section" / "B06_Section_UI_Cross_View.ts").read_text(encoding="utf-8") assert ( diff --git a/resources/tester/test_356_b06_card_center.py b/resources/tester/test_356_b06_card_center.py new file mode 100644 index 000000000..4f7fd6684 --- /dev/null +++ b/resources/tester/test_356_b06_card_center.py @@ -0,0 +1,19 @@ +"""356 B06 횡단 카드 — 키 강조 · 중심점 좌우(요구 235-17 · 18). + +못박는 것 + - 356-2 카드 초점 없음 — 마우스로 고른 뒤 키를 눌러도 초점 테두리(다른 색) 안 뜸 · ▲▼ 계획고는 창 듣개. +""" + +from __future__ import annotations + +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +B06 = ROOT / "B06_Section" + + +def test_카드_초점_없음(): + view = (B06 / "B06_Section_UI_Cross_View.ts").read_text(encoding="utf-8") + assert "card.tabIndex" not in view + assert 'card.addEventListener("keydown"' not in view + assert 'card.addEventListener("click", () => onSelect(section.station_id));' in view