Openlayers 投影与坐标转换

Openlayers 投影与坐标转换

在初始化map实例时,如果不在view中用projection参数指定投影坐标系,则将会使用默认的空间参考EPSG:3857(Web 墨卡托投影)。后续叠加的图层,都会将数据进行投影转换,确保map在同一个空间参考内。

EPSG(European Petroleum Survey Group,欧洲石油调查组织)负责维护并发布坐标参照系统的数据集参数,以及坐标转换描述。它将已有的椭球体,投影坐标系等及其不同组合都对应着不同的ID号,这个号在EPSG中被称为EPSG code,它代表特定的椭球体、单位、地理坐标系或投影坐标系等信息。

Openlayers中的指定空间参考可以直接使用EPSG code指定,如EPSG:4326,因为ol.proj.Projection已经帮我们定义好EPSG:4326EPSG:3857这两个空间参考的参数,同时也为这两个空间参考定义了一些别名,如EPSG:3857EPSG:102100EPSG:102113EPSG:900913这些曾用名,也有用于识别GML要素的http://www.opengis.net/gml/srs/epsg.xml#3857urn:ogc:def:crs:EPSG:6.18:3:3857

空间参考的别名可以使用proj4jsdefs()方法添加:

proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326'));

ol对于其他空间参考,可以使用proj4js进行自定义。defs()方法定义,register()方法进行注册。

proj4js是一个JavaScript库,是一个强大的通用坐标转换引擎,可以同时进行大规模地图投影和高精密度的坐标转换。

proj4.defs(
  'EPSG:21781',
  '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 ' +
    '+x_0=600000 +y_0=200000 +ellps=bessel ' +
    '+towgs84=660.077,13.551,369.344,2.484,1.783,2.939,5.66 +units=m +no_defs'
);
register(proj4);

自定义的投影必须是在https://epsg.io/可以找到的才有效。
在这里插入图片描述在这里插入图片描述
常用参数列表:

参数描述
+proj投影名称,安装proj后可以使用proj - l命令查看支持的投影名称
+lat_0维度起点
+lon_0中央经线
+x_0东(伪)偏移量
+y_0北(伪)偏移量
+ellps椭球体名称,使用proj -le 命令查看支持哪些椭球体
+units水平单位,meters(米)。使用proj -lu命令查看PROJ支持的单位
+lat_ts有效纬度范围
+a椭球体长半轴长度
+b椭球体短半轴长度
+k比例系数(比例因子),旧版本,不赞成使用
+k_0比例系数(比例因子)
+vunits垂直单位
+datum基准面名称,使用proj -ld命令查看支持的基准面
+towgs843参数或7参数基面转换
+to_meter将水平单位转换为米计算输出转换参数,如:1英尺=
+no_defs不要使用proj库中的缺省定义文件。

下面使用OSM地图作为示例图层,定义CGCS2000的空间参考。

<!doctype html>
<html>
<head>
    <link rel="stylesheet" href="css/ol.css" type="text/css">
    <style>
        .map {
            height: 85vh;
            width: 100%;
        }
    </style>
    <script src="lib/ol.js"></script>
    <!--引入proj4.js-->
    <script src="lib/proj4.js"></script>
    <title>OpenLayers example</title>
    <meta charset="UTF-8">
</head>
<body>
<h2>Projection CGCS2000(EPSG:4490)</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
    var shenzhen = [113.958334, 22.535640];
    
    //使用proj4.defs()定义投影
    proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
    //使proj4中定义的投影在OpenLayers中可用。
    ol.proj.proj4.register(proj4);

    //创建"EPSG:4490"的Projection实例,Openlayers将可以从Peoj4js中获取转换函数。
    var cgcs2000 = new ol.proj.Projection({
        code: "EPSG:4490",//EPSG code
        extent:[-180,-90,180,90],
        worldExtent:[-180,-90,180,90],
        units:"degrees"//Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or `'us-ft'.
    });
	ol.proj.addProjection(cgcs2000);
    
    var map = new ol.Map({
        target: "map",
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            })
        ],
        view: new ol.View({
            center:ol.proj.fromLonLat(shenzhen,cgcs2000),
            zoom: 11,
            projection: cgcs2000
        })
    })
</script>
</body>
</html>

可以将瓦片图层SOM当做底图,再往上叠加图层。
对于矢量数据可以使用ol.proj命名空间下的方法,在客户端进行坐标转换,如:

//将坐标coordinate从“EPSG:3857”转换到“EPSG:4490”
ol.proj.transform([12686109.88955285,2572810.705991532],"EPSG:3857","EPSG:4490");

//添加坐标转换函数
ol.proj.addCoordinateTransforms("EPSG:3857","EPSG:4490",function (coordinate) {
	return proj4("EPSG:3857","EPSG:4490",coordinate);
},function (coordinate) {
	return proj4("EPSG:4490","EPSG:3857",coordinate);
})

//将经纬度的coordinate转换到目标空间参考下的坐标,默认是EPSG:3857
ol.proj.fromLonLat([113.958334, 22.535640],cgcs2000)

//将coordinate转换成经纬度
ol.proj.toLonLat([12686109.88955285,2572810.705991532])

上述是对单个coordinate的转换,对于几何要素Geometry及其子类(点、线、面等)可以使用ol.geom.Geometry中的transform()方法转换几何对象中的每组坐标。像GeoJSONKMLgpx类型的文件可以选择在解析器解析完成得到要素集合后,对每个要素进行转化。

示例:

<!doctype html>
<html>
<head>
    <link rel="stylesheet" href="css/ol.css" type="text/css">
    <style>
        .map {
            height: 85vh;
            width: 100%;
        }
    </style>
    <script src="lib/ol.js"></script>
    <!--引入proj4.js-->
    <script src="lib/proj4.js"></script>
    <title>OpenLayers example</title>
    <meta charset="UTF-8">
