Files
Aislo/D03_PlanAnalysis/D03_PlanAnalysis_UI_LayerLegend.ts
T
eomsangdonandClaude Opus 5.5 c6a1efad0c refactor(공용 지도): 겹 받기 · 범례 줄 · 급경사 범위 · 위성 밝기 · 겹 자료 도움을 A00_Common/map 으로 — D03 은 다시 내놓기 · 동작 그대로 (PLAN 624-3 · 요구 530)
- D03_Api 겹 받기 → map_layer_api.ts(D03_Api 가 다시 내놓음)
- UI_SlopeBands · logic SlopeBands · UI_SatLight → map_slope_bands · logic/map_slope_bands · map_sat_light
- 범례 줄 legendRows → map_legend.ts(받은 자료 꼴 LegendData · D03 LayerLegend 가 다시 내놓음)
- glImage · glTagged · shadeImage · loadImage · WATER_KEYS · FOREST_ROAD_KINDS · hectare → map_layer_data.ts
- 시험 경로 고침 — test_603(TS 자리) · test_606_1(밝기 파일) · test_584_3(범례 글 = 공용 파일도 읽음)

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

123 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;
}
export type Prepared = Record<LineLayerKey, PreparedLines> & {
contour: PreparedLayer;
/** 세류 · 하천(소하천 · 지방하천 · 연결선). */
stream: [PreparedLayer, PreparedLayer];
cadastral: PreparedLayer;
/** 전체 · 그중 임도 짐작(소로 · 미분류) — `road` · `forestRoad` 가 함께 씀. */
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],
]
: [];
}),
),
});