在地图上,为了保证数据的局部精度,会根据不同区域,采用不同类型的投影坐标(如墨卡托投影、高斯投影等等)。所以经常需要将投影坐标,转换为地理坐标,便于理解和阅读。本文共提供七种方法解决此问题。当然,我确认绝对不止这7种方法,对没有提到的方法,请留言补充。
命令行工具gdaltransform
命令行工具,我认为是实现坐标转换最快捷也是最容易的。安装OSGeo4W,并安装GDAL命令行工具后,双击OSGeo4W.bat脚本,启动命令行。首先输入gdaltransform -s_srs EPSG:32651 -t_srs EPSG:4326
,设置坐标系变量。然后再输入X、Y数据后,即得到结果。
如输入300000.0 4500000.0
,返回120.635319212982 40.6266397268273 0
同时,参考如下脚本,实现gdaltransform批量坐标转换。
@echo off
type points.txt | gdaltransform -s_srs EPSG:32651 -t_srs EPSG:4326
点击这里,从官网了解更多用法。
QGIS-Python工具
使用QGIS中集成的Python工具,也是一种不错的选择。打开QGIS的Python控制台后,输入如下代码即可。
from qgis.core import QgsCoordinateTransform, QgsProject, QgsCoordinateReferenceSystem
# 使用EPSG编号,定义源投影坐标系(例如:UTM Zone 51N, EPSG:32651)
source_crs = QgsCoordinateReferenceSystem("EPSG:32651")
# 定义目标地理坐标系(WGS84, EPSG:4326)
dest_crs = QgsCoordinateReferenceSystem("EPSG:4326")
# 创建坐标转换器,需要传入当前项目的transform context
transform = QgsCoordinateTransform(source_crs, dest_crs, QgsProject.instance())
# 输入待转换的投影坐标点(示例坐标,单位:米)
x_proj = 300000
y_proj = 4500000
# 执行坐标转换
point = transform.transform(x_proj, y_proj)
# 获取转换后的地理坐标(经度, 纬度)
longitude = point.x() # 经度
latitude = point.y() # 纬度
GDAL Python
GDAL Python在Windows平台,也是由OSGeo4W提供。首先下载好OSGeo4W后。参考以下代码实现。
from osgeo import osr
x_proj = 300000
y_proj = 4500000
# 创建源坐标系
source_srs = osr.SpatialReference()
source_srs.ImportFromEPSG("EPSG:32651")
# 创建目标坐标系(WGS84)
target_srs = osr.SpatialReference()
target_srs.ImportFromEPSG("EPSG:4326")
# 创建坐标转换对象
transform = osr.CoordinateTransformation(source_srs, target_srs)
# 执行坐标转换(注意返回值为[经度, 纬度, 高度])
lon, lat, _ = transform.TransformPoint(x_proj, y_proj)
GDAL C++
使用GDAL C++接口,也是很容易实现不同坐标系之间的转换。与GDAL Python类似,核心是使用OGRCoordinateTransformation类的transform实现。
注意,使用变量OAMS_TRADITIONAL_GIS_ORDER调整数据转换后的XY顺序。点击这里,参考官方给出的解释文档。
// 初始化GDAL
GDALAllRegister();
// 定义投影坐标
double x = 300000.0; // 东向坐标
double y = 4500000.0; // 北向坐标
// 创建源坐标系(投影坐标系)
OGRSpatialReference sourceSRS;
sourceSRS.importFromEPSG(32651);
// 创建目标坐标系(地理坐标系 WGS84)
OGRSpatialReference targetSRS;
targetSRS.SetWellKnownGeogCS("WGS84");
// 注意:设置轴顺序为经度、纬度
(https://gdal.org/en/stable/tutorials/osr_api_tut.html#crs-and-axis-order)
targetSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
// 创建坐标转换对象
OGRCoordinateTransformation* coordTrans =
OGRCreateCoordinateTransformation(&sourceSRS, &targetSRS);
if (!coordTrans) {
std::cerr << "坐标转换对象创建失败!" << std::endl;
return 1;
}
// 执行坐标转换
double geoX = x;
double geoY = y;
int success = coordTrans->Transform(1, &geoX, &geoY);
// 清理资源
OCTDestroyCoordinateTransformation(coordTrans);
Java GeoTools
选择Java的GeoTools工具实现坐标转换,首先增加GeoTools的依赖。
示例代码如下:
import org.geotools.api.referencing.FactoryException;
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
import org.geotools.api.referencing.operation.MathTransform;
import org.geotools.api.referencing.operation.TransformException;
import org.geotools.referencing.CRS;
public class CoordinateConverter {
public static void main(String[] args) {
// 定义源投影坐标系
String sourceCRSCode = "EPSG:32651";
// 定义目标地理坐标系
String targetCRSCode = "EPSG:4326";
try {
// 1. 创建坐标系对象
CoordinateReferenceSystem sourceCRS = CRS.decode(sourceCRSCode);
CoordinateReferenceSystem targetCRS = CRS.decode(targetCRSCode);
// 2. 检查轴顺序,强制目标坐标系为经度-纬度顺序
boolean longitudeFirst = CRS.getAxisOrder(targetCRS) == CRS.AxisOrder.EAST_NORTH;
if (!longitudeFirst) {
// 如果目标坐标系默认是纬度在前,需指定强制轴顺序
targetCRS = CRS.decode(targetCRSCode + "?forceAxisOrder=long,lat");
}
// 3. 创建坐标转换器
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
// 4. 定义投影坐标点(东向、北向)
double[] srcPoints = {300000.0, 4500000.0}; // x, y
// 5. 执行坐标转换
double[] dstPoints = new double[2];
transform.transform(srcPoints, 0, dstPoints, 0, 1);
// 6. 输出结果(经度、纬度)
System.out.printf("经度: %.8f°, 纬度: %.8f°\n", dstPoints[0], dstPoints[1]);
} catch (FactoryException | TransformException e) {
e.printStackTrace();
}
}
}
JavaScript proj4js
若开发的是网页应用,使用proj4js也可以轻松实现坐标系转换。有一点需要注意,proj4js中,并没有内置EPSG编码及对应的参考系参数。所以需要使用proj4.defs
自定义。点击这里,从EPSG官网查询编码对应的坐标系参数。
示例代码,如下:
// 引入 proj4
// const proj4 = require('proj4');
// 定义坐标系
// 1. 源坐标系
proj4.defs("EPSG:32651", "+proj=utm +zone=51 +datum=WGS84 +units=m +no_defs +type=crs");
// 2. 目标坐标系
proj4.defs("EPSG:4326", "+proj=longlat +datum=WGS84 +no_defs");
// 定义投影坐标点(东向坐标, 北向坐标)
const utmX = 300000.0;
const utmY = 4500000.0;
try {
// 执行坐标转换
const [longitude, latitude] = proj4(
proj4.defs("EPSG:32651"),
proj4.defs("EPSG:4326"),
[utmX, utmY]
);
// 输出结果(经度, 纬度)
console.log("地理坐标(经度, 纬度):");
console.log(`经度: ${longitude.toFixed(8)}°, 纬度: ${latitude.toFixed(8)}°`);
} catch (error) {
console.error("坐标转换失败:", error);
}
QGIS-人机交互
无论是QGIS、ArcGIS、还是国产的地图平台,都会提供数据坐标转换功能。我以QGIS为例说明如何操作软件实现坐标转换。其实,我认为QGIS软件更适合于将整个数据图层的转换,不适合做单点的转换。请参考如下步骤操作,确实较为繁琐。
1.构建临时点图层,坐标选择为待计算的数据所使用的投影坐标系。
2.使用待计算的投影坐标数值,修改点的位置。
3.将图层重投影到地理坐标系。
4.右键点击点要素,在顶点编辑器中,即显示地理坐标。
有更多问题,联系我们。欢迎交流,转载请注明出处。