美文网首页
百度地图如何成功加载 GeoServer 的 WMS 图层

百度地图如何成功加载 GeoServer 的 WMS 图层

作者: Edwinpanzzz | 来源:发表于2021-06-29 11:24 被阅读0次

    首先说一下我的需求,需要将百度地图绘制的相交圆做并集处理(如下图所示),可能是我比较 low,并没有在百度地图的 API 上找到这样的方法,如果有哪位大佬知道怎么使用百度地图直接实现,或者更简单的办法,请留言告诉我,不胜感激。

    图片

    然后,我就想到了根据坐标点在 arcgis 上先处理,生成 shape 文件后,通过百度地图的 叠加自定义图层 案例,结合网上的教程,成功实现。让人操蛋的是,墙内的博客都是一个抄一个的,当你遇到问题的时候,百度一下你能发现一串博客内容都是一样的,就像我百度 百度地图加载 wms 你都能找到这段代码,不能说毫无关联,只能说一模一样。

    tileLayer.getTilesUrl = function(tileCoord, zoom) {
    
        var x = tileCoord.x;
        var y = tileCoord.y;
        //console.log("X: " + x + " Y : " + y + " Z: " + zoom);
    
        //下面这一段代码和上面的代码效果一模一样!!!利用的公瑾提供的一个js实现坐标转换,地址为:https://github.com/FreeGIS/coordtransform
        var res = resolutions[zoom];
        var tileWidth = 256;
        var minx = x * tileWidth * res;
        var miny = y * tileWidth * res;
        var maxx = (x + 1) * tileWidth * res;
        var maxy = (y + 1) * tileWidth * res;
    
        var bottomLeft = coordtransform.BD_MKT2WGS(minx, miny); //百度墨卡托坐标-》百度经纬度坐标
        var topRight = coordtransform.BD_MKT2WGS(maxx, maxy);
        bottomLeft = coordtransform.BD2WGS(bottomLeft[0], bottomLeft[1])
        topRight = coordtransform.BD2WGS(topRight[0], topRight[1])
        var bbox2 = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]; //计算出bbox
        console.log(bbox2);
        //根据geoserver WMS服务的规则设置URL
        // 
        var url = 'http://localhost:2000/geoserver/huangong/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&tiled=true&STYLES&LAYERS=huangong%3Apng-qingping&tilesOrigin=104.069%2C31.489&WIDTH=256&HEIGHT=256&SRS=EPSG%3A4326&BBOX=' +
            //var url = 'http://localhost:8080/geoserver/fsum/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image/png&LAYERS=fsum:T_UM_MAP_DISTRICT_GEOMETRY&TRANSPARENT=true&tiled=true&SRS=EPSG:4326&WIDTH=256&HEIGHT=256&BBOX=' +
            bbox2.join(',');
    
        //console.log(bbox.join(','));
        return url;
    }
    

    其中使用到的 coordtransform.BD_MKT2WGS(lon, lat);coordtransform.BD2WGS(lon, lat) 这两个方法就是没有人贴出来,兴致冲冲的以为自己即将实现图层加载的时候发现,没有这两个方法,难过吧。
    好了,废话就说到这里,下面讲讲我是怎么实现的。

    将图层发布到 GeoServer

    EPSG:3857 Pseudo Mercator 是用于在 Google 地图,OpenStreetMap 等呈现地图的投影坐标系,像国内的互联网地图如百度、高德、腾讯也是使用的这一坐标系。因此,我的操作是根据坐标,使用 arcgis 绘制出半径为 500 的缓冲区,采用 EPSG:3857 坐标系保存成 Shape 文件,发布到 GeoServer。

    GeoServer 坐标系自动填充 EPSG:3857

    然后新建 GeoServer 的 Style,我这里的操作比较简单,就是将 polygon 的样式复制过来,将 Fill 的颜色改为透明色 transparent ,保存为 my_polygon,如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <StyledLayerDescriptor version="1.0.0" 
     xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 
     xmlns="http://www.opengis.net/sld" 
     xmlns:ogc="http://www.opengis.net/ogc" 
     xmlns:xlink="http://www.w3.org/1999/xlink" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <!-- a Named Layer is the basic building block of an SLD document -->
      <NamedLayer>
        <Name>default_polygon</Name>
        <UserStyle>
        <!-- Styles can have names, titles and abstracts -->
          <Title>Default Polygon</Title>
          <Abstract>A sample style that draws a polygon</Abstract>
          <!-- FeatureTypeStyles describe how to render different features -->
          <!-- A FeatureTypeStyle for rendering polygons -->
          <FeatureTypeStyle>
            <Rule>
              <Name>rule1</Name>
              <Title>Gray Polygon with Black Outline</Title>
              <Abstract>A polygon with a gray fill and a 1 pixel black outline</Abstract>
              <PolygonSymbolizer>
                <Fill>
                  <CssParameter name="fill">transparent</CssParameter>
                </Fill>
                <Stroke>
                  <CssParameter name="stroke">#000000</CssParameter>
                  <CssParameter name="stroke-width">1</CssParameter>
                </Stroke>
              </PolygonSymbolizer>
            </Rule>
          </FeatureTypeStyle>
        </UserStyle>
      </NamedLayer>
    </StyledLayerDescriptor>
    

    发布图层的时候选择 my_polygon 就好了。

    image.png

    加载图层

    let resolutions = []
    for (let i = 0; i < 19; i++) {
        resolutions[i] = Math.pow(2, 18 - i);
    }
    
    let tileLayer = new BMap.TileLayer({
        isTransparentPng: true
    });
    
    tileLayer.getTilesUrl = function(tileCoord, zoom) {
    
        let x = tileCoord.x;
        let y = tileCoord.y;
    
        let res = resolutions[zoom];
        let tileWidth = 256;
        let minx = x * tileWidth * res;
        let miny = y * tileWidth * res;
        let maxx = (x + 1) * tileWidth * res;
        let maxy = (y + 1) * tileWidth * res;
    
        // 百度墨卡托坐标 ->百度经纬度坐标
        let bottomLeft = CoordinateTransform.BD_MKT2WGS(minx, miny);
        let topRight = CoordinateTransform.BD_MKT2WGS(maxx, maxy);
        // 计算出bbox
        let bbox2 = [bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]];
    
        return 'http://localhost:8080/geoserver/test/wms?' +
            'SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&' +
            'TRANSPARENT=true&tiled=true&STYLES&LAYERS=test%3AExport_Output_2&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3857&BBOX=' +
            bbox2.join(',');
    }
    
    map.addTileLayer(tileLayer);
    
    • 由于我发布的是 EPSG:3857 ,所以 url 中 SRS 也改为 SRS=EPSG%3A3857

    坐标转换文件 CoordinateTransform.js

    /**
     * Created by Daniel on 2016/7/27.
     *
     * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
     *
     * 会有偏差,但是偏差在可接受范围之内
     */
    (function(root, factory) {
        root.CoordinateTransform = factory();
    }(this, function() {
        var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
        var PI = 3.1415926535897932384626;
        var a = 6378245.0;
        var ee = 0.00669342162296594323;
        var MCBAND = [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0];
        var MC2LL = [
            [1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2],
            [-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86],
            [-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37],
            [-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06],
            [3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4],
            [2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5]
        ];
        /**
         * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
         * 即 百度 转 谷歌、高德
         * @param bd_lon
         * @param bd_lat
         * @returns {[]} GCJ-02 坐标:[经度,纬度]
         */
        var transformBD09ToGCJ02 = function(bd_lon, bd_lat) {
            var x = bd_lon - 0.0065;
            var y = bd_lat - 0.006;
            var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
            var gg_lng = z * Math.cos(theta);
            var gg_lat = z * Math.sin(theta);
            return [gg_lng, gg_lat]
        };
    
        /**
         * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
         * 即谷歌、高德 转 百度
         * @param lng
         * @param lat
         * @returns {[]}  BD-09 坐标:[经度,纬度]
         */
        var transformGCJ02ToBD09 = function(lng, lat) {
            var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
            var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
            var bd_lng = z * Math.cos(theta) + 0.0065;
            var bd_lat = z * Math.sin(theta) + 0.006;
            return [bd_lng, bd_lat]
        };
    
        /**
         * WGS84转GCj02
         * @param lng
         * @param lat
         * @returns {[]} GCj02 坐标:[经度,纬度]
         */
        var transformWGS84ToGCJ02 = function(lng, lat) {
            if (outOfChina(lng, lat)) {
                return [lng, lat]
            } else {
                var dLat = transformLat(lng - 105.0, lat - 35.0);
                var dLng = transformLng(lng - 105.0, lat - 35.0);
                var radLat = lat / 180.0 * PI;
                var magic = Math.sin(radLat);
                magic = 1 - ee * magic * magic;
                var sqrtMagic = Math.sqrt(magic);
                dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
                dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
                var mgLat = lat + dLat;
                var mgLng = lng + dLng;
                return [mgLng, mgLat]
            }
        };
    
        /**
         * GCJ02 转换为 WGS84
         * @param lng
         * @param lat
         * @returns {[]} WGS84 坐标:[经度,纬度]
         */
        var transformGCJ02ToWGS84 = function(lng, lat) {
            if (outOfChina(lng, lat)) {
                return [lng, lat]
            } else {
                var dLat = transformLat(lng - 105.0, lat - 35.0);
                var dLng = transformLng(lng - 105.0, lat - 35.0);
                var radLat = lat / 180.0 * PI;
                var magic = Math.sin(radLat);
                magic = 1 - ee * magic * magic;
                var sqrtMagic = Math.sqrt(magic);
                dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
                dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
                var mgLat = lat + dLat;
                var mgLng = lng + dLng;
                return [lng * 2 - mgLng, lat * 2 - mgLat]
            }
        };
    
        var transformLonLatToMecator = function(lng, lat) {
            let earthRad = 6378137.0;
            let x = lng * Math.PI / 180 * earthRad;
            let a = lat * Math.PI / 180;
            let y = earthRad / 2 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
            return [x, y]; //[12727039.383734727, 3579066.6894065146]
        }
    
        /**
         * 百度坐标BD09 转 WGS84
         *
         * @param lng 经度
         * @param lat 纬度
         * @return {[]} WGS84 坐标:[经度,纬度]
         */
        var transformBD09ToWGS84 = function(lng, lat) {
            var lngLat = transformBD09ToGCJ02(lng, lat);
            return transformGCJ02ToWGS84(lngLat[0], lngLat[1]);
        };
    
        /**
         * WGS84 转 百度坐标BD09
         *
         * @param lng 经度
         * @param lat 纬度
         * @return {[]} BD09 坐标:[经度,纬度]
         */
        var transformWGS84ToBD09 = function(lng, lat) {
            var lngLat = transformWGS84ToGCJ02(lng, lat);
    
            return transformGCJ02ToBD09(lngLat[0], lngLat[1]);
        };
    
        var transformLat = function(lng, lat) {
            var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
            ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
            return ret
        };
    
        var transformLng = function(lng, lat) {
            var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
            ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
            return ret
        };
    
        /**
         * 判断是否在国内,不在国内则不做偏移
         * @param lng
         * @param lat
         * @returns {boolean}
         */
        var outOfChina = function(lng, lat) {
            return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
        };
    
        var BD_MKT2WGS = function BD_MKT2WGS(lng, lat) {
            var cF = null;
            lng = Math.abs(lng);
            lat = Math.abs(lat);
            for (var cE = 0; cE < MCBAND.length; cE++) {
                if (lat >= MCBAND[cE]) {
                    cF = MC2LL[cE];
                    break;
                }
            }
            lng = cF[0] + cF[1] * Math.abs(lng);
            var cC = Math.abs(lat) / cF[9];
            lat = cF[2] + cF[3] * cC + cF[4] * cC * cC + cF[5] * cC * cC * cC + cF[6] * cC * cC * cC * cC + cF[7] * cC * cC * cC * cC * cC + cF[8] * cC * cC * cC * cC * cC * cC;
            lng *= (lng < 0 ? -1 : 1);
            lat *= (lat < 0 ? -1 : 1);
            return [lng, lat];
        }
    
        return {
            transformBD09ToWGS84: transformBD09ToWGS84,
            transformWGS84ToBD09: transformWGS84ToBD09,
            transformGCJ02ToWGS84: transformGCJ02ToWGS84,
            transformWGS84ToGCJ02: transformWGS84ToGCJ02,
            transformBD09ToGCJ02: transformBD09ToGCJ02,
            transformGCJ02ToBD09: transformGCJ02ToBD09,
            transformLonLatToMecator: transformLonLatToMecator,
            BD_MKT2WGS: BD_MKT2WGS
        }
    }));
    

    BD_MKT2WGS(lon, lat) 方法就在里面。

    相关文章

      网友评论

          本文标题:百度地图如何成功加载 GeoServer 的 WMS 图层

          本文链接:https://www.haomeiwen.com/subject/hjmhultx.html