一、背景javascript
在離線環境下(局域網中)的GIS系統中如何使用地圖?這裏的地圖主要指的是地圖底圖,有了底圖切片數據,咱們就能夠看到地圖,在上面加上本身的業務數據圖層,進行相關操做。css
要在離線環境下看到GIS地圖,就要有底圖切片數據,地圖的底圖切片數據在必定時間內是不會變化的,可使用一些地圖下載器下載地圖切片,如這個地圖下載器。html
在CS系統中能夠基於GMap.Net來作,參考《百度谷歌離線地圖解決方案》。前端
下面介紹下Web系統如何使用GIS切片數據,開發web GIS系統。java
二、使用GeoWebCache發佈WMS服務node
Geowebcache是基於Java的Web開源項目,主要用於緩存各類WMS數據源的地圖瓦片,它實現了多種服務接口,包括WMS-C,WMTS,TMS,KML。git
Geowebcache做爲一個獨立的開源項目,在最近被Geosever的幾個版本所集成,主要是對發佈的WMS圖層創建緩存切片。github
服務發佈步驟:web
1)官網下載 geowebcache-1.8.0-war.zip,直接解壓獲得geowebcache.war文件,將該文件直接拷貝至tomcat目錄下的webapps下便可,啓動tomcat會對war包進行解壓。算法
2)修改geowebcache的配置文件geowebcache-core-context.xml。該文件在Tomcat的webapps\geowebcache\WEB-INF下,修改以下:
<bean id="gwcXmlConfig" class="org.geowebcache.config.XMLConfiguration"> <constructor-arg ref="gwcAppCtx" /> <!--<constructor-arg ref="gwcDefaultStorageFinder" />--> <constructor-arg value="D:\\GisMap\\" /> <!-- By default GWC will look for geowebcache.xml in {GEOWEBCACHE_CACHE_DIR}, if not found will look at GEOSEVER_DATA_DIR/gwc/ alternatively you can specify an absolute or relative path to a directory by replacing the gwcDefaultStorageFinder constructor argument above by the directory path, like constructor-arg value="/etc/geowebcache" --> <property name="template" value="/geowebcache.xml"> <description>Set the location of the template configuration file to copy over to the cache directory if one doesn't already exist. </description> </property> </bean>
修改gwcXmlConfig實例化時使用固定路徑,該路徑能夠爲任意新建路徑文件夾。Geowebcache啓動以後會檢查此文件夾下是否存在gewebcache.xml文件,若是不存在則按模板新創建並讀取使用,若是存在則直接讀取使用。
3)修改第2步中的gewebcache.xml文件:
<layers> <arcgisLayer> <name>ARCGIS-Demo</name> <tilingScheme>D:\\GisMap\\Layer\\conf.xml</tilingScheme> <tileCachePath>D:\\GisMap\\Layer\\_alllayers</tileCachePath> </arcgisLayer> </layers>
在layers節點裏添加arcgisLayer節點(默認生成的gewebcache.xml的layers節點有許多其餘冗餘數據,可刪除可保留)。Name節點表示待添加圖層的名稱(這裏配置爲ARCGIS-Demo),titlingscheme節點爲conf.xml文件的路徑,tileCachePath爲瓦片數據的路徑。
4)瓦片地圖的準備
其中conf.xml爲配置文件,conf.cdi爲顯示區域約束文件,_alllayers文件夾下則存放了切片數據,Status.gdb爲切片狀態狀況記錄(可直接刪除)。
經過瓦片下載器下載瓦片地圖,而後生成的切片數據_alllayers文件夾:
L01-L10表示地圖縮放級數,按照ArcGIS切片目錄組織,切片命名規則也和ArcGIS切片數據命名規則一致。(conf.xml、conf.cdi和_alllayers在同級目錄)。
5)啓動tomcat,繼而啓動Geowebcache服務,瀏覽器訪問 localhost:8080/geowebcache,若是一切正確的話能夠看到下面的頁面
該頁面簡單說明了Geowebcache的一些狀況。
點擊「A list of all the layers and automatic demos」鏈接能夠看到下面:
該頁面顯示了geowebcache.xml配置的圖層信息。圖中能夠看到只配置了一個名字爲ARCGIS-Demo的圖層,使用的EPSG3857座標系,發佈的圖片格式爲png格式,點擊png連接便可看到瓦片地圖。
這裏地圖顯示的級別和座標系配置都來自conf.xml文件。這裏的前端js使用的是Openlayers。查看網頁源碼:
<html xmlns="http://www.w3.org/1999/xhtml"><head> <meta http-equiv="imagetoolbar" content="no"> <title>ARCGIS-Demo EPSG:3857_ARCGIS-Demo image/png</title> <style type="text/css"> body { font-family: sans-serif; font-weight: bold; font-size: .8em; } body { border: 0px; margin: 0px; padding: 0px; } #map { width: 85%; height: 85%; border: 0px; padding: 0px; } </style> <script src="../openlayers/OpenLayers.js"></script> <script type="text/javascript"> var map, demolayer; // sets the chosen modifiable parameter function setParam(name, value){ str = "demolayer.mergeNewParams({" + name + ": '" + value + "'})" // alert(str); eval(str); } OpenLayers.DOTS_PER_INCH = 96.0; OpenLayers.Util.onImageLoadErrorColor = 'transparent'; function init(){ var mapOptions = { resolutions: [156543.033928, 78271.5169639999, 39135.7584820001, 19567.8792409999, 9783.93962049996, 4891.96981024998, 2445.98490512499, 1222.99245256249, 611.49622628138, 305.748113140558, 152.874056570411, 76.4370282850732, 38.2185141425366, 19.1092570712683, 9.55462853563415, 4.77731426794937, 2.38865713397468, 1.19432856685505, 0.597164283559817, 0.298582141647617], projection: new OpenLayers.Projection('EPSG:3857'), maxExtent: new OpenLayers.Bounds(-20037508.342787,-20037508.342780996,20037508.342780996,20037508.342787), units: "meters", controls: [] }; map = new OpenLayers.Map('map', mapOptions ); map.addControl(new OpenLayers.Control.PanZoomBar({ position: new OpenLayers.Pixel(2, 15) })); map.addControl(new OpenLayers.Control.Navigation()); map.addControl(new OpenLayers.Control.Scale($('scale'))); map.addControl(new OpenLayers.Control.MousePosition({element: $('location')})); demolayer = new OpenLayers.Layer.WMS( "ARCGIS-Demo","../service/wms", {layers: 'ARCGIS-Demo', format: 'image/png' }, { tileSize: new OpenLayers.Size(256,256), tileOrigin: new OpenLayers.LonLat(-2.0037508342787E7, 2.0037508342787E7)}); map.addLayer(demolayer); map.zoomToExtent(new OpenLayers.Bounds(-20037497.2108,-19929239.113399997,20037497.2108,18379686.9965)); // The following is just for GetFeatureInfo, which is not cached. Most people do not need this map.events.register('click', map, function (e) { document.getElementById('nodelist').innerHTML = "Loading... please wait..."; var params = { REQUEST: "GetFeatureInfo", EXCEPTIONS: "application/vnd.ogc.se_xml", BBOX: map.getExtent().toBBOX(), X: e.xy.x, Y: e.xy.y, INFO_FORMAT: 'text/html', QUERY_LAYERS: map.layers[0].params.LAYERS, FEATURE_COUNT: 50, Layers: 'ARCGIS-Demo', Styles: '', Srs: 'EPSG:3857', WIDTH: map.size.w, HEIGHT: map.size.h, format: "image/png" }; OpenLayers.loadURL("../service/wms", params, this, setHTML, setHTML); OpenLayers.Event.stop(e); }); } function setHTML(response){ document.getElementById('nodelist').innerHTML = response.responseText; }; </script> </head> <body onload="init()"> <div id="params"></div> <div id="map"></div> <div id="nodelist"></div> </body> </html>
我的比較喜歡leaflet這個GIS javascript庫,使用leaflet加載GeoWebCache發佈的這個服務:
<!DOCTYPE html> <html> <head> <title>Leaflet - Offline Demo</title> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" /> <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script> </head> <body> <div id="map" style="height:100vh;" ></div> <script type="text/javascript"> var mapCenter = new L.LatLng(32.1280, 118.7742); //南京 var map = new L.Map('map', { center : mapCenter, zoom : 4 }); var wmsLayer = L.tileLayer.wms("http://localhost:8080/geowebcache/service/wms", { layers: 'ARCGIS-Demo', format: 'image/png' }); wmsLayer.addTo(map); var marker = new L.Marker(mapCenter); map.addLayer(marker); marker.bindPopup("<p>Hello! ;}</p>").openPopup(); </script> </body> </html>
三、使用自定義的Http服務
GeowebCache本質上就是個Http服務,經過請求參數獲取配置文件中的路徑中的切片數據,返回給請求方。
咱們能夠本身寫個獨立的Http服務,從數據庫中讀取切片數據返回給請求方。
切片請求地址相似:http://localhost:8899/1818940751/{z}/{x}/{y}
其中「1818940751」是下載器下載的地圖類型,z/x/y分別是zoom和地圖切片行列號。
前端js使用leaflet加載:
var amapNormalUrl = 'http://localhost:8899/788865972/{z}/{x}/{y}'; var amapNormalLayer = new L.TileLayer(amapNormalUrl, { minZoom : 1, maxZoom : 18, attribution : '高德普通地圖' }); var mapCenter = new L.LatLng(32.1280, 118.7742); //南京 var map = new L.Map('map', { center : mapCenter, zoom : 9, minZoom: 1, maxZoom: 18, layers : [ amapNormalLayer ] });
前端js能夠自定義投影Projection算法,而國內google地圖、高德地圖和騰訊地圖都是標準的墨卡託投影,能夠直接用leaflet加載。
配合一些畫圖插件,再配合一些後臺POI檢索服務,如:
則能作出以下效果:
總結:介紹瞭如何使用下載的離線切片數據在局域網環境下發布Web GIS地圖服務,前端配合使用一些js插件,實現web下空間數據的檢索。
在Github上開源了一些代碼,包含自定義的Http地圖服務,和一個簡單的頁面WebGISDemo。
地址:https://github.com/luxiaoxun/Code4Java
附件:
<?xml version="1.0" encoding="utf-8" ?> <EnvelopeN xsi:type='typens:EnvelopeN' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:typens='http://www.esri.com/schemas/ArcGIS/10.1'> <XMin>-20037497.2108</XMin> <YMin>-19929239.113399997</YMin> <XMax>20037497.2108</XMax> <YMax>18379686.9965</YMax> </EnvelopeN>
<?xml version="1.0" encoding="utf-8"?> <CacheInfo xsi:type="typens:CacheInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:typens="http://www.esri.com/schemas/ArcGIS/10.1"> <TileCacheInfo xsi:type="typens:TileCacheInfo"> <SpatialReference xsi:type="typens:ProjectedCoordinateSystem"> <WKT>PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG",3857]]</WKT> <XOrigin>-20037700</XOrigin> <YOrigin>-30241100</YOrigin> <XYScale>148923141.92838538</XYScale> <ZOrigin>-100000</ZOrigin> <ZScale>10000</ZScale> <MOrigin>-100000</MOrigin> <MScale>10000</MScale> <XYTolerance>0.001</XYTolerance> <ZTolerance>0.001</ZTolerance> <MTolerance>0.001</MTolerance> <HighPrecision>true</HighPrecision> <WKID>3857</WKID> </SpatialReference> <TileOrigin xsi:type="typens:PointN"> <X>-20037508.342787001</X> <Y>20037508.342787001</Y> </TileOrigin> <TileCols>256</TileCols> <TileRows>256</TileRows> <DPI>96</DPI> <LODInfos xsi:type="typens:ArrayOfLODInfo"> <LODInfo xsi:type="typens:LODInfo"> <LevelID>0</LevelID> <Scale>591657527.591555</Scale> <Resolution>156543.03392799999</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>1</LevelID> <Scale>295828763.79577702</Scale> <Resolution>78271.516963999893</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>2</LevelID> <Scale>147914381.89788899</Scale> <Resolution>39135.758482000099</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>3</LevelID> <Scale>73957190.948944002</Scale> <Resolution>19567.879240999901</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>4</LevelID> <Scale>36978595.474472001</Scale> <Resolution>9783.9396204999593</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>5</LevelID> <Scale>18489297.737236001</Scale> <Resolution>4891.9698102499797</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>6</LevelID> <Scale>9244648.8686180003</Scale> <Resolution>2445.9849051249898</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>7</LevelID> <Scale>4622324.4343090001</Scale> <Resolution>1222.9924525624899</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>8</LevelID> <Scale>2311162.2171550002</Scale> <Resolution>611.49622628138002</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>9</LevelID> <Scale>1155581.108577</Scale> <Resolution>305.74811314055802</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>10</LevelID> <Scale>577790.55428899999</Scale> <Resolution>152.874056570411</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>11</LevelID> <Scale>288895.27714399999</Scale> <Resolution>76.437028285073197</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>12</LevelID> <Scale>144447.638572</Scale> <Resolution>38.218514142536598</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>13</LevelID> <Scale>72223.819285999998</Scale> <Resolution>19.109257071268299</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>14</LevelID> <Scale>36111.909642999999</Scale> <Resolution>9.5546285356341496</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>15</LevelID> <Scale>18055.954822</Scale> <Resolution>4.7773142679493699</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>16</LevelID> <Scale>9027.9774109999998</Scale> <Resolution>2.38865713397468</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>17</LevelID> <Scale>4513.9887049999998</Scale> <Resolution>1.1943285668550501</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>18</LevelID> <Scale>2256.994353</Scale> <Resolution>0.59716428355981699</Resolution> </LODInfo> <LODInfo xsi:type="typens:LODInfo"> <LevelID>19</LevelID> <Scale>1128.4971760000001</Scale> <Resolution>0.29858214164761698</Resolution> </LODInfo> </LODInfos> </TileCacheInfo> <TileImageInfo xsi:type="typens:TileImageInfo"> <CacheTileFormat>PNG</CacheTileFormat> <CompressionQuality>0</CompressionQuality> <Antialiasing>false</Antialiasing> </TileImageInfo> <CacheStorageInfo xsi:type="typens:CacheStorageInfo"> <StorageFormat>esriMapCacheStorageModeExploded</StorageFormat> <PacketSize>0</PacketSize> </CacheStorageInfo> </CacheInfo>
參考:
http://leafletjs.com/
http://leafletjs.com/examples/quick-start/
http://www.cnblogs.com/luxiaoxun/p/4454880.html
http://www.cnblogs.com/luxiaoxun/p/5020247.html