proj4js空间坐标转换入门

proj4js是一个用于地理空间坐标转换的JavaScript库。可以很方便的在浏览器和nodejs环境下完成坐标转换,能在一定程度上弥补当前很多web gis引擎对坐标系支持能力不足的短板(大多数web端的gis引擎只支持WGS 84和Web墨卡托两种坐标系)。

proj4js源于另一个开源项目PROJ,虽然目前功能已经相对完善,开源社区也比较活跃,但是文档还有不少欠缺,想要了解完整的参数和用法还是得查阅PROJ的文档

坐标系描述

在proj4中可以通过下表所列的常用参数组合成一个描述坐标系信息的字符串,在proj4js中称为proj-string。本文对其中几个重要的参数进行介绍。

参数描述
+a椭球长轴的半径
+axis轴的方向
+b椭球短轴的半径
+ellps地球椭球
+datum大地基准面
+k缩放系数(已废弃)
+k_0缩放系数
+lat_0纬度的起算点(默认以度为单位)
+lat_ts有效纬度范围
+lon_0中央经线(默认以度为单位)
+lon_wrap定义经度范围的一种方式(+lon_wrap=180 表示 [ 0, 360] )
+over允许经度超出[ -180, 180 ]的范围
+pm自定义子午线(通常是城市名称)
+proj投影名称
+units水平坐标系单位(米、美制测量英尺等)
+vunits垂直坐标系单位
+x_0东偏移量(始终以米为单位)
+y_0北偏移量(始终以米为单位)
+no_defs不从默认的proj_def.dat读取默认参数
+zone指定UTM区域

常用坐标系定义参数 

投影名称

使用+proj指定投影名称,常用可选值如下

坐标系名称意义
merc墨卡托投影
utmUTM(横轴墨卡托)投影
longlat坐标值输入为 [ 经度, 纬度 ] 的地理坐标系
latlong坐标值输入为 [ 纬度, 经度 ] 的地理坐标系

 常用投影名称

示例: 

+proj=merc +lat_ts=56.5 +ellps=GRS80

+proj=utm +zone=50 +datum=WGS84 +units=m +no_defs +type=crs

单位

坐标系水平方向单位用+units参数定义,垂直方向的单位通过+vunits参数定义。

示例: 

坐标单位为度

+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees

坐标单位为米(投影坐标系默认单位是米)

+proj=gnom +lat_0=90 +lon_0=0 +x_0=6300000 +y_0=6300000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs

偏移量

坐标系允许存在东偏移量 (+x_0) 和北偏移 (+y_0)。即使坐标系是其他单位,偏移量也始终以米表示。

示例: 

+proj=tmerc +lat_0=0 +lon_0=75 +k=1 +x_0=13500000 +y_0=0 +a=6378140 +b=6356755.288157528 +units=m +no_defs

经度范围

经度范围默认被限制在 [ -180, 180 ],如果使用了+over参数,则经度范围可以忽略这个限制

示例: 

 +proj=merc +a=6371200 +b=6371200 +units=meters +no_defs + lon_1=110 +lon_2=-109.129 +lat_ts=20 +lon_wrap=180 +over

本初子午线

使用+pm参数可以自定义坐标系的本初子午线。proj4js有一组预定义的子午线名称。

子午线经度
greenwich(默认)0dE
lisbon9d07'54.862"W
paris2d20'14.025"E
bogota74d04'51.3"E
madrid3d41'16.48"W
rome12d27'8.4"E
bern7d26'22.5"E
jakarta106d48'27.79"E
ferro17d40'W
brussels4d22'4.71"E
stockholm18d3'29.8"E
athens23d42'58.815"E
oslo10d43'22.5"E

 proj4预定义子午线

示例:

+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs

+proj=latlong +datum=WGS84 +pm=madrid

坐标轴方向

+axis参数用于控制坐标系的轴方向,默认方向是“东、北、上”,或者由以下字母自由组合

  • "e" - 东
  • "w" - 西
  • "n" - 北
  • "s" - 南
  • "u" - 上
  • "d" - 下

例如以下几种组合方式

  • +axis=enu :默认的ENU(东、北、上)坐标系;
  • +axis=neu :通常用于 "纬度 / 经度" 形式的地理坐标或者南向横轴墨卡托投影(south orientated transverse mercator);
  • +axis=wnu :用于一些以西为正方向的行星坐标系

