'use strict' /** * Copyright (c) 2017~2022, OBCon Inc. * All rights reserved. */ /** * @file * @copyright 2017~2022, OBCon Inc. * @author gye hyun james kim [pnuskgh@gmail.com] */ //-------------------------------------------------------------------------------------------------- //--- 사용하는 좌표계 : https://hmjkor.tistory.com/483 //--- OBCon SCADA : EPSG:4326 : WGS84 좌표계. 위/경도 좌표계 //--- vWorld : EPSG:3857 (EPSG:900913) : 구글 Mercator(메카르도) 좌표계 //--- KakaoMap : WGS84 좌표계 //--- OpenLayers : EPSG:4326 : WGS84 좌표계. 위/경도 좌표계 //--- OpenLayers 3 : EPSG:3857 //--- //--- Korea에서 사용하는 좌표계 (https://www.osgeo.kr/17) //--- Korean 2000 : GRS80 경위도, EPSG:4019, EPSG:4737 (WGS84와 거의 유사) //--- GRS80 UTM-K : EPSG:5179, 네이버지도에서 사용중인 좌표계 //--- Bessel UTM-K : EPSG:5178, 새 주소지도에서 사용중 //--- Korean 1995 : WGS84 경위도, EPSG:4326, EPSG:4166 //--- Korean 1985 : Bessel 1841 경위도, EPSG:4004, EPSG:4162 //--- //--- 국토지리정보원(www.ngii.go.kr) 등에서 사용하는 좌표계 (http://www.juso.go.kr/) //--- GRS80 UTM-K(한국형 단일평면직각좌표계) : EPSG:5179 //--- 국토정보플랫폼 표준 좌표계 //--- 서부원점 : EPSG:5185 //--- 중부원점 : EPSG:5186 //--- 동부원점 : EPSG:5187 //--- 동해(울륭)원점 : EPSG:5188 //--- 좌표계 변환 프로그램 : https://wwhitelife.tistory.com/55 //--- //--- 좌표계 (https://www.slideshare.net/ybh0616/gis-2-93095088) //--- EPSG (European Petroleum Survey Group, 유럽석유조사그룹), https://epsg.io/ //--- https://www.google.com/maps/dir/37.575996,126.9769286//@37.5757392,126.9758296,18z 에서 위도, 경도 확인 가능 //--- CRS (Coordinate Reference System, 좌표참조체계) //--- GCS (Geographic Coordinate System, 지리좌표계) //--- 위도 (latitude) : 적도(0)가 기준, 북극(90), 남극(-90) //--- 경도 (longitude) : 본초 자오선(Prime Meridian)이 기준. 서경 -180 ~ 동경 180 //--- Prime Meridian : 영국 런던 그리니치 구 왕립 천문대를 지나는 자오선 //--- 대한민국 : 북위 33 ~ 43, 동경 124 ~ 132 //--- Bessel 1841, WGS84 (World Geodetic System 1984) //--- GRS80 (Geodetic Reference System 1980) //--- PCS (Projected Coordinate System, 투영좌표계) //--- SRS (Spatial Reference System, 공간참조체계) //-------------------------------------------------------------------------------------------------- //--- 지도 라이브러리 //--- vWorld //--- https://www.vworld.kr/dev/v4api.do //--- KakaoMap //--- //--- SGIS //--- https://sgis.kostat.go.kr/developer/html/newOpenApi/api/mapApi/ready.html //--- QGIS //--- https://snugis.tistory.com/category/ArcMap%20%26%20QGIS%20%EA%B0%95%EC%A2%8C //--- Proj4 : 좌표계 변환 프로그램 //--- https://wwhitelife.tistory.com/55 //-------------------------------------------------------------------------------------------------- /* - SharpFile 구조 * ~.shp : binary : 모양 형식 * ~.shx : binary : 모양 형식 인덱스 * ~.dbf : binary : 속성 형식 * ~.prj : string : 좌표 참조 시스템 "PROJCS > GEOGCS > DATUM > SPHEROID"의 첫번째 항목 : 좌표계 (예, GRS_1980) * ~.csf : binary : ??? * ~.cpg : string : 문자셋 * ~.sbn, sbx : binary : 기능의 공간 인덱스 x ~.fbn, fbx : 읽기 전용 기능의 공간 인덱스 x ~.ain, aih : 테이블에서 활성 필드의 속성 인덱스 * ~.shp.xml : string : 지리 공간 메타 데이터 (ISO 19115 또는 기타 XML 스키마 형식) x ~.ixs : 읽기/쓰기 데이터 세트에 대한 지오 코딩 색인 (ODB 형식) x ~.atx : ArcGIS 8 이상에서 .dbf 파일 속성 색인 x ~.qix : MapServer 및 GDAL/OGR 소프트웨어에서 사용하는 대체 쿼드 트리 공간 인덱스 - SharpFile - SharpFile To GeoJson - https://github.com/mbostock/shapefile - https://www.npmjs.com/package/shapefile - GeoJson - https://junghan92.medium.com/d3-geo-topojson-canvas%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A7%B5-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-ffab54ec23bf - GeoJson to TopoJson - https://www.npmjs.com/package/topojson-server - https://github.com/topojson/topojson - TopoJson : GeoJson의 확장 - GeoJson에 비해 1/10 크기 - KakaoMap - WGS84 좌표계 사용 - https://apis.map.kakao.com/web/sample/drawShape/ - https://apis.map.kakao.com/web/documentation/#Polygon */ const fs = require('fs'); const path = require('path'); const iconv = require('iconv-lite'); const proj4 = require('proj4'); const shapefile = require("shapefile"); class FileInfo { constructor(folderRoot, folder=null, filename=null, ext=null) { this._folderRoot = folderRoot; this._folder = folder; this._ext = ext this.filename = filename; } get folderRoot() { return this._folderRoot; } set folderRoot(newValue) { this._folderRoot = newValue; } get folder() { return this._folder; } set folder(newValue) { this._folder = newValue; } get filename() { return this._filename; } set filename(newValue) { if (newValue == null) { this._filename = newValue; } else { let tmpStrings = newValue.split('.'); if (tmpStrings.length == 2) { this._filename = tmpStrings[0]; this._ext = tmpStrings[1]; } else { this._filename = newValue; } } } get ext() { return this._ext; } set ext(newValue) { this._ext = newValue; } _getFile() { if (this._filename == null) { return null; } else { return (this._ext == null) ? this._filename:`${this._filename}.${this._ext}`; } } getFilename() { let filename = this._getFile(); if (filename == null) { return this._folder; } else { return (this._folder == null) ? filename:path.join(this._folder, filename); } } getFilenameFull() { let filename = this.getFilename(); if (filename == null) { return this._folderRoot; } else { return (this._folderRoot == null) ? this.getFilename():path.join(this._folderRoot, this.getFilename()); } } getFolderFull() { if (this._folderRoot == null) { return this._folder; } else { return (this._folder == null) ? this._folderRoot:path.join(this._folderRoot, this._folder); } } makeFolders() { if (this._folder == null) { return; } else { let folder = path.join(this._folderRoot); this._folder.split(path.sep).forEach(name => { folder = path.join(folder, name); if (!fs.existsSync(folder)) { fs.mkdirSync(folder); } }); } } deleteAllFile() { let folder = this.getFolderFull(); if (folder != null) { let files = fs.readdirSync(folder); files.forEach(function(file) { if (fs.statSync(path.join(folder, file)).isDirectory()) { fs.rmSync(path.join(folder, file), { recursive: true, force: true }) } else { fs.unlinkSync(path.join(folder, file)); } }.bind(this)); } } } class SharpFile { constructor() { //--- SharpFile : files/map/${serviceName}/site_${siteID}/SharpFile/${folder}/~.shp //--- GeoJson : files/map/${serviceName}/site_${siteID}/GeoJson/${folder}/~.geojson //--- KakaoMap : themes/${service}/${theme}/devices/KakaoMap/site_${siteID}/~.js this._folder = 'files/map'; //--- 지도 관련 파일이 저장되는 폴더 this._coordinates = []; //--- 좌표 변환에 사용되는 좌표계 this._messages = []; this.initialize(); } initialize() { this.init_proj4(); } //--- Proj4 라이브러리를 위한 설정 //--- https://wwhitelife.tistory.com/55 //--- 카카오맵에서 좌표 변환 : https://apis.map.kakao.com/web/sample/transCoord/ init_proj4() { this._coordinates = [ 'EPSG_3857', 'WGS84', 'GRS80', 'GRS_1980' ]; //--- OBCon과 vWorld에서 사용 //--- Google Mercator: EPSG:3857(공식), EPSG:900913(통칭) proj4.defs('EPSG_3857', '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs'); //--- KakaoMap에서 사용 //--- WGS84 (World Geodetic System 1984) : EPSG:4326, EPSG:4166 (Korean 1995) proj4.defs('WGS84', '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'); // proj4.defs('WGS84', '+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees'); //--- GRS80 (Geodetic Reference System 1980) : EPSG:4019, EPSG:4737 (Korean 2000) // proj4.defs('GRS80', '+proj=longlat +ellps=GRS80 +no_defs'); proj4.defs('GRS80', '+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs'); // proj4.defs('GRS_1980', '+proj=longlat +ellps=GRS80 +no_defs'); // proj4.defs('GRS_1980', '+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs'); // proj4.defs('GRS_1980', '+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs'); proj4.defs('GRS_1980', '+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs'); // proj4.defs('TM128', '+proj=tmerc +lat_0=38 +lon_0=128 +k=0.9999 +x_0=400000 +y_0=600000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43'); // proj4.defs('UTM-K', '+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs'); // //--- Bessel 1841 : EPSG:4004, EPSG:4162 (Korean 1985) // proj4.defs('Bessel_1841', '+proj=longlat +ellps=bessel +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43'); // //--- UTM52N (WGS84): EPSG:32652 // proj4.defs('UTM52N', '+proj=utm +zone=52 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'); // //--- UTM51N (WGS84) : EPSG:32651 proj4.defs('UTM51N', '+proj=utm +zone=51 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'); } getMessages(delimiter='') { return this._messages.join(delimiter); } //--- 서울도시가스 //--- MP: 적색, 확대시에만 표시 (LP: 청색, RP: 녹색) async sharpFileToGeoJson(service, site) { try { this._messages = []; this._messages.push('