栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

GeoTools,GIS的另一个基础设施~

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

GeoTools,GIS的另一个基础设施~

about GeoTools

GeoTools is an open source (LGPL) Java code library which provides standards compliant methods for the manipulation of geospatial data, for example to implement Geographic Information Systems (GIS). The GeoTools library implements Open Geospatial Consortium (OGC) specifications as they are developed.

走进 GeoTools

GeoTools的架构图如下,我们了解GeoTools的架构以及各个jar包所构成的库栈,能够帮助我们更加清晰的了解和学习GeoTools的各个模块,并且还能够帮助我们在项目里面选择适合我们的库。

../_images/geotools.png

这张架构图遵循了软件工程领域里面架构图设计标准,由下而上,第一层是基础设施,上层建筑依赖于基础设施。

比如:你如果想使用Referencing模块里的gt-opengis,gt-referencing,gt-metadata内容,那么当你使用data模块的时候,gt-main,jts,gt-opengis,gt-referencing,gt-opengis,gt-metadata,上面Referencing的内容也是会引用到的。

GeoTools常用模块的功能列表:

ModulePurpose
gt-renderImplements of Java2D rendering engine to draw a map
gt-jdbcImplements for accessing spatial database
gt-mainImplements for accessing spatial data
gt-xmlImplements of common spatial XML formats
gt-cqlImplements of Common Query Language for filters
gt-mainInterfaces for working with spatial information. Implements filter, feature, etc…
jtsDefinition and implementation of Geometry
gt-coverageImplementation for accessing raster information
gt-referencingImplementation of co-ordinate location and transformation
gt-metadataImplementation of identification and description
gt-opengisDefinition of interfaces for common spatial concepts

GeoTools提供插件来支持额外的数据格式、不同的坐标参考系统权限等等。

ModuleJARPlugin
gt-render
gt-jdbcgt-jdbc-db2Geometry in DB2
gt-jdbc-h2Pure Java “H2” database
gt-jdbc-mysqlGeometry in MySQL
gt-jdbc-oracleOracle SDO Geometry
gt-jdbc-postgisPostgreSQL extension PostGIS
gt-jdbc-sqlserverSQL Server
gt-jdbc-hanaSAP HANA
gt-jdbc-terasdataTeradata
gt-maingt-shapeShapefile read/write support
gt-wfsWFS read/write support
gt-xml
gt-cql
gt-main
jts
gt-coveragegt-geotiffGeoTIFF raster format
gt-arcgridarcgrid format
gt-mifMIF format
gt-imageJPG, PNG, TIFF formats
gt-referencingepsg-access .Official EPSG database in Access
epsg-hsqlPure Java port of EPSG database
epsg-wktLightweight copy of EPSG codes
epsg-postgresqlPostgreSQL port of EPSG database
gt-metadata
gt-opengis

除此之外,GeoTools团队在GeoTools的基础上实现了一些扩展,当然了,这些扩展是为了提供一些额外的功能。这些扩展是相互独立的,我们可以直接在项目中使用。

../_images/extension.png

JARExtension
gt-graphWork with graph and network traversals
gt-validationQuality assurance for spatial data
gt-wmsWeb Map Server client
gt-xsdParsing/Encoding for common OGC schemas
gt-brewerGeneration of styles using color brewer

GeoTools团队为了支持GeoTools中的XML模块,将几个XML模式打包成JAR形式,方便开发者进行调用。

JARSchema
net.opengis.owsopen web services schema
net.opengis.wfsweb feature service
net.opengis.wpsweb processing service schema
net.opengis.wcsweb coverage service schema
net.opengis.wfsweb feature service schema
org.w3.xlinkXlink schema

XSD解析器通过一系列XSD插件使用这些工具。这些插件指示如何使用Eclipse XSD库解析和编码额外的内容来解析XML模式文档,并提供“绑定”,显示如何解析和编码Java类,如String、Date、URL和Geometry。

