|
[OpenLayers component API 만들기] 5. FGIS_App 네이버 <=> 카카오 좌표계 변환
FGIS/App API 시리즈 는 OpenLayers(ol.js v6.*)로 개발중입니다.
GIS 및 OpenLayers 개발자가 아니거나 GIS 좌표계 공간 연산, 도식 등 깊이 알고 개발하지 않을 경우 간단한 함수만으로도 개발참여와 공동개발시 유용하게 개발하는 중입니다. (물론 CSS나 jquery 등 일치시키는게 중요합니다.)
단, 최소한의 상수나 class 구성은 익혀야할것 같습니다.
Openlayers의 함수를 굳이 감싸는 방식이 아니라 Openlayers API는 그대로 쓰고 확장한것(ol-ex와는 개념이 다른 방향)과 응용 기능을 API식으로 만드는게 목표입니다. 그래야 여러 맵폼을 독립적으로 사용할 수 있게됩니다.
네이버,브이월드,구글(EPSG:3857,EPSG:900913)과 카카오맵(EPSG:5181) 등 상이한 좌표계를 토글할때
기존 방식으로 각 레이어별 projection를 다중화하였으나 배경지도인 타일맵의 해상도가 떨어졌다.
이번 5단계는 메인맵의 자체를 현재 보는 배경지도의 좌표계로 변환하여 더 선명한 해상도를 유지하는 방안을 제시한다. 이때 WMS와 WFS, 로컬 생성한 레이어까지 자동변환하여 개발자는 기존 소스코딩방식을 유지하도록 한다.
물론, 이방식을 응용하면 다른 좌표계를 사용하는 배경지도를 더욱 선명하게 사용할수있게 된다.
- 데모 : http://www.gisapplication.kr/FGISAPPClass/
(1) 좌표계 전역변수 선언
사용할 네이버,브이월드,구글(EPSG:3857,EPSG:900913)과 카카오맵(EPSG:5181)의 좌표계와 맵뷰를 생성한다.
Main_proj5181 = new ol.proj.Projection({ code: 'EPSG:5181', extent: Daum_extent, units: 'm' }) Main_proj3857 = new ol.proj.Projection({ code: 'EPSG:3857', units: 'm', axisOrientation: 'neu' }); if (MainMapIndx == 'map2') this.main_projection = Main_proj5181; else this.main_projection = Main_proj3857; /////////////////////////////////////////////////////////////////////////////////////////// var Object_View = { projection: this.main_projection, minZoom: Set_restrict_Zoom[0], maxZoom: Set_restrict_Zoom[1], constrainResolution: true, }; if (Set_Map_extent) Object_View['extent'] = Set_Map_extent; var Map_View = new ol.View(Object_View); |
(2) 좌표계 변환처리
좌표계 변환시 메인맵뷰의 좌표계를 선언하고, 자동적으로 TMS, WMS, WFS, 로컬벡터 레이어의 좌표계와 소스의 각 객체의 좌표도 자동 변환한다.
//메인 좌표계 변환 //'EPSG:3857' 'EPSG:5181' var before_Coord = 'EPSG:3857'; var before_MapCenter = null; var before_MapExtent = null; var before_MapZoom = null; this.Set_MapCoord = function(_SetCoord) { if (before_Coord == _SetCoord) return; ////////////////////////////////////////////////////////////////////////////////// //1.MAP var Set_restrict_Zoom = [Init_restrict_Zoom[0], Init_restrict_Zoom[1]]; if (_SetCoord == 'EPSG:5181') { that.main_projection = Main_proj5181; before_MapZoom = before_MapZoom - 5; Set_restrict_Zoom[0] = Init_restrict_Zoom[0] - 5; Set_restrict_Zoom[1] = Init_restrict_Zoom[1] - 5; } else { that.main_projection = Main_proj3857; } //overviewmap var over_Object_View = { projection: that.main_projection, minZoom: Set_restrict_Zoom[0], maxZoom: Set_restrict_Zoom[1], constrainResolution: true, }; var over_Map_View = new ol.View(over_Object_View); GA_App.overviewMapControl.getOverviewMap().setView(over_Map_View); GA_App.overviewMapControl.setCollapsed(true); //main map var Object_View = { projection: that.main_projection, minZoom: Set_restrict_Zoom[0], maxZoom: Set_restrict_Zoom[1], constrainResolution: true, }; var Set_Map_extent = Init_Map_extent ? Coord_transformExtent(Init_Map_extent, 'EPSG:4326', _SetCoord) : null; if (Set_Map_extent) Object_View['extent'] = Set_Map_extent; var Map_View = new ol.View(Object_View); GA_App.map.setView(Map_View); GA_App.map.getView().on('change:resolution', function(e) { var Org_level = GA_App.map.getView().getZoom(); var _Zoom = Math.floor(Org_level); if (GA_App.GA_Map.main_projection.code_ == 'EPSG:5181') { _Zoom = _Zoom + 5; } GA_App.GA_MapControl.SetMapLevel(_Zoom); }); before_MapCenter = Coord_transformPoint(before_MapCenter, 'EPSG:4326', _SetCoord); before_MapExtent = before_MapExtent ? Coord_transformExtent(before_MapExtent, 'EPSG:4326', _SetCoord) : null; GA_App.map.getView().setCenter(before_MapCenter); GA_App.map.getView().setZoom(before_MapZoom); ////////////////////////////////////////////////////////////////////////////////// //2.Layer var Layers_arr = GA_App.map.getLayers().getArray(); Layers_arr.forEach(function(_layer) { try { var _source = _layer.getSource(); if ((_source instanceof ol.source.Vector)) { if (_source instanceof ol.source.Cluster) { _source.clear(); _source = _source.getSource(); _source.clear(); _source.refresh(); } else { var _features = _source.getFeatures(); _features.forEach(function(_feature) { try { _feature.getGeometry().transform(before_Coord, _SetCoord); } catch (error) { } }); _source.dispatchEvent('change'); //_source.refresh(); //_source.updateParams({"time": Date.now()}); } } } catch (error) { } }); ////////////////////////////////////////////////////////////////////////////////// before_Coord = _SetCoord; } |
(3) 좌표계 변환시 맵의 이벤트 적
- 오버맵(인덱스맵)
GA_App.overviewMapControl = new ol.control.OverviewMap({ className: 'ol-custom-overviewmap', layers: [Main_overviewmaplayer], collapsed: true, mapOptions: { projection: this.main_projection, numZoomLevels: 6, } }); |
- 메인맵 이벤트 처리 : 선택이벤트 등 사용되는 Interaction도 같이 변경시 처리 방안을 코딩한
GA_App.map.getView().on('change:resolution', function(e) { var Org_level = GA_App.map.getView().getZoom(); var _Zoom = Math.floor(Org_level); if (GA_App.GA_Map.main_projection.code_ == 'EPSG:5181') { _Zoom = _Zoom + 5; } GA_App.GA_MapControl.SetMapLevel(_Zoom); }); GA_App.map.on('moveend', function(e) { var Org_level = GA_App.map.getView().getZoom(); var _Zoom = Math.floor(Org_level); if (GA_App.GA_Map.main_projection.code_ == 'EPSG:5181') { _Zoom = _Zoom + 5; } var _Center = Coord_transformPoint(GA_App.map.getView().getCenter(), GA_App.GA_Map.main_projection.code_, 'EPSG:4326'); var _Extent = ol.proj.transformExtent(GA_App.map.getView().calculateExtent(GA_App.map.getSize()), GA_App.GA_Map.main_projection.code_, 'EPSG:4326'); GA_App.GA_Map.MapDIV().dispatchEvent(new CustomEvent('change:moveend', { detail: { "center": _Center, "zoom": _Zoom, "extent": _Extent } })); before_MapCenter = _Center; before_MapExtent = _Extent; before_MapZoom = _Zoom; }); GA_App.map.on('pointermove', function(e) { VectorObjectSelectedfeature = null; var _Center = Coord_transformPoint(e.coordinate, GA_App.GA_Map.main_projection.code_, 'EPSG:4326'); GA_App.GA_Map.MapDIV().dispatchEvent(new CustomEvent('change:cursormove', { detail: { "center": _Center } })); //마우스 오버시 벡터객체 힌트창 if (that.MainMapControlMode == "MOVE") { layerfeatures_Over(e); } }); GA_App.map.on('click', function(e) { var _Center = Coord_transformPoint(e.coordinate, GA_App.GA_Map.main_projection.code_, 'EPSG:4326'); if (selectClick) { clearInterval(HighLight_selectAnimationTimer); selectClick.getFeatures().clear(); } if (GA_App.GA_Map.MainMapControlMode == "RoadView") { GA_App.GA_DaumRoadViewControl.Show_DaumRoadView(_Center); } GA_App.GA_Map.MapDIV().dispatchEvent(new CustomEvent('mouse:click', { detail: { "center": _Center } })); //선택객체가 없을경우(마우스 오버된 객체가 없을 경우) if (!VectorObjectSelectedfeature) { that.WMS_LayerSearchFeature(_Center); //WMS레이어 선택 } VectorObjectSelectedfeature = null; }); |
- 공통함수
//지도상의 좌표로 변환 this.fromLonLat = function(_Point) { return ol.proj.transform(_Point, 'EPSG:4326', GA_App.GA_Map.main_projection.code_); } this.toLonLat = function(_Point) { return ol.proj.transform(_Point, GA_App.GA_Map.main_projection.code_, 'EPSG:4326'); } //지도 중심좌표 this.getCenter = function() { var _Center = GA_App.map.getView().getCenter(); _Center = Coord_transformPoint(_Center, GA_App.GA_Map.main_projection.code_, 'EPSG:4326'); return _Center; } //지도 줌 this.getZoom = function() { var _Zoom = GA_App.map.getView().getZoom(); if (GA_App.GA_Map.main_projection.code_ == 'EPSG:5181') { _Zoom = _Zoom + 5; } return _Zoom; } |
|