- 옮김: B04 2 · B05 23 · B06 11 · A00_Common/design 13 (9,299 줄) · 이미 logic/ 에 있던 16 파일 그대로 - 안 옮김: 묶음 입구(package.json build:*) · 파이썬 · 순수지만 계산 아닌 8 (보기 결선 · 콜백 · API 타입 · 갈아끼움 알림판) - import 266 줄(142 파일) · 시험 · 주석 · 짝 표시 문자열 경로 고침 · B05 · B06 CLAUDE.md 짝 줄 logic/ - 시험 도우미 새 경로: 가짜 require 열쇠 · B05()/B06() 부름 · 형제 import 자리 · tsc 묶어 돌리는 시험 · 정규식 · rglob - design_view_cross 줄 한도 시험 685 → 688 (긴 import 경로 줄바꿈 3줄) - 확인: typecheck 0 · 서버 묶음 넷(corridor · server-calc · b07-extent · b07-note) 다시 지어 코드 같음(//#region 경로 주석만 다름) · 관련 시험 270 파일 — 남은 실패 19 는 옮기기 전과 같음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
89 lines
3.9 KiB
TypeScript
89 lines
3.9 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Drainage_Spans.ts
|
|
* 배수유역도(평면)에서 **구간형 구조물이 놓인 자리**를 계획선 위에 띠로 그린다.
|
|
*
|
|
* 왜 (계획서 3-6) — 산마루측구·도수로·옹벽처럼 **구간**으로 놓이는 시설은 종단에는 띠로
|
|
* 보이는데 평면에는 아무 표시가 없었다. 「노선 위에 임의 구간을 얹는 부품이 없다」가
|
|
* 그동안의 걸림돌이었는데, 계획선 표본(`strengthSamples`)이 **1m 간격이라 배열 인덱스가
|
|
* 곧 누가거리**여서 구간 → 화면 선은 잘라 붙이기만 하면 된다.
|
|
*
|
|
* 그리는 자리 — **계획선 바로 위, 강도 색칠·마커 아래**. 굵고 반투명해서 계획선을 덮지
|
|
* 않는다. 이름은 안 적는다(종단에 이미 있고, 지도에 글자를 얹으면 눈금·유역 번호와 겹친다).
|
|
* ========================================================================== */
|
|
|
|
import type { RoutePoint } from "../B04_PreProcess/logic/B04_PreProcess_UI_RouteSamples";
|
|
import type { StructureInstance, StructureType } from "./B05_Profile_Api_Structures";
|
|
|
|
/** 계획선 위에 얹을 구간 하나 — 누가거리 두 값과 색. */
|
|
export interface RouteSpanBand {
|
|
startM: number;
|
|
endM: number;
|
|
/** 구조물 레지스트리의 표시색(`style.color`). */
|
|
color: string;
|
|
}
|
|
|
|
/** 띠 굵기(px) — 계획선(2px 안팎)보다 확실히 굵되 유역 채움을 가리지 않는 값. */
|
|
const BAND_WIDTH_PX = 7;
|
|
|
|
/**
|
|
* 구간 띠를 그린다. 표본이 없거나 구간이 비면 아무 것도 하지 않는다.
|
|
*
|
|
* 인덱스는 **누가거리(m)** 다 — 표본이 1m 간격이라 그렇다(`resampleRoute`). 범위를 벗어난
|
|
* 값은 잘라 쓰고, 한 점짜리 구간(시작=끝)은 짧은 토막으로라도 보이게 한 칸을 준다.
|
|
*/
|
|
export function drawRouteSpans(
|
|
context: CanvasRenderingContext2D,
|
|
samples: ReadonlyArray<RoutePoint>,
|
|
spans: ReadonlyArray<RouteSpanBand>,
|
|
toScreen: (x: number, y: number) => [number, number],
|
|
): void {
|
|
if (samples.length < 2 || spans.length === 0) return;
|
|
const last = samples.length - 1;
|
|
context.save();
|
|
context.lineCap = "round";
|
|
context.lineJoin = "round";
|
|
context.lineWidth = BAND_WIDTH_PX;
|
|
for (const span of spans) {
|
|
const from = Math.max(0, Math.min(last, Math.floor(Math.min(span.startM, span.endM))));
|
|
const to = Math.max(from + 1, Math.min(last, Math.ceil(Math.max(span.startM, span.endM))));
|
|
context.beginPath();
|
|
for (let index = from; index <= to; index += 1) {
|
|
const [x, y] = toScreen(samples[index].x, samples[index].y);
|
|
if (index === from) context.moveTo(x, y);
|
|
else context.lineTo(x, y);
|
|
}
|
|
context.strokeStyle = span.color;
|
|
context.globalAlpha = 0.45;
|
|
context.stroke();
|
|
context.globalAlpha = 1;
|
|
}
|
|
context.restore();
|
|
}
|
|
|
|
/**
|
|
* 구조물 정본 + 타입 레지스트리 → 띠 목록. **종단 레인과 같은 자료**를 본다(계획서 3-6).
|
|
*
|
|
* · 구간형(`interval`)만 띠가 된다 — 점형 시설은 마커로 이미 보인다.
|
|
* · 색은 레지스트리 표시색을 그대로 쓴다(여기서 새로 정하지 않는다).
|
|
* · 시작·끝이 없으면 기준 측점으로 대신한다. 그것도 없으면 뺀다.
|
|
*/
|
|
export function routeSpansFromStructures(
|
|
structures: ReadonlyArray<StructureInstance>,
|
|
types: ReadonlyArray<StructureType>,
|
|
): RouteSpanBand[] {
|
|
const colorOf = new Map(types.map((type) => [type.type_id, type.style?.color]));
|
|
const spans: RouteSpanBand[] = [];
|
|
for (const item of structures) {
|
|
if (item.placement !== "interval") continue;
|
|
const start = item.start_m ?? item.chainage_m ?? null;
|
|
const end = item.end_m ?? item.chainage_m ?? null;
|
|
if (start === null || end === null) continue;
|
|
spans.push({
|
|
startM: Math.min(start, end),
|
|
endM: Math.max(start, end),
|
|
color: colorOf.get(item.type_id) ?? "#8a8a8a",
|
|
});
|
|
}
|
|
return spans;
|
|
}
|