Android高德地图加载WMS服务应用实践
2017-12-14 13:48
921 查看
效果图(灰色两块为自定义瓦片):
需求:在Android高德地图上需要加载wms服务,用于显示自己绘制的瓦片地图。
由于需要在指定的位置添加一小块瓦片地图,所以在制作瓦片地图时需要参照高德地图底图作为参照进行图形绘制,但是因为网上没有找到具体可以参考的高德地图底图,本文采用天地图作为参照地图进行绘制,绘制后再通过经纬度坐标转换为高德地图对应的经纬度(网上有对应的转换代码)。
1、在ArcGis10.2中绘制瓦片地图保存为shapefile文件格式
本文采用ArcGis10.2进行瓦片地图的绘制,绘制前需要设置投影坐标系为EPSG:3857即墨卡托投影坐标系(900913),高德地图也正是采用此坐标系统,本地采用 “聚合天地图DOM瓦片地图服务http://www.scgis.net.cn/imap/iMapServer/defaultRest/services/newtianditudom/WMS”作为底图在其上进行绘制并导出shapefile文件。
绘制后的图形如下:
2、通过GeoServer加载shapefile文件并发布wms服务。
关于部署GeoServer.war这个步骤请自行百度,图中展示了发布wms的几个关键步骤:
完成上面几个步骤后就发布好了wms服务,地址为:http://localhost:8088/geoserver/hbgeo/wms?service=WMS&version=1.1.0&request=GetMap&layers=hbgeo:New_Shapefile2&
styles=&bbox=1.0842895202208204E7,4378002.325541817,1.1215106468992202E7,4638208.485151819
&width=768&height=536&srs=EPSG:3857&format=application/openlayers
注意此处地址对于android开发我们只需要精简一下参数就可以了,bbox的值去掉(投影范围有专门的计算方法往文章后面看),format需要改为image%2Fpng(即瓦片.png图片格式),width/height默认为256也可以去掉,最后得到的地址为:
http://192.168.58.226:8088/geoserver/hbgeo/wms?LAYERS=hbgeo:New_Shapefile2&FORMAT=image%2Fpng
&TRANSPARENT=TRUE&SERVICE=WMS&VERSION=1.1.1
&REQUEST=GetMap&STYLES=&SRS=EPSG:3857&BBOX=
到此为止wms服务地址已经准备好了,接下来只需要调用高德地图SDK中加载瓦片地图的方法即可,其中涉及到投影坐标的范围即bbox计算。
3、调用高德地图sdk加载瓦片地址
对于坐标系及瓦片地图加载原理可以参看里面的章节:http://weilin.me/ol3-primer/ch05/05-03.html
bbox覆盖范围求解:
请参考https://github.com/yxj1990/eye/wiki/%E5%85%B3%E4%BA%8E%E9%AB%98%E5%BE%B7API%
E5%8A%A0%E8%BD%BDwms%E5%9C%B0%E5%9B%BE%E6%9C%8D%E5%8A%A1%E5%9D%90%E6%A0%87
%E5%81%8F%E7%A7%BB%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88
思路: (1)在墨卡托投影系中先根据行列号求出瓦片的范围(米); (2)将瓦片范围转换为度; (3)利用高德api转换工具求出正常坐标和高德坐标的差; (4)在(2)的坐标加上差值得到正确坐标,即可获取到正确的瓦片。
调用高德地图sdk加载WMS服务地址核心片段:
需求:在Android高德地图上需要加载wms服务,用于显示自己绘制的瓦片地图。
由于需要在指定的位置添加一小块瓦片地图,所以在制作瓦片地图时需要参照高德地图底图作为参照进行图形绘制,但是因为网上没有找到具体可以参考的高德地图底图,本文采用天地图作为参照地图进行绘制,绘制后再通过经纬度坐标转换为高德地图对应的经纬度(网上有对应的转换代码)。
1、在ArcGis10.2中绘制瓦片地图保存为shapefile文件格式
本文采用ArcGis10.2进行瓦片地图的绘制,绘制前需要设置投影坐标系为EPSG:3857即墨卡托投影坐标系(900913),高德地图也正是采用此坐标系统,本地采用 “聚合天地图DOM瓦片地图服务http://www.scgis.net.cn/imap/iMapServer/defaultRest/services/newtianditudom/WMS”作为底图在其上进行绘制并导出shapefile文件。
绘制后的图形如下:
2、通过GeoServer加载shapefile文件并发布wms服务。
关于部署GeoServer.war这个步骤请自行百度,图中展示了发布wms的几个关键步骤:
完成上面几个步骤后就发布好了wms服务,地址为:http://localhost:8088/geoserver/hbgeo/wms?service=WMS&version=1.1.0&request=GetMap&layers=hbgeo:New_Shapefile2&
styles=&bbox=1.0842895202208204E7,4378002.325541817,1.1215106468992202E7,4638208.485151819
&width=768&height=536&srs=EPSG:3857&format=application/openlayers
注意此处地址对于android开发我们只需要精简一下参数就可以了,bbox的值去掉(投影范围有专门的计算方法往文章后面看),format需要改为image%2Fpng(即瓦片.png图片格式),width/height默认为256也可以去掉,最后得到的地址为:
http://192.168.58.226:8088/geoserver/hbgeo/wms?LAYERS=hbgeo:New_Shapefile2&FORMAT=image%2Fpng
&TRANSPARENT=TRUE&SERVICE=WMS&VERSION=1.1.1
&REQUEST=GetMap&STYLES=&SRS=EPSG:3857&BBOX=
到此为止wms服务地址已经准备好了,接下来只需要调用高德地图SDK中加载瓦片地图的方法即可,其中涉及到投影坐标的范围即bbox计算。
3、调用高德地图sdk加载瓦片地址
对于坐标系及瓦片地图加载原理可以参看里面的章节:http://weilin.me/ol3-primer/ch05/05-03.html
bbox覆盖范围求解:
请参考https://github.com/yxj1990/eye/wiki/%E5%85%B3%E4%BA%8E%E9%AB%98%E5%BE%B7API%
E5%8A%A0%E8%BD%BDwms%E5%9C%B0%E5%9B%BE%E6%9C%8D%E5%8A%A1%E5%9D%90%E6%A0%87
%E5%81%8F%E7%A7%BB%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88
思路: (1)在墨卡托投影系中先根据行列号求出瓦片的范围(米); (2)将瓦片范围转换为度; (3)利用高德api转换工具求出正常坐标和高德坐标的差; (4)在(2)的坐标加上差值得到正确坐标,即可获取到正确的瓦片。
调用高德地图sdk加载WMS服务地址核心片段:
TileOverlay scopeTileOverlay; int titleSize = 256; double initialResolution = 156543.03392804062;//2*Math.PI*6378137/titleSize;// double originShift = 20037508.342789244;//2*Math.PI*6378137/2.0;// String url = ""; /** * 添加wms图层 */ protected void addScope() { url = "http://192.168.58.226:8088/geoserver/hbgeo/wms?LAYERS=hbgeo:New_Shapefile2&FORMAT=image%2Fpng&TRANSPARENT=TRUE&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&SRS=EPSG:3857&BBOX="; TileProvider tileProvider = new UrlTileProvider(256, 256) { @Override public URL getTileUrl(int x, int y, int zoom) { try { System.out.println(x + "/" + y + "/" + zoom + "=====>" + url + TitleBounds(x, y, zoom)); return new URL(url + TitleBounds(x, y, zoom)); } catch (MalformedURLException e) { e.printStackTrace(); } return null; } }; if (tileProvider != null) { scopeTileOverlay = aMap.addTileOverlay(new TileOverlayOptions() .tileProvider(tileProvider) .diskCacheDir("/storage/amap/cache").diskCacheEnabled(true) .diskCacheSize(100)); } } /** * 根据像素、等级算出坐标 * * @param p * @param zoom * @return */ private double Pixels2Meters(int p, int zoom) { return p * Resolution(zoom) - originShift; } /** * 根据瓦片的x/y等级返回瓦片范围 * * @param tx * @param ty * @param zoom * @return */ private String TitleBounds(int tx, int ty, int zoom) { double minX = Pixels2Meters(tx * titleSize, zoom); double maxY = -Pixels2Meters(ty * titleSize, zoom); double maxX = Pixels2Meters((tx + 1) * titleSize, zoom); double minY = -Pixels2Meters((ty + 1) * titleSize, zoom); //转换成经纬度 minX = Meters2Lon(minX); minY = Meters2Lat(minY); maxX = Meters2Lon(maxX); maxY = Meters2Lat(maxY); //经纬度转换米 // minX=Lon2Meter(minX); // minY=Lat2Meter(minY); // maxX=Lon2Meter(maxX); // maxY=Lat2Meter(maxY); //坐标转换工具类构造方法 GPS( WGS-84) 转 为高德地图需要的坐标 CoordinateConverter converter = new CoordinateConverter(this); converter.from(CoordinateConverter.CoordType.GPS); converter.coord(new LatLng(minY, minX)); LatLng min = converter.convert(); converter.coord(new LatLng(maxY, maxX)); LatLng max = converter.convert(); minX = Lon2Meter(-min.longitude + 2 * minX); minY = Lat2Meter(-min.latitude + 2 * minY); maxX = Lon2Meter(-max.longitude + 2 * maxX); maxY = Lat2Meter(-max.latitude + 2 * maxY); return Double.toString(minX) + "," + Double.toString(minY) + "," + Double.toString(maxX) + "," + Double.toString(maxY) + "&WIDTH=256&HEIGHT=256"; } /** * 计算分辨率 * * @param zoom * @return */ private double Resolution(int zoom) { return initialResolution / (Math.pow(2, zoom)); } /** * X米转经纬度 */ private double Meters2Lon(double mx) { double lon = (mx / originShift) * 180.0; return lon; } /** * Y米转经纬度 */ private double Meters2Lat(double my) { double lat = (my / originShift) * 180.0; lat = 180.0 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180.0)) - Math.PI / 2.0); return lat; } /** * X经纬度转米 */ private double Lon2Meter(double lon) { double mx = lon * originShift / 180.0; return mx; } /** * Y经纬度转米 */ private double Lat2Meter(double lat) { double my = Math.log(Math.tan((90 + lat) * Math.PI / 360.0)) / (Math.PI / 180.0 ); my = my * originShift / 180.0; return my; }
相关文章推荐
- Android 中使用地图加载wms服务(高德地图,谷歌地图,天地图)
- Android 7.1 GUI系统-窗口管理WMS-窗口动画、应用动画的加载(六)
- Android应用测试实战与调试实践第5章:测试Android服务组件
- Android 应用的动画实践--View Animation篇
- Android应用setContentView与LayoutInflater加载解析机制源码分析
- 关于打开Android应用多次点击重复加载数据的问题。
- Android-应用开发-广播和服务(八)
- android中对服务的应用管理 .
- Android 应用的动画实践--View Animation篇
- Android之后台服务判断本应用Activity是否处于栈顶
- 容器云最佳实践:Docker、微服务、应用容器化之Kubernetes实践
- SAE实践——创建新应用开启MySQL服务
- Android应用本地拒绝服务漏洞浅析
- Android动态资源加载原理和应用
- Android应用开发提高系列(5)——Android动态加载(下)——加载已安装APK中的类和资源
- Java设计模式之单例模式(Singleton)在Android系统服务中的应用
- Android中(Service )服务的最佳实践——后台执行的定时任务
- android 应用动态加载机制1
- Android中WebView在加载网页的时候,怎样应用本地的CSS效果?就是说怎样把本地的CSS嵌入到HTML中
- Android应用中MVP最佳实践