Files
Aislo/D03_PlanAnalysis/D03_PlanAnalysis_UI_LayerLegend.ts
T
eomsangdonandClaude Opus 5.5 a6ef53e8a3 feat(공용 지도 겹): 임도 짐작 걷음 · 그 자리 = 임도망도(전국 국가임도 · route 아이콘 · 범례 「임도망도 간선 · 작업 · 산불」 · 줌 14 부터 연도 · 종류 글) · 올린 임도망도 = 임도(업로드)(위치 칸 단추 · 목록 · 알림 · 서버 글) (PLAN 630 · 요구 532 · 534)
- 열쇠 그대로(nationalRoad · forestRoadFile) — 옛 켬끔 취향 이어짐 · forestRoad 열쇠 · 도로 소로 거름은 B05 자료 셈 이음으로 남김(겹 목록 · 꼴 · 범례만 걷음)
- 기존 도로(road) 겹 · 소스 · 범례 그대로
- 시험 553_4 겹 차례 · 584_3 범례 기대값을 새 이름으로 고침 · 622_2 에 630 · 534 지킴 덧

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 22:10:58 +09:00

125 lines
5.0 KiB
TypeScript

/* =============================================================================
* D03_PlanAnalysis_UI_LayerLegend.ts
* D03 바탕 겹 받은 자료 꼴 · 범례 줄 · 겹별 수(PLAN 569-2 · 581 · 584-1 · 584-3) — 켠 겹의 받은 범위 안 수 · 넓이.
* 급경사 = 고른 범위(603)마다 % · ° · 비율(1 % 칸 수로 바로 셈).
* 범례 칸 · 조각 겹 범례 = 공용 `A00_Common/map/map_legend`(624-2) · 여기는 받은 자료 줄만.
* 범례 줄 셈 = 공용 `map_legend` `legendRows`(624-3) · 여기는 자료 꼴 · 겹별 수 · 부르는 곳 = `D03_PlanAnalysis_UI_Layers.ts`(받기 · 그리기).
* ========================================================================== */
import type { PreparedLayer } from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import type {
PlanForestRoads,
PlanLandslideZones,
PlanRaster,
PlanSoils,
PlanZones,
PlanBand,
} from "./D03_PlanAnalysis_Api";
import { LINE_KEYS, type LineLayerKey } from "../A00_Common/map/map_layer_list";
import { bandRatios, type SlopeBand } from "../A00_Common/map/logic/map_slope_bands";
/** 범례 줄 = 공용(624-3 · B05 평면도 씀) — 옛 이름으로 다시 내놓음. */
export { legendRows } from "../A00_Common/map/map_legend";
/** 선 겹 — 그릴 선 · 받은 범위 안 가닥 · 길이 m. */
export interface PreparedLines {
layer: PreparedLayer;
count: number;
length_m: number;
/** 0차곡 — 쓴 지형 원천(624-4). */
source?: string;
}
export type Prepared = Record<LineLayerKey, PreparedLines> & {
contour: PreparedLayer;
/** 세류 · 하천(소하천 · 지방하천 · 연결선). */
stream: [PreparedLayer, PreparedLayer];
cadastral: PreparedLayer;
/** 전체 · 그중 소로 · 미분류(옛 임도 짐작 · 겹 걷음 · 수만 셈). */
road: { all: PreparedLayer; small: PreparedLayer };
/** 임도(업로드)(584-3). */
forestRoadFile: { layer: PreparedLayer; info: PlanForestRoads };
/** 급경사(603) — 값 그림 칸 · 고른 범위 · 칠한 그림(blob 주소) · 칠하기 ms. */
slope: {
raster: PlanRaster;
image: HTMLImageElement;
values: ImageData;
bands: SlopeBand[];
url: string;
paintMs: number;
};
hillshade: { raster: PlanRaster; image: HTMLImageElement };
landslide: { raster: PlanRaster; image: HTMLImageElement };
/** 산사태취약지역(584-3) — 점(경위도) · 지번 맞는 필지 테두리. */
landslideZones: { parcels: PreparedLayer; info: PlanLandslideZones };
water: PreparedLayer;
zones: { kinds: Map<string, PreparedLayer>; summary: PlanZones["summary"] };
/** 토양형(코드 차례) → 지물 · 색 값. */
soils: { kinds: Array<{ layer: PreparedLayer; color: string }>; summary: PlanSoils["summary"] };
bands: { stream: PreparedLayer; road: PreparedLayer; info: { stream: PlanBand; road: PlanBand } };
building: PreparedLayer;
place: Array<{ lon: number; lat: number; name: string }>;
};
/** 검증 창구 — 겹별 수(지물 · 넓이 m² · 길이 m). */
export const layerCounts = (data: Partial<Prepared>): Record<string, number> => ({
...(data.building && { building: data.building.features.length }),
...(data.water && { water: data.water.features.length }),
...(data.road && {
road: data.road.all.features.length,
forestRoad: data.road.small.features.length,
}),
...(data.forestRoadFile && {
forestRoadFile: data.forestRoadFile.info.count,
forestRoadFile_m: data.forestRoadFile.info.length_m,
forestRoadFile_total: data.forestRoadFile.info.total,
}),
...(data.landslideZones && {
landslideZone_points: data.landslideZones.info.points.length,
landslideZone_parcels: data.landslideZones.parcels.features.length,
landslideZone_missing: data.landslideZones.info.missing.length,
}),
...(data.place && { place: data.place.length }),
...(data.zones &&
Object.fromEntries(
Object.entries(data.zones.summary).flatMap(([kind, value]) => [
[`zone_${kind}`, value.count],
[`zone_${kind}_m2`, value.area_m2],
]),
)),
...(data.soils &&
Object.fromEntries(
data.soils.summary.flatMap((soil) => [
[`soil_${soil.code}`, soil.count],
[`soil_${soil.code}_m2`, soil.area_m2],
]),
)),
...(data.bands && {
band_stream_m2: data.bands.info.stream.area_m2,
band_road_m2: data.bands.info.road.area_m2,
}),
...(data.hillshade && { hillshade_px: data.hillshade.image.naturalWidth }),
...(data.slope && {
slope_px: data.slope.image.naturalWidth,
slope_cells: (data.slope.raster.counts ?? []).reduce((sum, n) => sum + n, 0),
slope_paint_ms: data.slope.paintMs,
...Object.fromEntries(
bandRatios(data.slope.raster.counts ?? [], data.slope.bands).map((r, i) => [
`slope_band_${i}`,
r,
]),
),
}),
...(data.landslide && { landslide_px: data.landslide.image.naturalWidth }),
...Object.fromEntries(
LINE_KEYS.flatMap((key) => {
const got = data[key];
return got
? [
[key, got.count],
[`${key}_m`, got.length_m],
]
: [];
}),
),
});