好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

java 操作gis geometry类型数据方式

java操作gis geometry类型数据

现在做的gis方面的业务,所以需要操作postgis中的geometry对象,找了很多的库,比如geotools,但是莫名下载不下来。

还有就是jts,但是不好用,操作起来很复杂。找到了一个其他的类库--geolatte-geom 和geolatte-geojson。

用于操作geometry和String以及json的互相转化。而json和geojson个人理解就是输出格式不同。多了一些geometry特有的属性。

主要用于将String转geometry对象、wkt和wkb方便好用。

pom.xml文件如下

?

1

2

3

4

5

6

7

8

9

10

11

12

13

<!-- https://mvnrepository测试数据/artifact/org.geolatte/geolatte-geom -->

< dependency >

     < groupId >org.geolatte</ groupId >

     < artifactId >geolatte-geom</ artifactId >

     < version >1.6.0</ version >

</ dependency >

 

<!-- https://mvnrepository测试数据/artifact/org.geolatte/geolatte-geojson -->

< dependency >

     < groupId >org.geolatte</ groupId >

     < artifactId >geolatte-geojson</ artifactId >

     < version >1.6.0</ version >

</ dependency >

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public static void main(String[] args) {

        // 模拟数据库中直接取出的geometry对象值(他是二进制的)

        // WKT 是字符串形式,类似"POINT(1 2)"的形式

        // 所以WKT转  geometry,相当于是字符串转geometry

        // WKB转  geometry,相当于是字节转geometry

        String s= "01020000800200000097E5880801845C404D064F3AF4AE36400000000000000000290A915F01845C40DC90B1A051AE36400000000000000000" ;

        Geometry geo = Wkb.fromWkb(ByteBuffer.from(s));

 

        // geometry对象和WKT输出一致

//        Geometry geometry1 = Wkt.fromWkt(wkt);

        System.out.println( "-----Geometry------" +geo.getPositionN( 1 ));

        System.out.println( "-----wkt------" + Wkt.toWkt(geo));

        System.out.println( "-----wkb------" +Wkb.toWkb(geo));

    }

java读取数据库geometry

最近因为需要存一些经纬度块信息到数据库,所以用到了mysql中的Geometry属性(几何对象)。在网上搜集了很多资料,到真正用的时候还是各种问题,所以下面推荐一种可能有点笨但是实用的方法(我的使用环境springboot工具是sts),下面就举个例子来说明一下。

操作

先了解一下数据库中空间数据类型有哪些

类型 说明 简介 例子
Geometry 间数据 任意一种空间类型  
Point 坐标值 POINT(104.00924 30.46872)
LineString 线 线,由一系列点连接而成 LINESTRING(1 1, 1 1, 1 1)
Polygon 多边形 由多条线组成 POLYGON((1 1, 2 2, 3 3, 4 4, 5 5))
MultiPoint 点集合 集合类,包含多个点 MULTIPOINT(1 1, 2 2, 1 1)
MultiLineString 线集合 集合类,包含多条线 MULTILINESTRING((1 1, 2 2), (1 1, 1 1))
MultiPolygon 多边形集合 集合类,包含多个多边形 MULTIPOLYGON(((0 0, 1 0, 1 1, 0 1, 0 0)), ((1 1, 1 1, 1 1, 1 1, 1 1)))
GeometryCollection 空间数据集合 集合类,可以包括多个点、线、多边形 GEOMETRYCOLLECTION(POINT(1 1), POINT(3 3), LINESTRING(1 1, 2 2))

接着往数据库插入一个测试数据,插入的是一个空间数据集合里面包含多个多边形集合。

INSERT INTO `geometry`(`geome`) VALUES(GeomFromText('GEOMETRYCOLLECTION(MULTIPOLYGON(((104.009241 30.468972,104.009229 30.468961,104.009225 30.468997)),((104.009241 30.468972,104.009229 30.468961,104.009225 30.468997))),MULTIPOLYGON(((104.009241 30.468972,104.009229 30.468961,104.009225 30.468997))))'));

数据准备好了就准备开始准备读取操作。

在pom.xml添加操作Geometry等对象的依赖。

?

1

