[Leaflet] WMS and TMS




 - 'Web Map Service'의 약자인 WMS는 전문적인 GIS 소프트웨어로 널리 사용된다. (비 GIS사용자는 거의 사용하지 않는다.)
 - 이 형식은 지도 타일과 비슷하지만 더 일반적이며, 웹 지도에서 사용하기에는 적합하지 않다.
 - WMS 이미지는 모서리의 좌표에 의해 정의된다. (Leaflet이 내부적으로 수행하는 계산)

 - TMS는 'Tiled Map Service'를 의미하여 웹지도에 보다 초점을 맞춘 지도 타일링 표준으로, Leaflet이 L.TileLayer에서 기대하는 지도타일과 매우 유사하다.

 - WMTS는 'Web Map Tile Service'를 위한 표준 프로토콜로 L.TileLayer에서 직접 사용할 수 있는 맵 타일을 제공한다.


WMS in Leaflet

 - 누군가 WMS 서비스를 시작하면 해당 서비스는 GetCapabilities 라는 문서에 연결된 가능성이 크다.
 - 이 예제에서는 Mundialis가 제공하는 WMS를 사용한다.
 - 서비스의 기능은 다음 URL에 있다.
 - http://ows.mundialis.de/services/service?request=GetCapabilities

 - Leaflet은 WMS GetCapabilities 문서를 이해하지 못한다.
 - 대신에 L.TileLayer.WMS 레이어를 만들고, 기본적인 WMS URL을 제공하고, 우리가 필요한 WMS옵션을 명시할 수 있다.
 - 기본 WMS URL은 다음과 같이 매개변수가 없는 간단한 GetCapabilities URL이다.
 - http://ows.mundialis.de/services/service?

 - 그리고 Leaflet 지도에서 사용하는 방법은 간단하다.

var map = L.map(mapDiv, mapOptions);
var wmsLayer = L.tileLayer.wms('http://ows.mundialis.de/services/service?', wmsOptions).addTo(map);

 - L.TileLayer.WMS 인스턴스에는 최소한 한가지 옵션이 필요하다. (layers)
 - Leaflet의 layer 개념과 WMS의 layer 개념이 다름에 주의가 필요하다.

 - WMS서버는 서비스에서 layers의 설정을 정의한다.
 - 이러한 내용은 GetCapabilities XML 문서에 정의되어 있지만, 대부분의 경우 지루하고 이해하기 어렵다.
 - 일반적으로 QGIS와 같은 소프트웨어를 사용하여 WMS서버에서 사용할 수 있는 layers를 확인하여 사용가능한 레이어 이름을 확인하는것이 좋다.


 - 우리는 Mundialis WMS가 TOPO-OSM-WMS라는 이름의 WMS 레이어를 베이스맵으로 하고 있음을 알 수 있다.
 - 아래의 코드를 통해 확인을 해보자.

<!DOCTYPE html>
<html>
<head>
<title>WMS example - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
html, body { height: 100%; margin: 0; }
#map { width: 600px; height: 400px; }
</style>
</head>
<body>
<div id='map'></div>
<script type="text/javascript">
var map = L.map('map', {
center: [-17, -67],
zoom: 3
});
var wmsLayer = L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'TOPO-OSM-WMS'
}).addTo(map);
</script>
</body>
</html>


SRTM30-Colored-Hillshade WMS layer 로하면 다음과 같다.

<!DOCTYPE html>
<html>
<head>
<title>WMS example - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
html, body { height: 100%; margin: 0; }
#map { width: 600px; height: 400px; }
</style>
</head>
<body>
<div id='map'></div>
<script type="text/javascript">
var map = L.map('map', {
center: [-17, -67],
zoom: 3
});
/**
* SRTM30-Colored-Hillshade WMS layer
*/
var wmsLayer = L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'SRTM30-Colored-Hillshade'
}).addTo(map);
</script>
</body>
</html>


 - layers 옵션은 쉼표로 구분된 layers 목록이다.
 - WMS 서비스가 여러개의 layers를 정의한경우, 지도 이미지 요청은 두개 이상의 layer를 참조할 수 있다.

 - 우리가 사용하는 WMS서버의 예로는 세계 지형을 보여주는 'TOPO-WMS' WMS layer와 지역의 이름을 보여주는 'OSM-Overlay-WMS' WMS layer가 있다.

 - WNS서버는 쉼표로 구분된 2레이어를 요청 시 하나의 이미지로 구성한다.