</head>
<body>
<h2>Projection CGCS2000(EPSG:4490)</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
    var shenzhen = [113.958334, 22.535640];
    
    //使用proj4.defs()定义投影
    proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
    //使proj4中定义的投影在OpenLayers中可用。
    ol.proj.proj4.register(proj4);

    //创建"EPSG:4490"的Projection实例,Openlayers将可以从Peoj4js中获取转换函数。
    var cgcs2000 = new ol.proj.Projection({
        code: "EPSG:4490",//EPSG code
        extent:[-180,-90,180,90],
        worldExtent:[-180,-90,180,90],
        units:"degrees"//Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or `'us-ft'.
    });

    var map = new ol.Map({
        target: "map",
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            })
        ],
        view: new ol.View({
            center:ol.proj.fromLonLat(shenzhen,cgcs2000),
            zoom: 11,
            projection: cgcs2000
        })
    })

    var geojson = new ol.source.Vector();
    fetch("data/geojson/test.json").then(function(response){
        return response.json();
    }).then(function (value) {
        var features = (new ol.format.GeoJSON()).readFeatures(value);
        for(var i=0;i<features.length;i++){
            features[i].getGeometry().transform("EPSG:3857","EPSG:4490");
        }
        geojson.addFeatures(features);
    })

    var testLayer = new ol.layer.Vector({
        source: geojson
    });

    map.addLayer(testLayer);
</script>
</body>
</html>

效果:
在这里插入图片描述
test.json数据文件:

{
  "type": "FeatureCollection",
  "crs": {
    "type": "name",
    "properties": {
      "name": "urn:ogc:def:crs:EPSG:3857"
    }
  },
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          12686109.88955285,
          2572810.705991532
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          12683644.795390654,
          2568835.9805207034
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            12673134.704001442,
            2577473.364716928
          ],
          [
            12671453.089379169,
            2571625.932053112
          ],
          [
            12689186.479941329,
            2580358.8625346934
          ],
          [
            12677606.270156125,
            2580435.2995629786
          ]
        ]
      }
    }
  ]
}

对于服务类型的数据,像WFSWMS服务可以在请求中使用srsnameCRS参数指定返回要素的空间参考,将坐标转换的工作在服务端完成。

示例:

<!doctype html>
<html >
  <head>
    <link rel="stylesheet" href="css/ol.css" type="text/css">
    <style>
      .map {
        height: 85vh;
        width: 100%;
      }
    </style>
    <script src="lib/ol.js"></script>
    <script src="lib/proj4.js"></script>
    <title>OpenLayers example</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <h2>Projection:加载GeoServer的WFS服务</h2>
    <div id="map" class="map"></div>
    <script type="text/javascript">
        //使用proj4.defs()定义投影
        proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
        //使proj4中定义的投影在OpenLayers中可用。
        ol.proj.proj4.register(proj4);

        //创建"EPSG:4490"的Projection实例,Openlayers将可以从Peoj4js中获取转换函数。
        var cgcs2000 = new ol.proj.Projection({
            code: "EPSG:4490",//EPSG code
            extent:[-180,-90,180,90],
            worldExtent:[-180,-90,180,90],
            units:"degrees"//Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or `'us-ft'.
        });
      
        var nyc = [-73.92722,40.774221];
        var map = new ol.Map({
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                new ol.layer.Vector({
                    source: new ol.source.Vector({
                        format: new ol.format.GeoJSON(),
                        url: function(extent) {
                            //直接返回WFS的GetFeature接口访问地址,设置outputFormat为json格式和format中的解析器一致
                            //使用srsname指定返回要素的空间参考:srsname=EPSG:4490
                            return 'http://localhost:8080/geoserver/wfs?service=WFS&' +
                                'version=1.1.0&request=GetFeature&typename=tiger:tiger_roads&' +
                                'outputFormat=application/json&srsname=EPSG:4490&' +
                                'bbox=' + extent.join(',') + ',EPSG:4490';
                        },
                        /*
                        * 加载策略,可选值:
                        *   all,一次性加载所有的要素;
                        *   bbox,加载地图当前视图范围内的要素;
                        *   tile,基于瓦片格网加载要素
                        */
                        strategy: ol.loadingstrategy.bbox
                    })
                }),
                vecLayer
            ],
            target: document.getElementById('map'),
            view: new ol.View({
                center: nyc,
                maxZoom: 19,
                zoom: 12,
                projection: cgcs2000
            })
        });

    </script>
  </body>
</html>

在这里插入图片描述

var map = new ol.Map({
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        }),
        new ol.layer.Tile({
            source: new ol.source.TileWMS({
                url: 'http://localhost:8080/geoserver/tiger/ows',
                params: {
                    //WIDTH, HEIGHT, BBOX and CRS (SRS for WMS version < 1.3.0) 将被动态设置.
                    'LAYERS': 'tiger:tiger_roads',
                    'TILED': false,
                    'VERSION':'1.1.0',
                    'TRANSPARENT':true,//
                    'CRS':"EPSG:4490"
                },
                //远程WMS服务器的类型
                serverType: 'geoserver',
                // 用于渲染的不透明度过渡的持续时间。要禁用不透明过渡,设置transition为: 0
                transition: 0
            })
        })
    ],
    target: document.getElementById('map'),
    view: new ol.View({
        center: nyc,
        maxZoom: 19,
        zoom: 12,
        projection: cgcs2000
    })
});

在这里插入图片描述

参考文章

[1] proj4js https://github.com/proj4js/proj4js

[2] PROJ.4学习–坐标转换 https://www.cnblogs.com/eshinex/p/10301739.html

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值