腾讯地图SDK加载、删除Geoserver瓦片图层

近日项目需要,需要使用腾讯地图SDK进行二次开发,加载Geoserver发布的影像图层。现在就将加载过程记录一下。注:以腾讯地图官方文档为参考。
最终的效果:
腾讯地图SDK加载、删除Geoserver瓦片图层_第1张图片

首先需要在腾讯地图官网申请KEY值,申请过程请看官方文档中的介绍。加载图层的主要文档在Android地图SDK文档中“自定义瓦片层”章节。

首先准备一个实体类和一个工具类。
PositionModel:

public class PositionModel {
	private double wgLat;
	private double wgLon;
	public PositionModel(double wgLat, double wgLon) {
		setWgLat(wgLat);
		setWgLon(wgLon);
	}
	public double getWgLat() {
		return wgLat;
	}
	public void setWgLat(double wgLat) {
		this.wgLat = wgLat;
	}
	public double getWgLon() {
		return wgLon;
	}
	public void setWgLon(double wgLon) {
		this.wgLon = wgLon;
	}
	@Override
	public String toString() {
		return wgLat + "," + wgLon;
	}
}

PositionUtil:

public class PositionUtil {

     public static final String BAIDU_LBS_TYPE = "bd09ll";

     public static double pi = 3.1415926535897932384626;
     public static double a = 6378245.0;
     public static double ee = 0.00669342162296594323;


     /**
      * * 火星坐标系 (GCJ-02) to 84 * * @param longitude * @param latitude * @return
      */
     public static PositionModel gcj_To_Gps84(double lat, double lon) {
         PositionModel gps = transform(lat, lon);
         double lontitude = lon * 2 - gps.getWgLon();
         double latitude = lat * 2 - gps.getWgLat();
         return new PositionModel(latitude, lontitude);
     }


     public static boolean outOfChina(double lat, double lon) {
         if (lon < 72.004 || lon > 137.8347)
             return true;
         if (lat < 0.8293 || lat > 55.8271)
             return true;
         return false;
     }

     public static PositionModel transform(double lat, double lon) {
         if (outOfChina(lat, lon)) {
             return new PositionModel(lat, lon);
         }
         double dLat = transformLat(lon - 105.0, lat - 35.0);
         double dLon = transformLon(lon - 105.0, lat - 35.0);
         double radLat = lat / 180.0 * pi;
         double magic = Math.sin(radLat);
         magic = 1 - ee * magic * magic;
         double sqrtMagic = Math.sqrt(magic);
         dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
         dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
         double mgLat = lat + dLat;
         double mgLon = lon + dLon;
         return new PositionModel(mgLat, mgLon);
     }

     public static double transformLat(double x, double y) {
         double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
                 + 0.2 * Math.sqrt(Math.abs(x));
         ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
         ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
         ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
         return ret;
     }

     public static double transformLon(double x, double y) {
         double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
                 * Math.sqrt(Math.abs(x));
         ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
         ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
         ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
                 * pi)) * 2.0 / 3.0;
         return ret;
     }
 }

接下来写一个MyTileProvider类继承腾讯地图的UrlTileProvider类。

public class MyTileProvider extends UrlTileProvider {

    private String mRootUrl;
    //默认瓦片大小
    private static int titleSize = 256;//a=6378137±2(m)
    //基本参数
    private final double initialResolution= 156543.03392804062;//2*Math.PI*6378137/titleSize;
    private final double originShift      = 20037508.342789244;//2*Math.PI*6378137/2.0; 周长的一半

    private final double HALF_PI = Math.PI / 2.0;
    private final double RAD_PER_DEGREE = Math.PI / 180.0;
    private final double HALF_RAD_PER_DEGREE = Math.PI / 360.0;
    private final double METER_PER_DEGREE = originShift / 180.0;//一度多少米
    private final double DEGREE_PER_METER = 180.0 / originShift;//一米多少度

    public MyTileProvider(){
        super(titleSize,titleSize);
        //地址写自己的服务地址
        mRootUrl ="http://xxx.xxx.xx.xx:xxxx/geoserver/ksh/wms?service=WMS&version=1.1.0&request=GetMap&layers=ksh:xmh-2020-1m&styles=&width=650&height=768&srs=EPSG:3857&TRANSPARENT=TRUE&format=image%2Fpng&bbox=";//png
    }

