feat(ground): 해상 selectable with MSL levels, 고조위·저조위, and checks

- Rules confirmed (승인 2026-10-26): datum MSL; 고조위 HWL and 저조위 LWL as
  two levels; 세굴 깊이 as for 하상; 파랑과 선박 하중 excluded from this scope.
- Checks: G13 levels missing, G10 해저면 not below 고조위, G11 저조위 not
  below 고조위, G14 pile wall at or below the corrosion allowance reference.
- CORROSION_ALLOWANCE_MM = 1 is a PLACEHOLDER reference (not in the RAG
  documents); the card and G14 mark it as to be confirmed.
- Card: the 해상 inputs; the section draws 고조위 (solid), 저조위 (dashed),
  and labels the ground line 해저면 EL.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-10-26 11:11:31 +09:00
1 parent 26a5aff517
commit b6e7f36091
9 files changed
+132 -22

No files matched your search

+18 -6
View File
@@ -21,14 +21,21 @@ export function groundSectionSvg(input: PierInput, model: PierModel): string {
const pileTips = model.piles.map((p) => p.bottom);
const lowestRow = rows.length ? rows[rows.length - 1].bottomEl : ground - 1;
// 하상: the 설계홍수위 (solid) and the 세굴선 replace the groundwater (dashed, 승인 2026-10-26).
const river = (input.groundPosition ?? '육상') === '하상';
const position = input.groundPosition ?? '육상';
const river = position === '하상';
const sea = position === '해상';
const level = river
? (Number.isFinite(input.floodLevelEl) ? input.floodLevelEl : undefined)
: (input.groundWaterOn && Number.isFinite(input.groundWaterEl) ? input.groundWaterEl : undefined);
: sea
? (Number.isFinite(input.highWaterEl) ? input.highWaterEl : undefined)
: (input.groundWaterOn && Number.isFinite(input.groundWaterEl) ? input.groundWaterEl : undefined);
// 해상: the 저조위 is drawn too (dashed), on the MSL datum.
const lowLevel = sea && Number.isFinite(input.lowWaterEl) ? input.lowWaterEl : undefined;
const groundLabel = sea ? '해저면 EL' : '지반고';
const scour = river && Number.isFinite(input.scourDepthM) && (input.scourDepthM as number) >= 0 ? (input.scourDepthM as number) : undefined;
const scourEl = scour !== undefined ? ground - scour : undefined;
const yMin = Math.min(footBottom, lowestRow, ...pileTips, level ?? ground, scourEl ?? ground) - 1;
const yMin = Math.min(footBottom, lowestRow, ...pileTips, level ?? ground, lowLevel ?? ground, scourEl ?? ground) - 1;
const yMax = Math.max(ground, footTop, input.copingTopEl) + 0.5;
const scale = PLOT_H / (yMax - yMin);
const y = (el: number) => TOP_PAD + (yMax - el) * scale;
@@ -55,16 +62,21 @@ export function groundSectionSvg(input: PierInput, model: PierModel): string {
// Ground line and label.
parts.push(`<line x1="0" y1="${y(ground)}" x2="${WIDTH}" y2="${y(ground)}" stroke="#8A6D3B" stroke-width="1.5"></line>`);
parts.push(`<text x="8" y="${y(ground) - 6}" font-size="12" fill="#18212B">지반고 ${ground.toFixed(3)}</text>`);
parts.push(`<text x="8" y="${y(ground) - 6}" font-size="12" fill="#18212B">${groundLabel} ${ground.toFixed(3)}</text>`);
// Groundwater (육상, when on) as a dashed line; the 설계홍수위 (하상) as a solid line.
if (level !== undefined) {
const dash = river ? '' : ' stroke-dasharray="6 4"';
const label = river ? '설계홍수위 DHWL' : '지하수위';
const label = river ? '설계홍수위 DHWL' : sea ? '고조위 HWL' : '지하수위';
parts.push(`<line x1="0" y1="${y(level)}" x2="${WIDTH}" y2="${y(level)}" stroke="#2F6DB5" stroke-width="${river ? 2 : 1}"${dash}></line>`);
parts.push(`<text x="8" y="${y(level) - 4}" font-size="12" fill="#123E70">${label} ${level.toFixed(3)}</text>`);
}
// 세굴선 (하상): the bed after scour.
// 해상: 저조위 (dashed, MSL datum).
if (lowLevel !== undefined) {
parts.push(`<line x1="0" y1="${y(lowLevel)}" x2="${WIDTH}" y2="${y(lowLevel)}" stroke="#2F6DB5" stroke-dasharray="6 4"></line>`);
parts.push(`<text x="8" y="${y(lowLevel) + 12}" font-size="12" fill="#123E70">저조위 LWL ${lowLevel.toFixed(3)}</text>`);
}
// 세굴선 (하상·해상): the bed after scour.
if (scourEl !== undefined) {
parts.push(`<line x1="0" y1="${y(scourEl)}" x2="${WIDTH}" y2="${y(scourEl)}" stroke="#8A6D3B" stroke-dasharray="3 3"></line>`);
parts.push(`<text x="8" y="${y(scourEl) + 12}" font-size="12" fill="#5B4A2E">세굴선 ${scourEl.toFixed(3)}</text>`);