JARBindings
gt-xsd-coreBasic types defined by XML schema
gt-xsd-fesfilter 2.0
gt-xsd-filterfilter (used by OGC CAT and WFS)
gt-xsd-kmlkeyhole markup language
gt-xsd-wfsweb feature service
gt-xsd-wpsweb processing service
gt-xsd-gml3geographic markup language 3
gt-xsd-gml2geographic markup language 2
gt-xsd-owsopen web services
gt-xsd-wcsweb coverage service
gt-xsd-wmsweb map service
gt-xsd-sldstyle layer descriptor

以下是GeoTools不支持的扩展,你也可以使用Maven下载它们来使用。

UnsupportedPurpose
gt-swtStandard widget toolkit interactive map
gt-swingSwing interactive map
gt-oracleretired oracle support
gt-postgisretired PostGIS support
gt-db2retired db2 support
gt-wpsWeb Processing Service client
gt-processJob system for spatial data
牛刀小试
  1. 在POM文件中,首先添加以下内容:

    
        UTF-8
        24-SNAPSHOT
    
  1. 然后在POM文件的标签中,添加以下依赖,该依赖是GeoTools官方的依赖远程仓库位置:

 
      
        osgeo
        OSGeo Release Repository
        https://repo.osgeo.org/repository/release/
        false
        true
      
      
        osgeo-snapshot
        OSGeo Snapshot Repository
        https://repo.osgeo.org/repository/snapshot/
        true
        false
      
    
  1. 在POM文件中添加以下依赖:


        
            junit
            junit
            4.13.1
            test
        
        
            org.geotools
            gt-shapefile
            ${geotools.version}
        
        
            org.geotools
            gt-swing
            ${geotools.version}
        
        
        
            org.locationtech.jts
            jts-core
            1.16.1
        
        
        
            org.geotools
            gt-main
            22-RC
        

  1. 在你的Spring Boot工程中新建QuickStrat类,并添加以下代码:

import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.swing.JMapframe;
import org.geotools.swing.data.JFileDataStoreChooser;

import java.io.File;


public class Quickstart {

    
    public static void main(String[] args) throws Exception {
        // display a data store file chooser dialog for shapefiles
        File file = JFileDataStoreChooser.showOpenFile("shp", null);
        if (file == null) {
            return;
        }

        FileDataStore store = FileDataStoreFinder.getDataStore(file);
        SimpleFeatureSource featureSource = store.getFeatureSource();

        // Create a map content and add our shapefile to it
        MapContent map = new MapContent();
        map.setTitle("Quickstart");

        Style style = SLD.createSimpleStyle(featureSource.getSchema());
        Layer layer = new FeatureLayer(featureSource, style);
        map.addLayer(layer);

        // Now display the map
        JMapframe.showMap(map);
    }
}
  1. 在该网站http://www.naturalearthdata.com/downloads/50m-cultural-vectors/,根据自己的喜好来下载一个矢量数据文件。

    在下图的窗口中勾选你刚才下载、并解压文件后的位置。

  1. 接下来就会自动弹出一个窗口,里面展示了你刚才下载的矢量文件,如下图:

以上是我们对GeoTools的快速启动案例的学习。

CSV转换SHP教程
  1. 在该地址下载location.csv文件:

http://docs.geotools.org/stable/userguide/_downloads/d4bcf8751cc3f33a9fb673902a960e53/locations.csv

  1. 在你的IDE中键入以下代码:

package com.geovis.bin.utils.gis.geotools;


import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.Transaction;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import javax.swing.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;




public class Csv2Shape {
    public static void csv2Shape() throws IOException, SchemaException, ClassNotFoundException, UnsupportedLookAndFeelException, InstantiationException, IllegalAccessException {
        // Set cross-platform look & feel for compatability
        UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());