2

3

4

5

< dependency >

    < groupId >com.vividsolutions</ groupId >

    < artifactId >jts</ artifactId >

    < version >1.13</ version >

</ dependency >

本来先是想直接在实体类确定类型直接转对象,但是用了后发现不行,所以我就直接设置成Object,在mysql中存储Geometry使用的是二进制,所以下面直接把二进制通过jts转成Geometry对象。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

//private Geometry geom; 不可行

private Object geomAsBytes; //可行  最终得到的是一个byte数组

     //直接把数据库中的byte[]转Geometry对象

   public static Geometry getGeometryByBytes( byte []  geometryAsBytes) throws Exception {

            Geometry dbGeometry = null ;

                // 字节数组小于5,说明geometry有问题

                if (geometryAsBytes.length < 5 ) {

                                      return null ;

                }

 

                //这里是取字节数组的前4个来解析srid

                byte [] sridBytes = new byte [ 4 ];

                System.arraycopy(geometryAsBytes, 0 , sridBytes, 0 , 4 );

                boolean bigEndian = (geometryAsBytes[ 4 ] == 0x00 );

                // 解析srid

                int srid = 0 ;

                if (bigEndian) {

                    for ( int i = 0 ; i < sridBytes.length; i++) {

                        srid = (srid << 8 ) + (sridBytes[i] & 0xff );

                    }

                } else {

                    for ( int i = 0 ; i < sridBytes.length; i++) {

                        srid += (sridBytes[i] & 0xff ) << ( 8 * i);

                    }

                }

                //use the JTS WKBReader for WKB parsing

                WKBReader wkbReader = new WKBReader();

                // 使用geotool的WKBReader 把字节数组转成geometry对象。

                byte [] wkb = new byte [geometryAsBytes.length - 4 ];

                System.arraycopy(geometryAsBytes, 4 , wkb, 0 , wkb.length);

                dbGeometry = wkbReader.read(wkb);

                dbGeometry.setSRID(srid);

            return dbGeometry;

        }

完整使用例子,解析数据库中的geometry对象,得到我们需要的点位数据。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

//返回一个区域集合  区域由若干个点组成

public List < Area > geometryCollection2PressAreas( byte [] data) {

     List < Area > areas= new ArrayList < > ();

      try {

        //解析出空间集合层

         GeometryCollection geometryCollection = (GeometryCollection) GeometryUtil.getGeometryByBytes(data);

         int geometrySize = geometryCollection.getNumGeometries();

         for ( int i1 = 0 ; i1 < geometrySize; i1++) {

             try {

                //解析出多边形集合层

                 MultiPolygon multiPolygon = (MultiPolygon) geometryCollection.getGeometryN(i1);

                 int size = ( int ) multiPolygon.getNumPoints();

                 for ( int i = 0 ; i < size; i++) {

                     try {

                        //解析出多边形

                         Polygon polygon = (Polygon) multiPolygon.getGeometryN(i);

                        //解析出多边形中的多个点位

                         Coordinate[] coordinates2 = polygon.getCoordinates();

                         int size2 = coordinates2.length;

                         Area area = new Area();

                         area.area_pts = new ArrayList < > ();

                         for ( int j = 0 ; j < size2; j++) {

                            //点位对象 就一个x,一个y数据

                             Point point = new Point();

                             point.x = coordinates2[j].x;

                             point.y = coordinates2[j].y;

                            //点位集合

                             area.area_pts.add(point);

                         }

                         areas.add(area);

                     } catch (Exception e) {

                         break ;

                     }

                 }

             } catch (Exception e) {

                 break ;

             }

         }

     } catch (Exception e) {

         e.printStackTrace();

     }

     return areas;

}

小结一下

其实以前存地理信息都是用的自己组装的json字符串,占用空间太大。最近才发现mysql还有地理空间数据这个好东(发现新大陆~),空间节省了,读取也快了。不过读取数据库中数据不知道还有没有更好的方法,这篇介绍的都是自己手动转的对象,不过暂时先能用就好。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/TNT_D/article/details/109111708

查看更多关于java 操作gis geometry类型数据方式的详细内容...

  阅读:28次