问题描述
在Geotools中定义坐标系并转换,出现了个很奇怪的报错
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.Geometry;
import com.vividsolutions.jts.io.WKTReader;
public class WktTo3857AndBuffer {
public static void main(String[] args) {
try {
// 步骤 1:解析 WKT(EPSG:4326,经纬度)
String wktString = "POINT (116.3912 39.9042)"; // 示例:北京坐标(经度,纬度)
WKTReader wktReader = new WKTReader();
Geometry geometry = wktReader.read(wktString);
// 步骤 2:定义源和目标坐标参考系
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326"); // WGS84(经纬度)
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); // Web Mercator
// 步骤 3:创建从 EPSG:4326 到 EPSG:3857 的转换
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
// 步骤 4:将几何转换为 EPSG:3857
Geometry geometry3857 = JTS.transform(geometry, transform);
System.out.println("转换后的几何(EPSG:3857): " + geometry3857.toText());
// 步骤 5:在 EPSG:3857 下生成缓冲区
double bufferDistanceMeters = 1000.0; // 缓冲区距离:1000 米
Geometry bufferedGeometry = geometry3857.buffer(bufferDistanceMeters);
System.out.println("缓冲区几何(EPSG:3857): " + bufferedGeometry.toText());
// 可选:将缓冲区几何转换回 EPSG:4326
MathTransform inverseTransform = CRS.findMathTransform(targetCRS, sourceCRS, true);
Geometry bufferedGeometry4326 = JTS.transform(bufferedGeometry, inverseTransform);
System.out.println("缓冲区几何(EPSG:4326): " + bufferedGeometry4326.toText());
} catch (Exception e) {
e.printStackTrace();
}
}
}
这段代码没有任何问题,但是的时候就汇报错,如果传递的wkt改成POINT (39.9042 116.3912)
就是对的,上面的代码报错是维度超范围。但是我们平时定义wkt都是先X后Y。
原因分析
原因主要出在了定义坐标系上,使用EPSG 代码定义的坐标系,先维度,后京都的方式
将上面的代码改成
public String transformAndBufferWkt(String wkt, double bufferDistance) throws Exception {
// 1. 解析 WKT 字符串为 Geometry 对象
WKTReader wktReader = new WKTReader();
Geometry geometry = wktReader.read(wkt);
// 2. 定义源坐标系 (EPSG:4326) 和目标坐标系 (EPSG:3857)
CoordinateReferenceSystem sourceCRS = getCRS4326();
CoordinateReferenceSystem targetCRS =getCRS3857();
// 3. 创建坐标转换器
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
// 4. 将几何对象从 EPSG:4326 转换为 EPSG:3857
Geometry geometry3857 = JTS.transform(geometry, transform);
// 5. 生成缓冲区(单位为米,因为 EPSG:3857 使用米)
Geometry buffer = geometry3857.buffer(bufferDistance);
// 6. 将缓冲区几何对象转换回 WKT
WKTWriter wktWriter = new WKTWriter();
return wktWriter.write(buffer);
}
private CoordinateReferenceSystem getCRS4326(){
try {
String str = "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433],AUTHORITY[\"EPSG\",4326]]";
return CRS.parseWKT(str);
}catch (Exception e){
System.out.println(e.getMessage());
return null;
}
}
private CoordinateReferenceSystem getCRS3857() {
try {
String str = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\",GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_Auxiliary_Sphere\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"Standard_Parallel_1\",0.0],PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",3857]]";
return CRS.parseWKT(str);
}catch (Exception e){
System.out.println(e.getMessage());
return null;
}
}
使用上面转换就没有问题。大家可以亲自试试。