椭球体

椭球体是一个数学意义上的表面,它近似于大地水准面。由于地球是一个不规则的椭球体,于是地图投影中产生了多种多样的椭球体定义。每个地区都有最适合当地地形的地球椭球体。

椭球体包含尺寸(size)和形状(shape )两部分概念。具体由尺寸参数、形状参数和球谐参数指定。(如果使用了+R参数指定为标准球体,那么形状参数和球谐参数都会被忽略)

参数意义
+R=<value>球体的半径(定义为球体时使用)
+a=<value>椭球的长半轴

尺寸参数 

参数意义
+rf=<value>椭球扁率的倒数(Reverse flattening)
+f=<value>椭球扁率
+es=<value>偏心率的平方
+e=<value>偏心率
+b=<value>短半轴

形状参数 

参数意义
+R_A与椭球体表面积相同的球体
+R_V与椭球体体积相同的球体
+R_C半径为共形球体(conformal sphere)\phi _{0}处半径的球体
+R_a半径R为 (a + b) / 2 的球体(算数平均数)
+R_g半径R为 \sqrt{ab}的球体(几何平均数)
+R_h半径R为 2ab / (a + b)的球体(调和平均数)
+R_lat_a=<phi>半径为相应椭球在纬度\varnothing处的算数平均数的球体
+R_lat_g=<phi>半径为相应椭球在纬度\varnothing处的几何平均数的球体

 球谐参数

用户可以自定义椭球体,但更多的还是使用+ellps参数选用proj4内置的椭球体

椭球参数测量基准
GRS80(默认)a=6378137.0 rf=298.257222101GRS 1980(IUGG, 1980)
airya=6377563.396 b=6356256.910Airy 1830
bessela=6377397.155 rf=299.1528128Bessel 1841
clrk66a=6378206.4 b=6356583.8Clarke 1866
intla=6378388.0 rf=297.International 1909 (Hayford)
WGS60a=6378165.0 rf=298.3WGS 60
WGS66a=6378145.0 rf=298.25WGS 66
WGS72a=6378135.0 rf=298.26WGS 72
WGS84a=6378137.0 rf=298.257223563WGS 84
spherea=6370997.0 b=6370997.0Normal Sphere (r=6370997)

 proj4预定义椭球体

示例:

GRS80椭球

+proj=merc +lat_ts=56.5 +ellps=GRS80

通过半长轴和扁率的倒数自定义椭球

+proj=latlon +a=6378137.0 +rf=298.25 

和定义的椭球体体积相同的球体

+proj=latlon +a=6378137.0 +rf=298.25 +R_V 

常用坐标系定义

 WGS 84地理坐标系统 (EPSG:4326)

+proj=longlat +datum=WGS84 +no_defs

 Web Mercator (EPSG:3857)

+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs

 中国国家2000地理坐标系统 (EPSG:4490)

定义和WGS 84一样(CGCS2000椭球和WGS84椭球极为相似,偏差仅有0.11mm,完全可以兼容使用)

+proj=longlat +ellps=GRS80 +no_defs

 北京54坐标系 (EPSG:4214)

+proj=longlat +ellps=krass +towgs84=15.8,-154.4,-82.3,0,0,0,0 +no_defs

 西安80坐标系 (EPSG:4610)

+proj=longlat +a=6378140 +b=6356755.288157528 +no_defs

 UTM 50号带 / UTM zone 50N (EPSG:32650)

中国国境跨UTM带号为43-53,根据需要更改+zone后面的数字即可

+proj=utm +zone=50 +datum=WGS84 +units=m +no_defs

API使用介绍

proj4js主要的函数是proj4,函数签名如下所示:

    proj4([fromProjection, ]toProjection[, coordinates])

应用举例 

 下面的用例用到两个坐标系定义

    var firstProjection = 'PROJCS["NAD83 / Massachusetts Mainland",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",42.68333333333333],PARAMETER["standard_parallel_2",41.71666666666667],PARAMETER["latitude_of_origin",41],PARAMETER["central_meridian",-71.5],PARAMETER["false_easting",200000],PARAMETER["false_northing",750000],AUTHORITY["EPSG","26986"],AXIS["X",EAST],AXIS["Y",NORTH]]';
    var secondProjection = "+proj=gnom +lat_0=90 +lon_0=0 +x_0=6300000 +y_0=6300000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";

