- 맞춤 규칙 한 벌 — common_util_structure_station(파이썬 · TS 짝 · 거울 시험) - 입력 — 좌측 폼 칸(1 m 단계 · 친 값만) · 끌기 · 우클릭 · 방향키(1 m 걸음) · 배수유역도 관 · B06 관 옮김 · 추가 - 구간형 시작 · 끝도 정수 m · 일반 측점 = 횡단 상세를 읽을 때 등록 - 서버 자동 배치 · 노선 재투영 자리도 정수 m(확정본은 단추로만) - [정수 맞춤] — 구조물 목록 머리 · 확인 창 · 관은 하나씩 폼 [수정] 길 · 계획고 편집 따라감 · 결과 n건 알림 - 찾는 폭 한 값 — 손으로 적은 0.51 을 PIPE_MATCH_M 으로 - 시험 — test_234_1 새로 · 1 m 걸음 · 정수 입력에 맞춘 기대값 고침(219_1 · station_roundtrip) · 헬퍼 대역 보탬 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F3mdb91125mPoC6tpsQx4P
70 lines
2.9 KiB
TypeScript
70 lines
2.9 KiB
TypeScript
/* =============================================================================
|
|
* common_util/common_util_structure_station.ts
|
|
* 구조물 · 관 기준 측점 = 정수 m · 일반 측점 1 m 안이면 그 측점에 붙음(234-1).
|
|
*
|
|
* 파이썬 짝 = `common_util/common_util_structure_station.py`(서버 자동 배치 · 노선 재투영).
|
|
* 거울 시험 = `resources/tester/test_234_1_structure_station.py`.
|
|
* 일반 측점 = 격자 · 시종점(구조물 측점 kind "irregular" 은 뺌) — 상세를 읽을 때 한 번 둔다.
|
|
* ========================================================================== */
|
|
|
|
/** 일반 측점에 붙는 폭(m) — 이 안이면 그 측점 값(끝 측점처럼 정수가 아니어도). */
|
|
export const GENERAL_SNAP_M = 1;
|
|
const EPS = 1e-6;
|
|
|
|
let general: number[] = [];
|
|
|
|
/** 일반 측점 목록을 둔다 — 횡단 상세를 읽을 때마다(B05 · B06 한 노선). */
|
|
export function setGeneralStations(
|
|
stations: ReadonlyArray<{ chainage_m: number; kind?: string }> | null | undefined,
|
|
): void {
|
|
general = (stations ?? [])
|
|
.filter((station) => station.kind !== "irregular")
|
|
.map((station) => station.chainage_m);
|
|
}
|
|
|
|
export const generalStations = (): readonly number[] => general;
|
|
|
|
function nearGeneral(value: number, stations: readonly number[]): number | null {
|
|
let best: number | null = null;
|
|
for (const station of stations) {
|
|
const gap = Math.abs(station - value);
|
|
if (gap < GENERAL_SNAP_M - EPS && (best === null || gap < Math.abs(best - value)))
|
|
best = station;
|
|
}
|
|
return best;
|
|
}
|
|
|
|
/** 기준 측점 맞춤 — 일반 측점 1 m 안이면 그 측점 · 아니면 정수 m(.5 는 올림) · 정수가 일반 측점
|
|
* 1 m 안이면 그 측점(끝 119.8 옆 119 → 119.8). 두 번 맞춰도 같다. */
|
|
export function snapStructureStation(
|
|
chainageM: number,
|
|
stations: readonly number[] = general,
|
|
): number {
|
|
if (!Number.isFinite(chainageM)) return chainageM;
|
|
const direct = nearGeneral(chainageM, stations);
|
|
if (direct !== null) return direct;
|
|
const whole = Math.floor(chainageM + 0.5);
|
|
return nearGeneral(whole, stations) ?? whole;
|
|
}
|
|
|
|
/** 방향키 한 걸음(1 m) — 붙기가 제자리로 되돌리면 한 걸음 더(끝 119.8 → 118). 노선 밖이면 제자리. */
|
|
export function stepStructureStation(
|
|
fromM: number,
|
|
direction: 1 | -1,
|
|
stations: readonly number[] = general,
|
|
): number {
|
|
const end = stations.length ? Math.max(...stations) : Infinity;
|
|
for (let steps = 1; steps <= 3; steps += 1) {
|
|
const next = snapStructureStation(fromM + direction * steps, stations);
|
|
if (next < 0 || next > end + EPS) return fromM;
|
|
if ((next - fromM) * direction > EPS) return next;
|
|
}
|
|
return fromM;
|
|
}
|
|
|
|
/** 이미 맞춘 값인가(정수 맞춤 단추가 옮길 것을 가름). */
|
|
export const isSnappedStation = (
|
|
chainageM: number,
|
|
stations: readonly number[] = general,
|
|
): boolean => Math.abs(snapStructureStation(chainageM, stations) - chainageM) < EPS;
|