Gis坐标系4326与3857

Posted 言成言成啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gis坐标系4326与3857相关的知识,希望对你有一定的参考价值。

参考

  1. GIS基础知识 - 坐标系、投影、EPSG:4326、EPSG:3857
  2. GIS基础教程之坐标系 - 知乎
  3. Axis Order — GeoTools 28-SNAPSHOT User Guide
  4. EPSG.io: Coordinate Systems Worldwide
  5. 区域面积-距离/面积计算-示例中心-JS API 示例 | 高德地图API

一、坐标系

分类

坐标系分为两种

  1. 地理坐标系(Geographic Coordinate System, GCS)
  2. 投影坐标系(Projected Coordinate System, PCS)

这边知乎老哥的文章描述很容易理解,我直接cv过来。

地理坐标系,就是一个球,说成球面坐标系反而好理解一点。就比如一个完整的橘子。

投影坐标系,就是将球展开后的一个面。就比如橘子剥皮展开。

地理坐标系和投影坐标系的最大区分,就是单位不同。

地理坐标系以为单位。

投影坐标系以为单位。

常用坐标系

对于地图开发人员来说,常见的测量系统就是WGS84测量系统(1984年全球测量系统)。

基于WGS84的常用坐标系为两种。

  • EPSG:4326
  • EPSG:3857

4326是地理坐标系,以度为单位。广泛用于GPS定位等。

3857是投影坐标系,以米为单位。用于平面地图,如GoogleMapOpenStreetMapBingMap等。

如果想要找取专属于自己地区、更精确的坐标系。可以去epsg.io搜索。

二、geotools

作为用java做饭碗的人来说,想要研究Gis,肯定少不了跟geotools打交道。

maven依赖

pom.xml

<repositories>
    <repository>
        <id>osgeo</id>
        <name>OSGeo Release Repository</name>
        <url>https://repo.osgeo.org/repository/release/</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <releases>
            <enabled>true</enabled>
        </releases>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-grid</artifactId>
        <version>$geotools.version</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-opengis</artifactId>
        <version>$geotools.version</version>
    </dependency>


    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-epsg-hsql</artifactId>
        <version>$geotools.version</version>
        <exclusions>
            <exclusion>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-main</artifactId>
        <version>$geotools.version</version>
        <exclusions>
            <exclusion>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-geojson</artifactId>
        <version>$geotools.version</version>
        <exclusions>
            <exclusion>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

简单使用

下面简单演示一些常见用法。我这边就全以wkt为例了。wkt的绘制可以参考meethigher/wkt-show-on-openlayers: 基于openlayers的wkt绘制展示功能

/**
 * GeoTools简单使用
 *
 * @author chenchuancheng github.com/meethigher
 * @since 2022/5/22 20:30
 */
public class GeotoolsUsing 

    @Test
    public void testCreateGeo() throws Exception 
        //这是4326坐标系的wkt
        String wkt = "LINESTRING(110.26968650499015 35.774090269456565,118.2156404214427 35.973104738241815)";
        WKTReader reader = new WKTReader();
        Geometry geometry = reader.read(wkt);
        System.out.println(geometry.buffer(1));
        Assert.assertNotNull(geometry);
    

    @Test
    public void testGeoApi() throws Exception 
        //area1是包含area2的
        String area1 = "POLYGON((113.36572265625 38.80204526520603,107.28369301557538 33.994384090476174,112.38134926557541 28.960087983961387,119.2368153333664 31.690781121452815,113.36572265625 38.80204526520603))";
        String area2 = "LINESTRING(110.35095139165554 33.90070434182671,116.21651043156132 33.564288629604945)";
        WKTReader reader = new WKTReader();
        Geometry geometry1 = reader.read(area1);
        Geometry geometry2 = reader.read(area2);

        System.out.println(geometry1.contains(geometry2));//true

        //获取边界,即获取最北、最南、最东、最西,组成一个矩形
        Geometry envelope = geometry1.getEnvelope();
        System.out.println(envelope.toString());//输出wkt

        //获取边界的点
        Envelope internal = geometry1.getEnvelopeInternal();
        double minX = internal.getMinX();
        double minY = internal.getMinY();

        //返回其中一个顶点
        Coordinate coordinate = geometry1.getCoordinate();
        System.out.println(coordinate);

        //拓宽区域,由于使用的是4326坐标系,1在此处表示1度。这个单位也是跟着坐标系走的
        //以面的边向外拓宽1,顶点处就是以1为半径的圆弧。如果是线,就是四周拓宽
        Geometry buffer = geometry1.buffer(1);
        System.out.println(buffer);

        //判断交叉,我画的是个不相交,但包含的。
        //这个方法有两个含义。a.相交 b. 包含 满足其一即可
        boolean intersects = geometry1.intersects(geometry2);
        System.out.println(intersects);//true

        //面求面积,线求长度。单位同样是跟着坐标系走
        System.out.println(geometry1.getArea());
        System.out.println(geometry2.getLength());
    


    @Test
    public void testTransformCrs() throws Exception 
        //我使用的wkt都是经度在前,一般正常使用也是经度在前。将4326转换为3857计算面积(㎡)
        CRSAuthorityFactory factory = CRS.getAuthorityFactory(true);
        CoordinateReferenceSystem source = factory.createCoordinateReferenceSystem("EPSG:4326");
        CoordinateReferenceSystem target = factory.createCoordinateReferenceSystem("EPSG:3857");
        MathTransform transform = CRS.findMathTransform(source, target);

        //高德地图面积https://developer.amap.com/demo/javascript-api/example/calcutation/ring-area
        // 该区域高德面积125178908819平方米,坐标系不同,有误差很正常
        String wkt = "POLYGON((110.4141583943802 36.03154311769477,110.54418331527785 33.09352034423874,114.95057594167424 33.32318635566811,114.73386810758919 35.99648515314789,110.4141583943802 36.03154311769477))";

        WKTReader reader = new WKTReader();
        Geometry geometry = reader.read(wkt);
        System.out.println(geometry.getArea());//度为单位,12.258110818164612
        Geometry geometry1 = JTS.transform(geometry, transform);
        //用bigdecimal只是单纯不想看到科学计数法。
        System.out.println(BigDecimal.valueOf(geometry1.getArea()));//米为单位,184591949648.2439
    

以上是关于Gis坐标系4326与3857的主要内容,如果未能解决你的问题,请参考以下文章

Gis坐标系4326与3857

OpenLayers5在EPSG:4326下以m为单位画圆

记一次 CesiumJS 中非 4326/3857 WMTS 数据的加载

OpenLayers自定义投影,转换OpenLayers中加载的OSM的默认投影坐标

北京54坐标如何转换WGS84坐标?

EPSG:3857 坐标系统与 Azure Maps 的兼容性