        File file = JFileDataStoreChooser.showOpenFile("csv", null);
        if (file == null) {
            return;
        }

        
        final SimpleFeatureType TYPE =
                DataUtilities.createType(
                        "Location",
                        "the_geom:Point:srid=4326,"
                                + // <- the geometry attribute: Point type
                                "name:String,"
                                + // <- a String attribute
                                "number:Integer" // a number attribute
                );
        System.out.println("TYPE:" + TYPE);

        
        List features = new ArrayList<>();

        
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);

        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            
            String line = reader.readLine();
            System.out.println("Header: " + line);

            for (line = reader.readLine(); line != null; line = reader.readLine()) {
                //skip blank lines
                if (line.trim().length() > 0) {
                    String[] tokens = line.split("\,");

                    double latitude = Double.parseDouble(tokens[0]);
                    double longitude = Double.parseDouble(tokens[1]);
                    String name = tokens[2].trim();
                    int number = Integer.parseInt(tokens[3].trim());

                    
                    Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude));

                    featureBuilder.add(point);
                    featureBuilder.add(name);
                    featureBuilder.add(number);
                    SimpleFeature feature = featureBuilder.buildFeature(null);
                    features.add(feature);
                }
            }
        }
        
        File newFile = getNewShapeFile(file);

        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();

        Map params = new HashMap<>();
        params.put("url", newFile.toURI().toURL());
        params.put("create spatial index", Boolean.TRUE);

        ShapefileDataStore newDataStore =
                (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);

        
        newDataStore.createSchema(TYPE);


        
        Transaction transaction = new DefaultTransaction("create");

        String typeName = newDataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
        SimpleFeatureType SHAPE_TYPE = featureSource.getSchema();
        
        System.out.println("SHAPE:" + SHAPE_TYPE);

        if (featureSource instanceof SimpleFeatureStore) {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
            
            SimpleFeatureCollection collection = new ListFeatureCollection(TYPE, features);
            featureStore.setTransaction(transaction);
            try {
                featureStore.addFeatures(collection);
                transaction.commit();
            } catch (Exception problem) {
                problem.printStackTrace();
                transaction.rollback();
            } finally {
                transaction.close();
            }
//            success!
            System.exit(0);
        } else {
            System.out.println(typeName + " does not support read/write access");
            System.exit(1);
        }
    }


    
    private static File getNewShapeFile(File csvFile) {
        String path = csvFile.getAbsolutePath();
        String newPath = path.substring(0, path.length() - 4) + ".shp";

        JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
        chooser.setDialogTitle("Save shapefile");
        chooser.setSelectedFile(new File(newPath));

        int returnVal = chooser.showSaveDialog(null);

        if (returnVal != JFileDataStoreChooser.APPROVE_OPTION) {
            // the user cancelled the dialog
            System.exit(0);
        }

        File newFile = chooser.getSelectedFile();
        if (newFile.equals(csvFile)) {
            System.out.println("Error: cannot replace " + csvFile);
            System.exit(0);
        }

        return newFile;
    }

    public static void main(String[] args) throws Exception {
        csv2Shape();
    }

}



  1. 运行该代码,会弹出对话框,需要你选择下载并解压后的location.csv文件

  1. 选好之后会在同级目录生成shape file,我们把location.shp文件拖入ArcGIS DeskTop软件中,就可以看到如下界面:

  1. 至此,我们完成csv至shp文件的转换工作。

从shp文件读取要素集
   
    public static List getGeometryList(String fileUrl) throws IOException {
        List geometryList = new ArrayList<>();
        ShapefileReader r = null;
        try {
            r = new ShapefileReader(new ShpFiles(fileUrl), false, false, new GeometryFactory());
            while (r.hasNext()) {
                Geometry shape = (Geometry) r.nextRecord().shape();
                ShapeType shapeType = r.getHeader().getShapeType();
                double x1 = r.getHeader().maxX();
                double y1 = r.getHeader().maxY();
                double x2 = r.getHeader().minX();
                double y2 = r.getHeader().minY();

                geometryList.add(shape);
            }
        } catch (Exception e) {
            if (r != null) {
                r.close();
            }
            e.printStackTrace();
        }

        return geometryList;
    }

