/* ============================================================================= * map_layer_list.ts * 공용 지도 겹 목록(PLAN 624-2 · 요구 530 · 결정 A② · A⑧ · A⑨) — 예정노선(D03) · B05 평면이 같이 씀. * 겹 = 열쇠 · 아이콘 · 이름 · 처음 값(`on` = 예정노선) · 단추 묶음(바탕 · 물 · 길 · 구역 · 사이 나눔선). * 페이지 표(`MAP_LAYER_PAGES`) = 보일 겹(숨길 겹) · 처음 켬(없으면 겹의 `on`) · 켬끔 취향 열쇠. * 선 겹 꼴 · 보호구역 색 · 산사태위험 범례 = GL 꼴(`map_layer_specs`) · 범례(`map_legend`) · 옛 캔버스가 같이 읽음. * 쓰는 법 = 겹 줄 `createMapLayerBar({ page })`(`map_layer_bar`) · 새 겹 = `GROUPS` 한 줄 + 꼴 한 벌. * ========================================================================== */ import type { IconName } from "@ui/ui_template_icons"; import type { LegendItem } from "@ui/ui_template_flow_legend"; import { readByKey } from "../b_page_state"; export type MapLayerKey = | "satellite" | "hillshade" | "contour" | "slope" | "stream" | "water" | "road" | "forestRoad" // 걷은 겹(임도 짐작 · 요구 532) — 목록 · 꼴 없음 · 페이지 자료 셈 이음만 남음 | "forestRoadFile" | "nationalRoad" | "ecoForest" | "ecology" | "cadastral" | "zones" | "soils" | "landslide" | "landslideZones" | "faults" | "lineaments" | "zeroOrder" | "bands" | "building" | "place"; /** 임도(업로드) 고름(605-2) — 묶음 하나 또는 그 안의 선 하나(지도 강조). */ export interface RoadPick { bundle: string; line?: number; } export interface LayerDef { key: MapLayerKey; icon: IconName; title: string; /** 예정노선 처음 값 — 다른 페이지는 `MAP_LAYER_PAGES[page].on`. */ on: boolean; } /** 단추 묶음(사이 나눔선) — 바탕 · 물 · 길 · 구역. 「지금」 겹 처음 값 = 끔(`_분석_440-C` 1-4). */ export const GROUPS: readonly (readonly LayerDef[])[] = [ [ { key: "satellite", icon: "satellite", title: "위성사진", on: true }, { key: "hillshade", icon: "sun", title: "음영기복(2 m 지형 · 산줄기 · 골)", on: false }, { key: "contour", icon: "mountain", title: "도엽 등고선(굵은 선 = 계곡선 25 m)", on: true }, { key: "slope", icon: "angle", title: "급경사 색(기울기 % 범위 · 범례 ⚙ 로 바꿈)", on: false }, ], [ { key: "stream", icon: "droplet", title: "세류선(가는 파랑) · 하천(굵은 파랑)", on: true }, { key: "water", icon: "ripple", title: "물 면(도엽 실폭하천 · 저수지 등)", on: false }, { key: "road", icon: "road", title: "기존 도로(도엽 도로중심선)", on: false }, { key: "nationalRoad", icon: "route", title: "임도망도(산림청 전국 국가임도 · 간선 · 작업 · 산불 색 · 지방 · 민간임도는 「임도(업로드)」로)", on: false, }, { key: "forestRoadFile", icon: "map", title: "임도(업로드)(산림청 시군구 SHP 등 사용자가 올린 지방 · 민간임도 = 밝은 분홍 실선 · 왼쪽 「위치」 칸에서 올리고 묶음 고름 · 지움)", on: false, }, ], [ { key: "cadastral", icon: "borderAll", title: "지적도(참고용 · 법적 효력 없음)", on: false }, { key: "zones", icon: "shield", title: "보호 · 규제 구역(브이월드 여덟 종 · 참고용)", on: false, }, { key: "soils", icon: "leaf", title: "산림입지도(토양형 · 산림청 산림입지토양도 1:25,000 · 줌 10 이상 · 참고용)", on: false, }, { key: "ecoForest", icon: "trees", title: "경제림육성단지(산림청 2014 · 국유 · 사유 테두리 · 참고용)", on: false, }, { key: "ecology", icon: "plant", title: "생태자연도(환경부 · 1~3 등급 · 별도관리 · 참고용)", on: false, }, { key: "landslide", icon: "alert", title: "산사태위험지도(1~5 등급 · 행안부 생활안전지도 · 참고용)", on: false, }, { key: "landslideZones", icon: "alertOctagon", title: "산사태취약지역(시도 지정 현황 · 점 + 지번 필지 테두리 · 참고용)", on: false, }, { key: "faults", icon: "bolt", title: "단층(브이월드 지질 · 참고용)", on: false }, { key: "lineaments", icon: "lineDashed", title: "지질구조선(브이월드 지질 · 참고용)", on: false, }, { key: "zeroOrder", icon: "arrowsJoin", title: "0차곡(지형 추정 골짜기 머리 · 위 집수 0.1~1 ha · 곡두 통과 피함)", on: false, }, { key: "bands", icon: "borderOuter", title: "계류 100 m · 도로 300 m 띠(타당성평가)", on: false, }, { key: "building", icon: "building", title: "건물(도엽 · 하류 민가 · 인가)", on: false }, { key: "place", icon: "mapPin", title: "지명(도엽 계곡 · 령 · 부락)", on: false }, ], ]; export const LAYERS: readonly LayerDef[] = GROUPS.flat(); /** 지도가 있는 페이지. */ export type MapPage = "d03" | "b05"; /** 페이지 표 — 숨길 겹 · 처음 켬(없음 = 겹의 `on`) · 켬끔 취향 열쇠. */ export const MAP_LAYER_PAGES: Record< MapPage, { hide: readonly MapLayerKey[]; on?: readonly MapLayerKey[]; pref: string } > = { d03: { hide: [], pref: "aislo:pref:d03.layers" }, // A② 처음 = 지금 그대로(등고선 · 하천) · A⑨ 띠(타당성) · 임도(업로드) 숨김 b05: { hide: ["bands", "forestRoadFile"], on: ["contour", "stream"], pref: "aislo:pref:b05.layers", }, }; /** 그 페이지에 보일 겹 묶음(빈 묶음 뺌). */ export const pageGroups = (page: MapPage): LayerDef[][] => GROUPS.map((group) => group.filter((def) => !MAP_LAYER_PAGES[page].hide.includes(def.key)), ).filter((group) => group.length); /** 켬끔 취향 — 없거나 깨지면 페이지 처음 값 · 숨긴 겹 = 끔. */ export function readLayerPref(page: MapPage): Record { const { hide, on: first, pref } = MAP_LAYER_PAGES[page]; const on = Object.fromEntries( LAYERS.map((def) => [def.key, first ? first.includes(def.key) : def.on]), ) as Record; try { const saved = JSON.parse(readByKey(pref) ?? "{}") as Partial>; for (const def of LAYERS) if (typeof saved[def.key] === "boolean") on[def.key] = saved[def.key] as boolean; } catch { // 깨진 값 = 처음 값 } for (const key of hide) on[key] = false; return on; } /** 보호구역 종류 → 그림 색 값(서버 `ZONE_KINDS` 열쇠). */ export const ZONE_COLORS: Record = { forest: "--draw-map-zone-forest", baekdu: "--draw-map-zone-baekdu", water: "--draw-map-zone-water", park: "--draw-map-zone-park", heritage: "--draw-map-zone-heritage", wetland: "--draw-map-zone-wetland", wildlife: "--draw-map-zone-wildlife", greenbelt: "--draw-map-zone-greenbelt", }; /** 산사태위험지도 범례(1 등급 = 가장 위험 · 색 = WMS 그림 색). */ export const LANDSLIDE_LEGEND: LegendItem[] = [1, 2, 3, 4, 5].map((grade) => ({ label: `산사태 ${grade}등급`, color: `var(--draw-map-landslide-grade-${grade})`, })); /** 선 겹 — 이름 · 그림 꼴(서버 `LINE_KINDS` 열쇠 = `kind` · 없으면 0차곡). 새 선 겹 = 여기 한 줄. */ export type LineLayerKey = "faults" | "lineaments" | "zeroOrder"; export const LINE_LAYERS: Record< LineLayerKey, { label: string; kind?: string; color: string; width: number; dash: number[] } > = { faults: { label: "단층", kind: "faults", color: "--draw-map-fault", width: 2.4, dash: [] }, lineaments: { label: "지질구조선", kind: "lineaments", color: "--draw-map-lineament", width: 1.8, dash: [8, 4], }, zeroOrder: { label: "0차곡", color: "--draw-map-zero-order", width: 1.8, dash: [4, 3] }, }; export const LINE_KEYS = Object.keys(LINE_LAYERS) as LineLayerKey[];