fix(507-3 덧 MC): B07 계획평면도 MC 큰 글 (MC) · B05 종단 아래 표 측점 행 (MC) · B07 횡단 장 단추 (MC) — 요구 311-4
- 평면도 측점 글 = 5 배수만 → 종단 kind curve 측점도 큰 글 + 원 + (MC) - 종단 표 측점 행 · 고른 측점 값 열 = (MC) · 굵게 · 경고색 · 칸 폭 판정은 옛 글 그대로 - 횡단 장 단추 이름 뒤 (MC) · 긴 이름이라 두 열 가로지름 - test_507_3_mc_label 칸 넷 더함 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -294,6 +294,11 @@ export function renderProfile(ctx: ProfileRenderContext): void {
|
||||
),
|
||||
selectedStationId,
|
||||
stationDisplay,
|
||||
mcKeys: new Set(
|
||||
(longitudinal.stations ?? [])
|
||||
.filter((station) => station.kind === "curve")
|
||||
.map((station) => station.chainage_m.toFixed(3)),
|
||||
),
|
||||
onCurveRadiusChange: (curve, radius) =>
|
||||
ctx.applyEdits(setCurveRadius(store.edits(), curve, radius ?? 0)),
|
||||
// 값 열 계획고 직접 입력 → 규칙 측점과 동일한 station_offset 파이프라인.
|
||||
|
||||
@@ -43,6 +43,8 @@ export interface ProfileTableOptions {
|
||||
irregularStations?: IrregularStation[];
|
||||
/** 현재 선택된 측점 id. 규칙/비정규 측점 모두 그 측점의 값 열을 테이블에 겹쳐 보여준다. */
|
||||
selectedStationId?: string | null;
|
||||
/** MC(곡선 가운데) 측점 누가거리(`toFixed(3)` 열쇠) — 측점 행에 「 (MC)」 · 크게 · 굵게 · 경고색(507-3 덧). */
|
||||
mcKeys?: ReadonlySet<string>;
|
||||
/** 이어 공사 시작 기준 — 측점번호·누가거리 표시를 이만큼 더한다(내부 chainage는 0기준 유지). */
|
||||
stationDisplay?: { station: number; cumulative: number };
|
||||
onCurveRadiusChange: (curve: AlignmentCurve, radiusM: number | null) => void;
|
||||
@@ -55,6 +57,8 @@ interface StationRowSpec {
|
||||
unit: string;
|
||||
cell: (index: number) => string;
|
||||
modifier?: string;
|
||||
/** 측점 이름 행 — MC 열에 (MC) 강조. */
|
||||
station?: boolean;
|
||||
}
|
||||
|
||||
interface SegmentRowSpec {
|
||||
@@ -208,6 +212,7 @@ function buildStationRows(
|
||||
{
|
||||
label: "측점",
|
||||
unit: "측점번호+잔여거리",
|
||||
station: true,
|
||||
cell: (index) => displayStationLabel(stations[index].chainage_m, interval, display.station),
|
||||
},
|
||||
];
|
||||
@@ -458,6 +463,7 @@ function buildSelectedColumn(
|
||||
display: { station: number; cumulative: number },
|
||||
onAdjustStation?: (chainageM: number, deltaM: number) => void,
|
||||
isIrregular = false,
|
||||
mc = false,
|
||||
): HTMLElement {
|
||||
const plan = interpolateSample(alignment.samples, chainage, "elevation_m");
|
||||
const ground = interpolateSample(alignment.samples, chainage, "ground_elevation_m");
|
||||
@@ -487,7 +493,12 @@ function buildSelectedColumn(
|
||||
{ value: gradeCell((segment) => segment.grade_percent, 2), modifier: "grade" }, // 구배 S
|
||||
{ value: { text: plan !== null ? plan.toFixed(2) : "" }, modifier: "plan", plan: true }, // 계획고
|
||||
{ value: { text: ground !== null ? ground.toFixed(2) : "" }, modifier: "" }, // 지반고
|
||||
{ value: { text: displayStationLabel(chainage, interval, display.station) }, modifier: "" }, // 측점
|
||||
{
|
||||
value: {
|
||||
text: displayStationLabel(chainage, interval, display.station) + (mc ? " (MC)" : ""),
|
||||
},
|
||||
modifier: mc ? "mc" : "",
|
||||
}, // 측점
|
||||
{ value: { text: curve ? curve.l_m.toFixed(2) : "" }, modifier: "" }, // 곡선 L
|
||||
{ value: { text: curve ? curve.r_m.toFixed(1) : "" }, modifier: "" }, // 곡선 R
|
||||
];
|
||||
@@ -617,10 +628,13 @@ export function createProfileTable(options: ProfileTableOptions): HTMLElement {
|
||||
alignment.stations.forEach((_, stationIndex) => {
|
||||
// 구조물 측점 열은 기본값을 비운다 — 격자(빈 셀)만 남기고 값은 선택 오버레이가 맡는다.
|
||||
const structural = isStructural[stationIndex];
|
||||
// MC 열 = 측점 행에 「 (MC)」 · 굵게 · 경고색(507-3 덧) — 칸 폭 판정(`longest`)은 옛 글 그대로
|
||||
const mc =
|
||||
spec.station && options.mcKeys?.has(alignment.stations[stationIndex].chainage_m.toFixed(3));
|
||||
const cell = element(
|
||||
"span",
|
||||
`b05-profile-table__cell${structural ? " is-structure" : ""}`,
|
||||
structural ? "" : spec.cell(stationIndex),
|
||||
`b05-profile-table__cell${structural ? " is-structure" : ""}${mc ? " b06-station--mc" : ""}`,
|
||||
structural ? "" : spec.cell(stationIndex) + (mc ? " (MC)" : ""),
|
||||
);
|
||||
const rotated = stationThickness[stationIndex];
|
||||
if (rotated !== null) {
|
||||
@@ -649,6 +663,7 @@ export function createProfileTable(options: ProfileTableOptions): HTMLElement {
|
||||
// 선택된 측점(규칙·비정규 공용)을 **값 열 오버레이**로 강조한다.
|
||||
// 규칙 측점은 종점 이동을 반영한 `centers[index]`, 비정규 측점은 `x(chainage)`를 중심으로 쓴다.
|
||||
const selectedIrregular = selectedIrregularEntry;
|
||||
const mcAt = (chainageM: number): boolean => options.mcKeys?.has(chainageM.toFixed(3)) ?? false;
|
||||
const selectedRegularIndex = selectedStationRow
|
||||
? alignment.stations.indexOf(selectedStationRow)
|
||||
: -1;
|
||||
@@ -665,6 +680,7 @@ export function createProfileTable(options: ProfileTableOptions): HTMLElement {
|
||||
display,
|
||||
options.onAdjustStation,
|
||||
true,
|
||||
mcAt(selectedIrregular.chainage_m),
|
||||
),
|
||||
);
|
||||
} else if (selectedRegularIndex >= 0) {
|
||||
@@ -678,6 +694,7 @@ export function createProfileTable(options: ProfileTableOptions): HTMLElement {
|
||||
display,
|
||||
options.onAdjustStation,
|
||||
false,
|
||||
mcAt(alignment.stations[selectedRegularIndex].chainage_m),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -288,6 +288,12 @@
|
||||
color: rgb(37 99 235);
|
||||
}
|
||||
|
||||
/* MC 측점 이름(507-3 덧) — 굵게 · 경고색 */
|
||||
.b05-profile-table__irregular-col-cell.is-mc {
|
||||
color: var(--color-warning);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
/* 계획고(is-plan)는 오버레이에서 별도 강조 없이 다른 값과 동일한 스타일을 쓴다(작업 C-2). */
|
||||
|
||||
/* 값 열의 계획고 직접 입력 셀 — 열은 pointer-events:none이라 입력만 되살린다. */
|
||||
|
||||
@@ -221,6 +221,7 @@ def _drawing_list(project_root: Path, longitudinal_path: Path) -> list[DesignDra
|
||||
chainages = sheet["chainages"]
|
||||
first = station_by_chainage.get(chainages[0], {})
|
||||
station = station_no_label(float(first.get("chainage_m", chainages[0])), interval)
|
||||
station += mc_suffix(first)
|
||||
drawings.append(
|
||||
DesignDrawingItem(
|
||||
id=sheet["id"],
|
||||
|
||||
@@ -25,7 +25,11 @@ from B05_Profile.B05_Profile_Engine_Sections import (
|
||||
)
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures
|
||||
from B06_Section.B06_Section_Engine_Design import compute_cross_design, curve_widening_args
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import infer_station_interval, station_no_label
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
|
||||
infer_station_interval,
|
||||
mc_suffix,
|
||||
station_no_label,
|
||||
)
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_IpTable import clip_lines, ip_table_piece
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Plan import (
|
||||
_structure_label,
|
||||
@@ -502,6 +506,11 @@ def build_pieces(
|
||||
pieces["ip"], pieces["radius"] = curve_pieces(_load_design_curves(project_root), route, box)
|
||||
if "station" in wanted:
|
||||
items = []
|
||||
curve_at = {
|
||||
float(item["chainage_m"])
|
||||
for item in longitudinal.get("stations") or []
|
||||
if mc_suffix(item) and isinstance(item.get("chainage_m"), (int, float))
|
||||
}
|
||||
for chainage, x, y in stations:
|
||||
if not (start_m <= chainage <= end_m):
|
||||
continue
|
||||
@@ -509,6 +518,8 @@ def build_pieces(
|
||||
label = station_no_label(chainage, interval).replace("No.", "NO.")
|
||||
number_only = "+" not in label
|
||||
major = number_only and int(label[3:]) % 5 == 0
|
||||
if chainage in curve_at: # MC = 고칠 자리(507-3) — 5 배수가 아니어도 글 · 큰 글(major)
|
||||
label, major = label + " (MC)", True
|
||||
items.append(
|
||||
{
|
||||
"chainage_m": chainage,
|
||||
|
||||
@@ -178,7 +178,10 @@ export function buildDrawingSidePanel(
|
||||
}
|
||||
for (const drawing of items) {
|
||||
// 횡단면도는 장 단위(여러 측점)라 서버가 준 "N장 (구간)" 라벨을 그대로 쓴다.
|
||||
section.append(drawingButton(drawing, drawing.label));
|
||||
const button = drawingButton(drawing, drawing.label);
|
||||
// 이름 뒤 「 (MC)」(507-3 덧) — 한 칸에 안 들어가 두 열을 가로지름
|
||||
if (drawing.label.includes("(MC)")) button.dataset.mc = "true";
|
||||
section.append(button);
|
||||
}
|
||||
if (structure && items.length === 0) {
|
||||
const empty = document.createElement("p");
|
||||
|
||||
@@ -70,6 +70,11 @@
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
/* MC 장 단추(507-3 덧) — 이름이 길어 한 줄 전체 */
|
||||
.b07-drawing-group[data-kind="cross"] .b07-drawing-button[data-mc="true"] {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.b07-drawing-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -87,3 +87,39 @@ def test_b05_b06_screen_mc_emphasis() -> None:
|
||||
assert 'themeColor("--color-warning"' in ticks
|
||||
swap = _src("B06_Section/logic/B06_Section_Station_Swap.ts")
|
||||
assert 'formatStation(station.chainageM) + (kind === "curve" ? " (MC)" : "")' in swap
|
||||
|
||||
|
||||
def test_b07_plan_station_mc_label() -> None:
|
||||
"""계획평면도 측점 글 = 5 배수만이었음 → MC 도 큰 글(major) + (MC)."""
|
||||
plan = _src("B07_DesignDetail/B07_DesignDetail_Router_Support_Plan.py")
|
||||
assert 'label, major = label + " (MC)", True' in plan
|
||||
assert "if mc_suffix(item)" in plan # 종단 kind curve 측점만
|
||||
|
||||
|
||||
def test_b07_sheet_button_mc() -> None:
|
||||
"""B07 횡단 장 단추 「3장 (No.29+19.0 (MC))」 — 그 장 첫 측점이 MC 일 때."""
|
||||
support = _src("B07_DesignDetail/B07_DesignDetail_Router_Support.py")
|
||||
assert "station += mc_suffix(first)" in support
|
||||
assert "label=f\"{sheet['number']}장 ({station})\"" in support
|
||||
|
||||
|
||||
def test_b05_profile_table_station_mc() -> None:
|
||||
table = _src("B05_Profile/B05_Profile_UI_Profile_Table.ts")
|
||||
# 칸 글 · 굵게 · 경고색 = B06 공용 규칙 · 칸 폭 판정(`longest`)은 (MC) 없는 글 그대로
|
||||
assert 'spec.cell(stationIndex) + (mc ? " (MC)" : "")' in table
|
||||
assert '${mc ? " b06-station--mc" : ""}' in table
|
||||
assert 'display.station) + (mc ? " (MC)" : "")' in table # 고른 측점 값 열
|
||||
render = _src("B05_Profile/B05_Profile_UI_Profile_Render.ts")
|
||||
assert 'station.kind === "curve"' in render
|
||||
css = _src("B05_Profile/B05_Profile_UI_Style_Table.css")
|
||||
body = css[css.index("__irregular-col-cell.is-mc {") : css.index("}", css.index(".is-mc {"))]
|
||||
assert "var(--color-warning)" in body
|
||||
assert "var(--font-weight-bold)" in body
|
||||
|
||||
|
||||
def test_b07_sheet_button_spans_row() -> None:
|
||||
panels = _src("B07_DesignDetail/B07_DesignDetail_UI_Panels.ts")
|
||||
assert 'button.dataset.mc = "true"' in panels
|
||||
css = _src("B07_DesignDetail/B07_DesignDetail_UI_Style.css")
|
||||
rule = css[css.index('.b07-drawing-button[data-mc="true"] {') :]
|
||||
assert "grid-column: 1 / -1" in rule[: rule.index("}")]
|
||||
|
||||
Reference in New Issue
Block a user