通过PROJ4转换地理数据到GoogleMap投影坐标系

Google Map以及VirtualEarth等web gis都采用一种特殊的投影坐标系EPSG:900913,其实这个900913并不是EPSG分配的编号,而是设计Google Map的工程师自己选定的一个编号。该投影坐标系一开始不被EPSG组织承认(EPSG认为这个坐标系的参数设定非常不符合地理科学),后来因为使用的人越来越多,不得已承认了,但分配了一个别的编号epsg:3785而不是900913。但是大多数程序员不知道,还一直使用900913,呵呵。

关于epsg:3785投影坐标系的详细参数如下:(参考 http://spatialreference.org/ref/epsg/3785/

+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs 

上面这组参数是用于PROJ4(一个著名的地理投影变换开源库)的,我用以上参数以及从中国国家测绘局下载的中国地图数据和Google Map对照了一下发现x坐标(经度)没有差异,但是y坐标有较大的差异。后来在下述网页http://proj.maptools.org/faq.html的最后一个问题上发现需要一个额外的参数:

 

The coordinate system definition for Virtual Earth Mercator is as follows, which uses a sphere as the earth model for the mercator projection.

+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 +no_defs
But, if you do something like:
cs2cs +proj=latlong +datum=WGS84 +to +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 +no_defs

to convert between WGS84 and mercator on the sphere there will be substantial shifts in the Y mercator coordinates. This is because internally cs2cs is having to adjust the lat/long coordinates from being on the sphere to being on the WGS84 datum which has a quite differently shaped ellipsoid.

In this case, and many other cases using spherical projections, the desired approach is to actually treat the lat/long locations on the sphere as if they were on WGS84 without any adjustments when using them for converting to other coordinate systems. The solution is to "trick" PROJ.4 into applying no change to the lat/long values when going to (and through) WGS84. This can be accomplished by asking PROJ to use a null grid shift file for switching from your spherical lat/long coordinates to WGS84.

 

cs2cs +proj=latlong +datum=WGS84 
    +to +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 +no_defs

Note the strategic addition of +nadgrids=@null to the spherical projection definition.

Similar issues apply with many other datasets distributed with projections based on a spherical earth model - such as many NASA datasets, and also (I think) the Google Maps mercator projection.

 

原来缺少+nadgrids=@null参数用来避免sphere lat/long调节就可以了,最终的PROJ4参数如下:

+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +nagrids=@null +no_defs
这回数据就非常符合Google Map了。
将经纬度坐标(地理坐标)转换为投影坐标(平面坐标)通常涉及以下几个步骤,这些步骤可以使用不同的编程语言或GIS软件(如ArcGIS、QGIS)实现。以下是常见的实现方法: ### 1. 选择投影方式 不同的应用场景需要不同的投影方法,常见的投影包括: - **高斯-克吕格投影**(Gauss-Kruger Projection):适用于小范围高精度的局部投影,常用于国家测绘标准。 - **墨卡托投影**(Mercator Projection):适用于全球范围的地图显示,常用于Web地图服务(如Google Maps、OpenStreetMap)。 - **UTM投影**(Universal Transverse Mercator):适用于中纬度区域的平面坐标转换,分为多个投影带。 选择合适的投影方式后,可以通过编程实现或使用GIS工具进行转换。 ### 2. 使用GIS软件进行转换(如ArcGIS) ArcGIS 提供了完整的工具链来实现经纬度坐标到投影坐标的转换: #### 步骤: 1. **设置投影坐标系**: - 使用工具:`Data Management Tools -> Projections and Transformations -> Project` - 输入数据:包含经纬度坐标的点数据(如Shapefile) - 输出坐标系:选择目标投影坐标系(如WGS84 World Mercator) 2. **导出投影坐标**: - 使用工具:`Data Management Tools -> Features -> Add XY Coordinates` - 输出结果:属性表中会新增`POINT_X`和`POINT_Y`字段,分别表示投影坐标系下的X和Y值。 3. **导出数据**: - 在属性表左上角选择导出功能,将数据导出为`.txt`或`.csv`格式,以便在Excel或其他工具中进一步处理。 ### 3. 使用编程语言实现转换 可以使用多种编程语言(如Python、Java、JavaScript)结合地理库来实现经纬度到投影坐标的转换。 #### Python实现(使用`pyproj`库) ```python import pyproj # 定义输入和输出坐标系 wgs84 = pyproj.CRS('EPSG:4326') # WGS84经纬度坐标系 mercator = pyproj.CRS('EPSG:3857') # Web墨卡托投影坐标系 # 创建转换器 transformer = pyproj.Transformer.from_crs(wgs84, mercator, always_xy=True) # 输入经纬度坐标 longitude = 116.4074 # 经度 latitude = 39.9042 # 纬度 # 转换为投影坐标 x, y = transformer.transform(longitude, latitude) print(f"投影坐标: X={x}, Y={y}") ``` #### Java实现(使用`GeoTools`库) ```java import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; public class CoordinateConversion { public static void main(String[] args) throws Exception { // 定义输入和输出坐标系 CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326"); // WGS84经纬度坐标系 CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); // Web墨卡托投影坐标系 // 创建转换器 MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS); // 输入经纬度坐标 GeometryFactory geometryFactory = new GeometryFactory(); Point point = geometryFactory.createPoint(new Coordinate(116.4074, 39.9042)); // 转换为投影坐标 Point transformedPoint = (Point) JTS.transform(point, transform); System.out.println("投影坐标: " + transformedPoint.getX() + ", " + transformedPoint.getY()); } } ``` #### JavaScript实现(使用`proj4js`库) ```javascript // 引入proj4js库 const proj4 = require('proj4'); // 定义输入和输出坐标系 const wgs84 = "+proj=longlat +datum=WGS84 +no_defs"; const mercator = "+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"; // 输入经纬度坐标 const longitude = 116.4074; const latitude = 39.9042; // 转换为投影坐标 const [x, y] = proj4(wgs84, mercator, [longitude, latitude]); console.log(`投影坐标: X=${x}, Y=${y}`); ``` ### 4. 注意事项 - **坐标系选择**:确保输入和输出的坐标系定义正确,避免因坐标系不匹配导致的误差。 - **坐标范围**:某些投影方法(如UTM)只适用于特定的地理区域,超出范围可能导致精度下降。 - **数据格式**:在使用编程语言进行转换时,注意输入数据的格式是否符合要求(如经纬度顺序、单位等)。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值