Geotools中关于坐标转换纬度超限问题
问题描述
在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:3857Geometry 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:4326MathTransform 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:3857Geometry geometry3857 = JTS.transform(geometry, transform);// 5. 生成缓冲区(单位为米,因为 EPSG:3857 使用米)Geometry buffer = geometry3857.buffer(bufferDistance);// 6. 将缓冲区几何对象转换回 WKTWKTWriter 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;}}
使用上面转换就没有问题。大家可以亲自试试。