gc-wing/scripts/prepare-zones.mjs

97 lines
2.7 KiB
JavaScript
Raw Normal View 히스토리

2026-02-15 11:22:38 +09:00
import fs from "node:fs/promises";
import path from "node:path";
const ROOT = process.cwd();
const ZONES = [
{ zoneId: "1", file: "특정어업수역Ⅰ.json", label: "", name: "수역I(동해)" },
{ zoneId: "2", file: "특정어업수역Ⅱ.json", label: "Ⅱ", name: "수역II(제주남방)" },
{ zoneId: "3", file: "특정어업수역Ⅲ.json", label: "Ⅲ", name: "수역III(서해남부)" },
{ zoneId: "4", file: "특정어업수역Ⅳ.json", label: "Ⅳ", name: "수역IV(서해중간)" },
];
// Inverse Web Mercator (EPSG:3857) -> WGS84 lon/lat
function mercatorToLonLat(x, y) {
const R = 6378137;
const lon = (x / R) * (180 / Math.PI);
const lat = (2 * Math.atan(Math.exp(y / R)) - Math.PI / 2) * (180 / Math.PI);
return [lon, lat];
}
function looksLikeLonLat(x, y) {
return Math.abs(x) <= 180 && Math.abs(y) <= 90;
}
function convertPoint(pt) {
if (!Array.isArray(pt) || pt.length < 2) return pt;
const x = pt[0];
const y = pt[1];
if (typeof x !== "number" || typeof y !== "number") return pt;
if (looksLikeLonLat(x, y)) return [x, y];
return mercatorToLonLat(x, y);
}
function convertCoords(coords) {
if (!Array.isArray(coords)) return coords;
if (coords.length === 0) return coords;
// Point: [x, y]
if (typeof coords[0] === "number") return convertPoint(coords);
// Nested arrays
return coords.map(convertCoords);
}
async function main() {
const rawDir = path.join(ROOT, "data", "raw", "zones");
const outDir = path.join(ROOT, "apps", "web", "public", "data", "zones");
await fs.mkdir(outDir, { recursive: true });
const features = [];
for (const z of ZONES) {
const rawPath = path.join(rawDir, z.file);
const txt = await fs.readFile(rawPath, "utf-8");
const fc = JSON.parse(txt);
if (!fc || fc.type !== "FeatureCollection" || !Array.isArray(fc.features)) {
throw new Error(`Unexpected GeoJSON in ${rawPath}`);
}
for (const f of fc.features) {
if (!f?.geometry?.coordinates) continue;
const geometry = {
...f.geometry,
coordinates: convertCoords(f.geometry.coordinates),
};
features.push({
...f,
properties: {
...(f.properties || {}),
zoneId: z.zoneId,
zoneLabel: z.label,
zoneName: z.name,
},
geometry,
});
}
}
const out = {
type: "FeatureCollection",
name: "zones.wgs84",
features,
};
const outPath = path.join(outDir, "zones.wgs84.geojson");
await fs.writeFile(outPath, JSON.stringify(out), "utf-8");
// eslint-disable-next-line no-console
console.log(`Wrote ${features.length} features -> ${path.relative(ROOT, outPath)}`);
}
main().catch((err) => {
// eslint-disable-next-line no-console
console.error(err);
process.exit(1);
});