diff --git a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Areas.ts b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Areas.ts index f43e3ad8..0b38f4ca 100644 --- a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Areas.ts +++ b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Areas.ts @@ -156,7 +156,7 @@ function soilDepth(design: CrossDesign): number | null { * 밴드는 평소 투명에 가깝게 두되 클릭 대상은 되도록 남겨 "면적을 눌러도 강조"가 성립한다. */ export function appendCrossAreaBands( - svg: SVGSVGElement, + svg: SVGElement, design: CrossDesign, groundSamples: SectionSample[], x: (offset: number) => number, diff --git a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Design.ts b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Design.ts index 4b57411f..251a4148 100644 --- a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Design.ts +++ b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_Design.ts @@ -437,7 +437,7 @@ export function buildDesignControls( * 부분)만 점선으로 그려 뒤에 깔린 지표선이 비쳐 보이게 하고, 나머지는 실선으로 둔다. */ export function appendCrossDesignOverlay( - svg: SVGSVGElement, + svg: SVGElement, design: CrossDesign, x: (offset: number) => number, toDisplayY: (elevation: number) => number, @@ -516,7 +516,7 @@ export function appendCrossDesignOverlay( * 무효 샘플 구간은 지반선과 동일하게 선을 끊어 그린다. */ export function appendRockBoundaryOverlay( - svg: SVGSVGElement, + svg: SVGElement, groundSamples: Array<{ offset_m?: number; elevation_m?: number | null; valid: boolean }>, offsetM: number, x: (offset: number) => number, @@ -544,7 +544,7 @@ export function appendRockBoundaryOverlay( /** 포장 측점의 노면 포장층 박스를 겹쳐 그린다 (노면 양 끝점 기준, 두께만큼 하향). */ export function appendPavementOverlay( - svg: SVGSVGElement, + svg: SVGElement, design: CrossDesign, x: (offset: number) => number, toDisplayY: (elevation: number) => number, diff --git a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_View.ts b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_View.ts index 2db3d66c..0c5b1845 100644 --- a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_View.ts +++ b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Cross_View.ts @@ -476,11 +476,26 @@ export function createCrossSectionCard( if (section.design) { const toDisplayY = (elevation: number): number => y(elevationMid + (elevation - elevationMid) * exaggeration); + // 표시 반폭으로 지면 샘플만 잘라도 설계선·면적 밴드·포장·암경계는 원래 좌표를 그대로 + // 쓰므로 플롯 밖으로 뚫고 나간다(2026-08-06 사용자 지적). 플롯 영역 clipPath로 잘라 + // 지정한 반폭 범위만 보이게 한다. + const clipId = `b06-cross-clip-${section.station_id}`; + const clip = svgElement("clipPath", { id: clipId }); + clip.append( + svgElement("rect", { + x: CROSS_PAD.left, + y: CROSS_PAD.top, + width: Math.max(widthPx - CROSS_PAD.left - CROSS_PAD.right, 1), + height: Math.max(heightPx - CROSS_PAD.top - CROSS_PAD.bottom, 1), + }), + ); + const overlayGroup = svgElement("g", { "clip-path": `url(#${clipId})` }); + svg.append(clip, overlayGroup); // 면적 밴드는 지면선 위·설계선 아래에 깔아 선이 밴드에 가리지 않게 한다. // 선택 여부와 무관하게 항상 깐다 — 평소에는 투명이고, 선택이 바뀔 때 카드를 새로 만들지 // 않고 클래스만 켜면 되므로 줌·팬이 살아남는다. setBandActive = appendCrossAreaBands( - svg, + overlayGroup, section.design, sourceSamples, x, @@ -488,12 +503,12 @@ export function createCrossSectionCard( toggleArea, ); // 포장층 → 설계선 → 암 경계선 순으로 겹쳐, 설계선이 포장 박스 위에 오게 한다. - appendPavementOverlay(svg, section.design, x, toDisplayY); - appendCrossDesignOverlay(svg, section.design, x, toDisplayY, sourceSamples); + appendPavementOverlay(overlayGroup, section.design, x, toDisplayY); + appendCrossDesignOverlay(overlayGroup, section.design, x, toDisplayY, sourceSamples); // 암 경계선은 지면선(지반선) 복사 + 오프셋 — 계획선 기준이 아님에 유의. if (rockBoundary && section.design.geometry_preset === "rock") { appendRockBoundaryOverlay( - svg, + overlayGroup, sourceSamples, rockBoundary.offsetFor(section), x, diff --git a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Page.ts b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Page.ts index cb810379..69f509d6 100644 --- a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Page.ts +++ b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Page.ts @@ -282,6 +282,16 @@ export async function renderB06ProfileCross(root: HTMLElement): Promise { } hideLoadingOverlay(); } + // 전체 반영 = 개별 반폭도 전역값으로 초기화(2026-08-06). 저장된 개별값 + // (design.display_half_width_m)이 남아 있으면 전역 반폭이 무시되므로, 세션에 + // 전역값을 명시해 저장값보다 우선하게 한다(확정 시 저장값도 전역으로 덮인다). + stationWidths.clear(); + if (requested !== undefined) { + for (const section of sectionDetail.cross_sections) { + stationWidths.set(widthKey(section.chainage_m), clampStationWidth(requested)); + } + } + persistStationWidths(); persistDisplayHalfWidth(); renderSectionDetail(); updateActionState();