运行结果如下:

自定义GeoTools工具类

以下代码是自定义的一个GeoTools工具类,主要实现了一些点、线、面以及简单的空间分析的操作。

package com.geovis.bin.utils.gis.geotools;


import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKBReader;
import com.vividsolutions.jts.io.WKBWriter;
import com.vividsolutions.jts.io.WKTReader;
import org.geotools.geometry.jts.JTSFactoryFinder;

import java.util.ArrayList;
import java.util.List;

public class GeoToolsUtil {

    private static  com.vividsolutions.jts.geom.GeometryFactory GEOMETRYFACTORY = JTSFactoryFinder.getGeometryFactory();
    private static WKTReader WKTREADER = new WKTReader(GEOMETRYFACTORY);
    private static WKBWriter WKBWRITER = new WKBWriter();
    private static WKBReader WKBREADER = new WKBReader();

    

    
    public static Geometry polygon2LineString(Geometry geom) {

        String geometryType = geom.getGeometryType().toUpperCase();
        Geometry res;

        if ("MULTIPOLYGON".equals(geometryType)) {
            int geoNum = geom.getNumGeometries();
            ArrayList lineList = new ArrayList<>();
            if (geoNum > 1) {
                // 包含多个面,面中包含环
                for (int i = 0; i < geoNum; i++) {
                    Polygon geo = (Polygon) geom.getGeometryN(i);
                    lineList.add(GEOMETRYFACTORY.createLineString(geo.getExteriorRing().getCoordinates()));
                    for (int j = 0; j < geo.getNumInteriorRing(); j++) {
                        lineList.add(GEOMETRYFACTORY.createLineString(geo.getInteriorRingN(i).getCoordinates()));
                    }
                }
                LineString[] lines = new LineString[lineList.size()];
                lineList.toArray(lines);
                res = GEOMETRYFACTORY.createMultiLineString(lines);
            } else {
                //包含一个面,面中包含环
                Polygon poly = (Polygon) geom.getGeometryN(0);
                lineList.add(GEOMETRYFACTORY.createLineString(poly.getExteriorRing().getCoordinates()));
                for (int i = 0; i < poly.getNumInteriorRing(); i++) {
                    lineList.add(GEOMETRYFACTORY.createLineString(poly.getInteriorRingN(i).getCoordinates()));
                }
                LineString[] lines = new LineString[lineList.size()];
                lineList.toArray(lines);
                res = GEOMETRYFACTORY.createMultiLineString(lines);
            }
        } else if ("POLYGON".equals(geometryType)) {
            //只包含一个面
            res = GEOMETRYFACTORY.createLineString(geom.getCoordinates());
        } else {
            res = null;
        }
        return res;
    }

    
    public static Geometry getPointOfIntersection(Geometry geom, Geometry line) {
        Geometry lines = polygon2LineString(geom);
        return lines.intersection(line);
    }

    
    public static Geometry wkt2Geometry(String wkt) {
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        WKTReader wktReader = new WKTReader(geometryFactory);
        Geometry geometry = null;

        try {
            Geometry read = wktReader.read(wkt);
            return geometry;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;

    }

    
    public static Point creatrPoint(String lon, String lat) {
        Coordinate coordinate = new Coordinate(Double.parseDouble(lon), Double.parseDouble(lat));
        Point point = GEOMETRYFACTORY.createPoint(coordinate);
        return point;
    }

    
    public static Point creatrPoint(String coor) throws ParseException {
        Point p = (Point) WKTREADER.read(coor);
        return p;
    }

    
    public static Polygon createPolygon(String polygon) throws ParseException {
        Polygon p = (Polygon) WKTREADER.read(polygon);
        return p;
    }

    
    public static LineString createLineString(String line) throws ParseException {
        LineString lineString = (LineString) WKTREADER.read(line);
        return lineString;
    }

    
    public static boolean equalsLinePoint(String p1, String p2, int srid) throws ParseException {
        Point geom1 = (Point) WKTREADER.read(p1);
        geom1.setSRID(srid);
        Point geom2 = (Point) WKTREADER.read(p2);
        geom2.setSRID(srid);
        return geom1.equals(geom2);
    }

    
    public static boolean equalsLineString(String l1, String l2) throws ParseException {
        LineString geom1 = (LineString) WKTREADER.read(l1);
        LineString geom2 = (LineString) WKTREADER.read(l2);
        return geom1.equals(geom2);
    }


    
    public static boolean equalsPolygon(String p1, String p2) throws ParseException {
        Polygon geom1 = (Polygon) WKTREADER.read(p1);
        Polygon geom2 = (Polygon) WKTREADER.read(p2);
        return geom1.equals(geom2);
    }

    
    public static boolean disjoinLineString(String s1, String s2) throws ParseException {
        LineString line1 = (LineString) WKTREADER.read(s1);
        LineString line2 = (LineString) WKTREADER.read(s2);
        return line1.disjoint(line2);
    }


    
    public static boolean disjoinPolygon(String s1, String s2) throws ParseException {
        Polygon p1 = (Polygon) WKTREADER.read(s1);
        Polygon p2 = (Polygon) WKTREADER.read(s2);
        return p1.disjoint(p2);
    }

    
    public static boolean interSectionOfLineStringAndLineString(String s1, String s2) throws ParseException {
        LineString l1 = (LineString) WKTREADER.read(s1);
        LineString l2 = (LineString) WKTREADER.read(s1);
        Geometry points = l1.intersection(l2);
        return l1.intersects(l2);
    }

    
    public static Coordinate[] interSectionOfLineStringAndLineString(String s1, String s2, int srid) throws ParseException {
        LineString l1 = (LineString) WKTREADER.read(s1);
        LineString l2 = (LineString) WKTREADER.read(s1);
        Geometry points = l1.intersection(l2);
        Coordinate[] coordinates = points.getCoordinates();
        return coordinates;
    }

    
    public static Polygon pointArray2Polygon(String s) throws ParseException {
        return (Polygon) WKTREADER.read(s);
    }

    
    public static List IntersectionPointsAndPolygon(Polygon polygon, String lon, String lat) {
        List points = new ArrayList<>();
        Point point = creatrPoint(lon, lat);
        boolean contains = polygon.contains(point);
        if (contains) {
            points.add(point);
        }
        return points;
    }


    
    public static List IntersectionPointsAndPolygon(Polygon polygon, String coor) throws ParseException {
        List points = new ArrayList<>();
        Point point = creatrPoint(coor);
        boolean contains = polygon.contains(point);
        if (contains) {
            points.add(point);
        }
        return points;
    }

    
    public static boolean isIntersects(Polygon p1, Polygon p2) {
        boolean flag = p1.intersects(p2);
        return flag;
    }


    
    public static Polygon intersectsArea(Polygon p1, Polygon p2) {
        Polygon geom = (Polygon) p1.intersection(p2);
        return geom;
    }

    
    public static Polygon fireArea(String point, double range) throws ParseException {
        Point fire = (Point) WKTREADER.read(point);
        Polygon buffer = (Polygon) fire.buffer(range);
        return buffer;
    }

    
    public static double distanceOfPoint(Point p1, Point p2) {
        return p1.distance(p2);
    }

    
    public static double distanceOfPoint(String lon1, String lon2, String lat1, String lat2) {
        Point p1 = creatrPoint(lon1, lat1);
        Point p2 = creatrPoint(lat2, lon2);
        return p1.distance(p2);
    }

    
    public static double timeOfGoal(Coordinate start, Coordinate end, float speed) {
        return (start.distance3D(end)) / speed;
    }


}

希望这个初步教程可以帮助到你,也欢迎私信交流、一起进步~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/582993.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号