var topographyAndPlaces = L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'TOPO-WMS,OSM-Overlay-WMS'
}).addTo(map);


 - WMS서버에 하나의 이미지를 요청한다는 점에 유의해야한다.
 - 이것은 지형을 위해 L.TileLayer.WMS를 생성하고 장소를 위한 하나의 L.tileLayer.WMS를 생성해서 둘다 지도에 추가하는것과는 다르다.

 - 첫번째의 경우, 1개의 이미지요청을 하고 WMS서버가 이미지를 어떻게 구성할지 결정한다. (이미지를 서로 위에 올려놓음)
 - 두번째의 경우 두개의 이미지 요청을 하고, 웹브라우저의 Leaflet 코드가 어떻게 구성할지 결정한다.

 - layers control을 이용하여 결합하여 간단히 지도를 생성하면 어떻게 다른지 알 수 있다. (아래의 예제코드)
 - 'Topography, then places' 옵션을 선택 시 장소가 지역의 위로 올라오는 것을 볼 수 있다.
 - layers를 많이 요청 시 레이어를 구성하는 방법은 WMS서버에게 달려있다.

<!DOCTYPE html>
<html>
<head>
<title>WMS example - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
html, body { height: 100%; margin: 0; }
#map { width: 600px; height: 400px; }
</style>
</head>
<body>
<div id='map'></div>
<script type="text/javascript">
var map = L.map('map', {
center: [-17, -67],
zoom: 3
});
var basemaps = {
Topography: L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'TOPO-WMS'
}),
Places: L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'OSM-Overlay-WMS'
}),
'Topography, then places': L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'TOPO-WMS,OSM-Overlay-WMS'
}),
'Places, then topography': L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'OSM-Overlay-WMS,TOPO-WMS'
})
};
L.control.layers(basemaps, {}, {collapsed: false}).addTo(map);
basemaps.Topography.addTo(map);
</script>
</body>
</html>


WMS서비스의 GIS사용자를 위한 참고사항

 - GIS관점에서 보면 Leaflet의 WMS처리는 상당히 기본적이며 GetCapabilities / GetFeatureInfo / legend의 지원이 없다.

 - T.TileLayer.WMS는 추가적인 옵션이 있는데 Leaflet API Document에서 찾아볼 수 있다.
 - API Document에 기술되지 않은 모든 옵션은 getImage URL의 WMS서버로 전송된다.

 - 또한 Leaflet은 CRS:3857, CRS:3395 and CRS:4326 등 매우 적은수의 좌표시스템을 지원한다. (document의 L.CRS 참고)
 - WMS서비스가 해당 좌표계의 이미지를 제공하지 않는경우, Proj4Leaflet을 사용하여 Leaflet의 다른 좌표시스템을 사용해야 할 수 있다.
 - 그외에는 지도를 초기화 할때 올바를 CRS를 사용하면 모든 추가된 WMS layers는 사용가능하다.

<!DOCTYPE html>
<html>
<head>
<title>WMS example - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
html, body { height: 100%; margin: 0; }
#map { width: 600px; height: 400px; }
</style>
</head>
<body>
<div id='map'></div>
<script type="text/javascript">
var map = L.map('map', {
center: [0, 0],
zoom: 1,
crs: L.CRS.EPSG4326
});
var wmsLayer = L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'TOPO-OSM-WMS'
}).addTo(map);
</script>
</body>
</html>


TMS in Leaflet

 - Leaflet은 TMS서비스를 공식적으로 지원하지 않지만 tile 이름구조는 공통 L.TileLayer 이름체계와 유사하며 평범한 TMS서비스를 표시할 수 있다.

 - 아래와 같은 엔드포인트가 있는 TMS서버를 고려해보자.
 - http://base_url/tms/1.0.0

 - TMS 및 TMS 사양에 대한 MapCache 도움말을 확인하면 TMS의 지도 타일 URL이 다음과 같다.
 - http://base_url/tms/1.0.0/ {tileset} / {z} / {x} / {y} .png

 - L.TileLayer로 TMS서비스를 사용하려면, 사용가능한 tileset에 대해 기능문서를 체크하여 아래와 같은 base URL을 빌드할 수 있다. (우리의 경우 http://base_url/tms/1.0.0로 기본 엔드포인트가 같을때)
 - http://base_url/tms/1.0.0/{example_layer}@png/{z}/{x}/{y}.png

 - 아래와 같이 레이어를 인스턴스화 할때 tms:true 옵션을 사용해라.

var tms_example = L.tileLayer('http://base_url/tms/1.0.0/example_layer@png/{z}/{x}/{y}.png', {
tms: true
}).addTo(map);


 - Leaflet 1.0의 새로운 기능은 tms:true 옵션 대신 URL에 {-y}를 사용할 수 있다.

var layer = L.tileLayer('http://base_url/tms/1.0.0/tileset/{z}/{x}/{-y}.png');


 - (Leaflet 0.7에서) tms:true 옵션이나 (Leaflet 1.0에서) {-y}는 일반적인 L.TileLayer 좌표 원점이 왼쪽 상단 모서리에 있으므로 Y좌표가 내려가기 때문에 필요한 옵션과 기능이다.
 - TMS에서 좌표의 원점은 왼쪽 하단 모서리가 되어 Y좌표가 위로 올라가게 된다.

 - Y좌표와 tilesets의 발견의 차이 외에도 TMS서비스는 L.TileLayer가 기대하는 방법으로 정확하게 tile을 제공한다.


참조: https://leafletjs.com/examples/wms/wms.html


댓글