    public MyTileProvider(int i, int i1) {
        super(i, i1);
    }


    @Override
    public URL getTileUrl(int x, int y, int zoom) {

        try {
            String url = mRootUrl + TitleBounds(x, y, zoom);
            URL l=new URL(url);
            LogUtils.e("mRootUrl:"+l);
            return new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @Date:         2020/10/14 15:20
     * @Author:       zhj
     * @Description:  检查当前瓦片地址是否有数据
     */
    private boolean checkTileExists(int x, int y, int zoom) {
        int minZoom = 12;
        int maxZoom = 16;

        if ((zoom < minZoom || zoom > maxZoom)) {
            return false;
        }
        return true;
    }

    /**
     * 根据像素、等级算出坐标
     *
     * @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);
        PositionModel position1 = PositionUtil.gcj_To_Gps84(minY,minX);
        minX = position1.getWgLon();
        minY = position1.getWgLat();
        PositionModel position2 = PositionUtil.gcj_To_Gps84(maxY,maxX);
        maxX = position2.getWgLon();
        maxY = position2.getWgLat();

        minX=Lon2Meter(minX);
        minY=Lat2Meter(minY);
        maxX=Lon2Meter(maxX);
        maxY=Lat2Meter(maxY);

        return minX + "," + Double.toString(minY) + "," + Double.toString(maxX) + "," + Double.toString(maxY);
    }
    /**
     * 计算分辨率
     *
     * @param zoom
     * @return
     */
    private double Resolution(int zoom) {
        return initialResolution / (Math.pow(2, zoom));
    }

    /**
     * X米转经纬度
     */
    private double Meters2Lon(double mx) {
        double lon = mx * DEGREE_PER_METER;
        return lon;
    }
    /**
     * Y米转经纬度
     */
    private double Meters2Lat(double my) {
        double lat = my * DEGREE_PER_METER;
        lat = 180.0 / Math.PI * (2 * Math.atan(Math.exp(lat * RAD_PER_DEGREE)) - HALF_PI);
        return lat;
    }
    /**
     * X经纬度转米
     */
    private double Lon2Meter(double lon) {
        double mx = lon * METER_PER_DEGREE;
        return mx;
    }
    /**
     * Y经纬度转米
     */
    private double Lat2Meter(double lat) {
        double my = Math.log(Math.tan((90 + lat) * HALF_RAD_PER_DEGREE)) / (RAD_PER_DEGREE);
        my = my * METER_PER_DEGREE;
        return my;
    }
}

注意填写自己服务地址的时候,有可能需要对URL路径做些改变。
①加载的图层服务需要是png格式;
②注意坐标系需要改成EPSG:3857,其他坐标系加载不上;
③如果加载的瓦片图层除了需要的影像外,其他的部分都会白色的瓦片,这就需要在URL中添加“TRANSPARENT=TRUE”;
④需要把URL中原来bbox=之后的坐标值全删掉,并且剪切“bbox=”到URL的最后,以为在上述程序中将原有的坐标转化成需要的坐标,然后拼接到bbox后面了。
添加瓦片图层到地图上。

public TileOverlay addMyTileProvider(TencentMap map){
        MyTileProvider provider = new MyTileProvider();
        options = new TileOverlayOptions();
        options.diskCacheDir("/map/")                  //设置瓦片缓存目录
                .betterQuality(true)                     //设置瓦片图片质量
                .zIndex(10)                              //设置瓦片压盖级别
                .tileProvider(provider);
        tileOverlay=map.addTileOverlay(options);
        return tileOverlay;
    }

注意需要定义titleOverlay。

private TileOverlay tileOverlay;
private TileOverlayOptions options;

然后调用该方法即可。

addMyTileProvider(tencentMap);

tencentMap是获取的腾讯地图控件。

TencentMap tencentMap=mainMap.getMap();

最后记录一下,怎么删除图层。
直接使用这个方法即可。

tileOverlay.remove();

注:titleOverlay需要先获取值,即添加瓦片方法中的tileOverlay=map.addTileOverlay(options)。
然后才可以调用该方法。

你可能感兴趣的:(学习教程,Android,android,移动开发,腾讯)