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: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;
        }
    }

使用上面转换就没有问题。大家可以亲自试试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值