1、将一个坐标点从一个坐标系转换到另一个坐标系

    // ...
    // [-2690575.447893817, 36622916.8071244564]
    proj4(firstProjection, secondProjection, [-122.305887, 58.9465872]); 

2、转换带高程值的坐标(高程值会原样保留)

    // ...
    // [-2690575.447893817, 36622916.8071244564, 10]
    proj4(firstProjection,secondProjection,[-122.305887, 58.9465872,10]);

3、如果只提供一个坐标系,这个坐标系会被认为是目标坐标系(toProjection),源坐标系(fromProjection)默认为WGS84

    // ...
    // 坐标从WGS 84转换到 firstProjection
    // [242075.00535055372, 750123.32090043]
    proj4(firstProjection, [-71, 41]);

4、如果proj4函数中只传入了坐标系,没有传入待转换的坐标。那么proj4函数返回一个包含 forward 和 inverse 两个函数的对象。

  • forward :从第一个坐标系参数转换到第二个坐标系参数
  • inverse :从第二个坐标系参数转换到第一个坐标系参数
	// firstProjection 转换到 secondProjection
    // [-2690575.447893817, 36622916.8071244564]
	proj4(firstProjection, secondProjection).forward([-122.305887, 58.9465872]);
	// firstProjection 转换到 secondProjection
    // [-2690575.447893817, 36622916.8071244564]
    proj4(secondProjection, firstProjection).inverse([-122.305887, 58.9465872]);

5、只给出一个坐标系,并且没有坐标,那么原始坐标系被认为是wgs84

    // wgs84转换到firstProjection
    // [242075.00535055372, 750123.32090043]
    proj4(firstProjection).forward([-71,41])
    // 因为是inverse,所以把坐标从firstProjection转换到wgs84
    // [-71, 40.99999999999986]
    proj4(firstProjection).inverse([242075.00535055372, 750123.32090043]);

投影命名

proj4js允许用户通过defs函数自定义坐标系名称,并在后续引用

    proj4.defs([
      [
        'EPSG:4326',
        '+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees'],
      [
        'EPSG:4269',
        '+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees'
      ]
    ]);
    // 从secondProjection转换到自定义的'EPSG:4326'
    // [-163.48520399669096, 11.401530800453495, 10]
    proj4(secondProjection, 'EPSG:4326', [-2690575.447893817, 36622916.8071244564, 10]);

proj4js内置了一些预定义的坐标系名称

坐标系名称别名
EPSG:4326WGS84
EPSG:4269
EPSG:3857EPSG:3785 或 GOOGLE 或 EPSG:900913 或 EPSG:102113

proj4预定义坐标系及别名 

    // 使用预定义坐标系
    proj4(secondProjection, 'EPSG:3785', [-2690575.447893817, 36622916.8071244564, 10]);
    proj4(secondProjection, 'EPSG:900913', [-2690575.447893817, 36622916.8071244564, 10])

使用proj4js预定义的坐标系 

反转坐标轴顺序

默认情况下,proj4中投影坐标系使用 [x, y] 的坐标轴顺序,地理坐标系使用 [x = longitude, y = latitude] 的坐标轴顺序。可以按以下方式设置enforceAxis参数以反转默认的坐标轴顺序。

proj4(fromProjection, toProjection).forward(coordinate, enforceAxis);
proj4(fromProjection, toProjection).inverse(coordinate, enforceAxis);

	// enforceAxis默认值为false
    // [-71, 40.99999999999986]
    proj4('+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees +axis=neu', firstProjection).inverse([242075.00535055372, 750123.32090043]);

    // 显示指定enforceAxis为true,反转坐标轴
	// [40.99999999999986, -71]
    proj4('+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees +axis=neu', firstProjection).inverse([242075.00535055372, 750123.32090043], true);
	// 不设置enforceAxis
    // [39078917.71700995, -2076788.7936424324]
    proj4('+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees +axis=neu', firstProjection).forward([41, -71]);
	
    // enforceAxis设置为true
	// [242075.00535055372, 750123.32090043]
    proj4('+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees +axis=neu', firstProjection).forward([41, -71], true);

结语

这篇文章只是总结了proj4js涉及的基本概念以及使用方法,并不能囊括所有proj4js的细节。同时地图投影的内容很多,还有很多理论和概念是我不了解的,有待后续不断学习和总结!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值