java+geotools (geotools for java)

发布时间 2023-07-04 15:26:09作者: 小鱼写代码的过往

geotools所需的依赖,在pom.xml引入;

<dependencies>
    <!-- for geotools begin -->
        <!--处理空间数据-->
        <!-- geotools主要依赖 -->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-metadata</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-referencing</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-epsg-wkt</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-shapefile</artifactId>
            <version>27.2</version>
        </dependency>

        <!--<dependency>-->
            <!--<groupId>org.geotools</groupId>-->
            <!--<artifactId>gt-data</artifactId>-->
            <!--<version>27.2</version>-->
        <!--</dependency>-->

        <!--<dependency>-->
            <!--<groupId>org.geotools</groupId>-->
            <!--<artifactId>gt-api</artifactId>-->
            <!--<version>27.2</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-swing</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-jdbc</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools.jdbc</groupId>
            <artifactId>gt-jdbc-postgis</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-opengis</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-epsg-hsql</artifactId>
            <version>27.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>27.2</version>
        </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
     <artifactId>gt-process-feature</artifactId>
     <version>27.2</version>
    </dependency>

     <dependency> <groupId>org.locationtech.jts</groupId> <artifactId>jts-core</artifactId> <version>1.18.2</version> </dependency> <!--for geotools end--> <!--读取geojson文件--> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.wowtools</groupId> <artifactId>giscat-vector-pojo</artifactId> <version>1.1.1-STABLE</version> </dependency> <!--读取geojson文件end--> </dependencies> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </repository> <!-- geotools的远程库 --> <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> <repository> <id>osgeo-snapshot</id> <name>OSGeo Snapshot Repository</name> <url>https://repo.osgeo.org/repository/snapshot/</url> <snapshots><enabled>true</enabled></snapshots> <releases><enabled>false</enabled></releases> </repository> <!-- geotools的远程库end --> </repositories>

 下面是封装的一些方法(读取shp、读取geojson文件、读取属性attribute、查询...)

package com.example.demo.mapper;

import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureSource;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.geojson.GeoJSON;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.util.factory.GeoTools;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
@Component
public class GeoToolsMethod {
//使用openGIS FilterFactory2
private static org.opengis.filter.FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());
//读取shp
public FeatureSource<SimpleFeatureType, SimpleFeature> ReadShpFile(String filePath) throws Exception{
File dir = new File(filePath);
File[] subFiles = dir.listFiles();
if (null!=subFiles){
for (File subFile : subFiles) {
if (subFile.getName().endsWith(".shp")) {
filePath = subFile.getPath();break;
}
}
}
File shpFile = new File(filePath);
//源shape文件
//ShapefileDataStore shpDataStore = (ShapefileDataStore) new ShapefileDataStoreFactory().createDataStore(subFile.toURI().toURL());
ShapefileDataStore shpDataStore = new ShapefileDataStore(shpFile.toURI().toURL());
shpDataStore.setCharset(Charset.forName("UTF-8"));
FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = shpDataStore.getFeatureSource();
return featureSource;
}
//读取geojson
public FeatureCollection ReadGeojsonFile(String pathfile) throws Exception{
FeatureCollection featureCollection = null;
//创建一个JSONParser对象
JSONParser jsonParser = new JSONParser();
//解析JSON文件的内容
try {
//String pathfile = getClass().getClassLoader().getResource("csdata").getPath()+"/csfeature.geojson";
//先用json.simple读取geojson文件
// org.json.simple.JSONObject obj = (org.json.simple.JSONObject) jsonParser.parse(new FileReader("D:/hjyTest/JAVA/demo_gdal2/target/classes/csdata/csfeature.geojson"));
JSONObject obj = (JSONObject) jsonParser.parse(new FileReader(pathfile));
//JSONObject obj = (JSONObject) jsonParser.parse(new FileReader("E:\\河南省乡镇点\\FieldPolygon.geojson"));
//删除除features以外其它对象,方便下面所需的geojson字符串
// obj.remove("type");
// obj.remove("name");
// obj.remove("crs");
//获取features对象json字符串
String strGeoJson =obj.toString();
System.out.println(strGeoJson);


// 指定GeometryJSON构造器,15位小数
FeatureJSON fjson_15 = new FeatureJSON(new GeometryJSON(15));
// fjson_15已经保留15位
fjson_15.setEncodeFeatureCollectionCRS(true);
fjson_15.setEncodeNullValues(true);

featureCollection = fjson_15.readFeatureCollection(strGeoJson);
fjson_15.writeFeatureCollection(featureCollection,System.out); // 控制台输出和原始geojson一致



// OutputStream ostream = new ByteArrayOutputStream();
// GeoJSON.write(featureCollection, ostream);
// // 输出:{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[116.1983,39.7832],[116.0445,39.2323],[116.8959,39.3831],[116.8698,39.9182],[116.1983,39.7832]]]},"properties":{"area":3865207830},"id":"polygon.1"}]}
// System.out.println(ostream);

// //获取数据
// FeatureIterator<SimpleFeature> iterator = featureCollection.features();
// while(iterator.hasNext()) {
// SimpleFeature feature = iterator.next();
// try{
// org.locationtech.jts.geom.Geometry geom1 = (org.locationtech.jts.geom.Geometry) feature.getDefaultGeometry();
// System.out.println(geom1.getCoordinate());
// }catch (Exception e){
//
// }
//
//
// feature.getName();
// Iterator<Property> it = feature.getProperties().iterator();
// LinkedHashMap<String, Object> data = new LinkedHashMap<>();
// String geometry = "";
// while (it.hasNext()) {
// Property pro = it.next();
// if (pro.getValue() instanceof org.locationtech.jts.geom.Point) {//点
// geometry = "'" + ((org.locationtech.jts.geom.Point) pro.getValue()).toString() + "'";
// data.put("geom", geometry);
// } else if (pro.getValue() instanceof org.locationtech.jts.geom.Polygon) {//面
// geometry = "'" + ((org.locationtech.jts.geom.Polygon) pro.getValue()).toString() + "'";
// data.put("geom", geometry);
// } else if (pro.getValue() instanceof org.locationtech.jts.geom.MultiPolygon) {//多面
// geometry = "'" + ((org.locationtech.jts.geom.MultiPolygon) pro.getValue()).toString() + "'";
// data.put("geom", geometry);
// } else if (pro.getValue() instanceof org.locationtech.jts.geom.LineString) {//线
// geometry = "'" + ((org.locationtech.jts.geom.LineString) pro.getValue()).toString() + "'";
// data.put("geom", geometry);
// } else {
// data.put(pro.getName().toString(), pro.getValue());
// }
// }
// System.out.println(data);
// }

} catch (IOException e) {
e.printStackTrace();
}
return featureCollection;
}
//方法一:
//返回其属性值
public List<LinkedHashMap<String,Object>> getAttirbutes(String srs, FeatureCollection col){
//srs="EPSG:4326"
List<LinkedHashMap<String,Object>> listMap = new ArrayList<>();
FeatureIterator<SimpleFeature> iterator = col.features();
while(iterator.hasNext()) {
SimpleFeature feature = iterator.next();
//获取属性
Iterator<Property> it = feature.getProperties().iterator();
LinkedHashMap<String, Object> data = new LinkedHashMap<>();
String geometry = "";
while (it.hasNext()) {
Property pro = it.next();
if (pro.getValue() instanceof Point) {//点
geometry = "'" +((Point) pro.getValue()).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else if (pro.getValue() instanceof Polygon) {//面
geometry = "'"+((Polygon) pro.getValue()).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else if (pro.getValue() instanceof MultiPolygon) {//多面
geometry = "'"+((MultiPolygon) pro.getValue()).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else if (pro.getValue() instanceof LineString) {//线
geometry = "'" +((LineString) pro.getValue()).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else {
if(pro.getValue() instanceof Date){
Date myDate = (Date)pro.getValue();
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strDate3 = sdf3.format(myDate);
data.put(pro.getName().toString(),strDate3);
}else{
data.put(pro.getName().toString(),pro.getValue());
}
}
}
//System.out.println(data);
listMap.add(data);
}
return listMap;
}
//方法二:
//返回属性值
public List<LinkedHashMap<String,Object>> getAttirbutes2(String srs, FeatureCollection col){
//srs="EPSG:4326"
List<LinkedHashMap<String,Object>> listMap = new ArrayList<>();
//另外一种循环start
SimpleFeatureCollection sfc = (SimpleFeatureCollection)col;
// 获取当前矢量数据有哪些属性字段值
List<AttributeDescriptor> attributes = sfc.getSchema().getAttributeDescriptors();
// 拿到迭代器
SimpleFeatureIterator simpleFeatureIterator = sfc.features();
// 遍历每一个要素
while(simpleFeatureIterator.hasNext()) {
SimpleFeature simpleFeature = simpleFeatureIterator.next();
LinkedHashMap<String, Object> data = new LinkedHashMap<>();
// java8新特性流api
attributes.stream().forEach((a) -> {
Object tempobj = simpleFeature.getAttribute(a.getLocalName());
// 依次读取这个shape中每一个属性值,当然这个属性值,可以处理其它业务
if(a.getLocalName().indexOf("geom")>=0){
String geometry = "";
if (tempobj instanceof Point) {//点
geometry = "'" +((Point) tempobj).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else if (tempobj instanceof Polygon) {//面
geometry = "'"+((Polygon) tempobj).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else if (tempobj instanceof MultiPolygon) {//多面
geometry = "'"+((MultiPolygon) tempobj).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
} else if (tempobj instanceof LineString) {//线
geometry = "'" +((LineString) tempobj).toString()+ "'"+","+srs.substring(srs.indexOf(":")+1);
data.put("geom",geometry);
}
}else{
if(tempobj instanceof Date){
Date myDate = (Date)tempobj;
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strDate3 = sdf3.format(myDate);
data.put(a.getLocalName(),strDate3);
}else{
data.put(a.getLocalName(),tempobj);
}
// System.out.println(a.getLocalName() + ":" + simpleFeature.getAttribute(a.getLocalName()));
}
});
listMap.add(data);
}
return listMap;
}
//查询 CQL
public Filter ReturnFilter(String sql)throws Exception{
String wkt = "POLYGON ((113.17574362102584 23.135924459989738, 113.07445367113468 22.981863911800943, 113.3121749821035 22.932375044753726, 113.3907263718155 23.073180341529934, 113.17574362102584 23.135924459989738))";
Filter filter = null;
// 相交
filter = CQL.toFilter( "OBJECTID = 5 or INTERSECTS(the_geom," + wkt + ")");
if(sql!=null || sql!=""){
filter = CQL.toFilter(sql);
}
// 在10公里以内
// Filter filter = CQL.toFilter( "DWITHIN(the_geom," + wkt + ", 10, kilometers)");
return filter;
}
//查询 使用openGIS FilterFactory2
public Filter ReturnFilter2(){
Filter filter = ff.greaterOrEqual(ff.property("OBJECTID"), ff.literal(5));
return filter;
}

public static SimpleFeatureType createType(Class<?> c, String layerName) {
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setCRS(DefaultGeographicCRS.WGS84);
builder.add("FID",String.class);
builder.add("the_geom", c);
// 设置了图层的名字
builder.setName(layerName);
SimpleFeatureType simpleFeatureType = builder.buildFeatureType();
return simpleFeatureType;
}
  //生成shp
public static void createShp(String shpPath, SimpleFeatureCollection collection) throws IOException {
File shpFile = new File(shpPath);
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
SimpleFeatureType simpleFeatureType = collection.getSchema();
// 创造shpstore需要的参数
Map<String, Serializable> params = new HashMap<>();
params.put("url", shpFile.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
ShapefileDataStore newDataStore =
(ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
newDataStore.createSchema(simpleFeatureType);
Transaction transaction = new DefaultTransaction("create");
String typeName = newDataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
featureStore.setTransaction(transaction);
featureStore.addFeatures(collection);
featureStore.setTransaction(transaction);
transaction.commit();
transaction.close();
}
/  //这里也是读取shp
public static SimpleFeatureCollection readFeatureCollection(String shpPath) {
SimpleFeatureCollection featureCollection = null;
File shpFile = new File(shpPath);
try {
ShapefileDataStore shapefileDataStore = new ShapefileDataStore(shpFile.toURI().toURL());
// 设置编码,防止属性的中文字符出现乱码
shapefileDataStore.setCharset(Charset.forName("UTF-8"));
// 这个typeNamae不传递,默认是文件名称
FeatureSource featuresource = shapefileDataStore.getFeatureSource(shapefileDataStore.getTypeNames()[0]);
featureCollection = (SimpleFeatureCollection) featuresource.getFeatures();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return featureCollection;
}

}

在测试类,测试

@Autowired
    GeoToolsMethod geoToolsMethod;

//测试geoTools封装好的方法
    @Test
    public void Test_geoToolsMethod() throws Exception{
        //测试读取shp
        FeatureSource<SimpleFeatureType, SimpleFeature> featureSource=geoToolsMethod.ReadShpFile("D:\\ceshi\\dwq0606");
        String srs = CRS.lookupIdentifier(featureSource.getSchema().getCoordinateReferenceSystem(),true);  // 获取EPSG
        System.out.println(srs);
        FeatureCollection collection = featureSource.getFeatures();
        long startTime = System.currentTimeMillis();
        //测试获取getAttributes
        List<LinkedHashMap<String,Object>> listAttr = geoToolsMethod.getAttirbutes(srs,collection);
        long endTime = System.currentTimeMillis();
        System.out.println("运行时长:"+(endTime-startTime)+"ms"); //1128ms
        startTime = System.currentTimeMillis();
        //测试获取getAttributes2
        List<LinkedHashMap<String,Object>> listAttr2 = geoToolsMethod.getAttirbutes2(srs,collection);
        endTime = System.currentTimeMillis();
        System.out.println("运行时长:"+(endTime-startTime)+"ms"); //980ms 1015
        //System.out.println(listAttr);
    }
View Code

 

geotools做geometry 的计算距离,取交集、合并几何、difference

//做geometry 的计算距离,取交集、合并几何、difference
    @Test
    public void GeometryOperate() throws Exception{
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
        //创建一条线
        List<Coordinate> points1 = new ArrayList<Coordinate>();
        points1.add(new Coordinate(0,0));
        points1.add(new Coordinate(1,3));
        points1.add(new Coordinate(2,3));
        Coordinate[] coords  = (Coordinate[]) points1.toArray(new Coordinate[points1.size()]);
        LineString line1 = geometryFactory.createLineString(coords);
        //创建第二条线
        List<Coordinate> points2 = new ArrayList<Coordinate>();
        points2.add(new Coordinate(3,0));
        points2.add(new Coordinate(3,3));
        points2.add(new Coordinate(5,6));
        Coordinate[] coords2  = (Coordinate[]) points2.toArray(new Coordinate[points2.size()]);
        LineString line2 = geometryFactory.createLineString(coords2);
//        返回(A)与(B)中距离最近的两个点的距离
        System.out.println(line1.distance(line2));//out 1.0
//        两个几何对象的交集
        System.out.println(line1.intersection(line2));//out GEOMETRYCOLLECTION EMPTY
//        几何对象合并
        Geometry lineunion = line1.union(line2);
        System.out.println(lineunion); //out MULTILINESTRING ((0 0, 1 3, 2 3), (3 0, 3 3, 5 6))
        //在A几何对象中有的,但是B几何对象中没有
        System.out.println(line1.difference(line2));//out LINESTRING (0 0, 1 3, 2 3)
        System.out.println(lineunion.difference(line2));//out LINESTRING (0 0, 1 3, 2 3)
        //交集
        System.out.println(lineunion.intersection(line2));//out MULTILINESTRING ((3 0, 3 3), (3 3, 5 6))

        WKTReader reader = new WKTReader(geometryFactory);
        Polygon geometry1 = (Polygon) reader.read("POLYGON((0 0, 2 0 ,2 2, 0 2,0 0))");
        Polygon geometry2 = (Polygon) reader.read("POLYGON((0 0, 4 0 , 4 1, 0 1, 0 0))");
        OverlayOp op = new OverlayOp(geometry1,geometry2);
        Geometry g =op.getResultGeometry(OverlayOp.INTERSECTION);//POLYGON ((2 0, 0 0, 0 1, 2 1, 2 0))
        //Geometry g2 = op.getResultGeometry(OverlayOp.UNION);
        //Geometry g3 = op.getResultGeometry(OverlayOp.DIFFERENCE);
        //Geometry g4 = op.getResultGeometry(OverlayOp.SYMDIFFERENCE);
        //PlanarGraph p = op.getGraph(); //图<v,e

        //LineMerger 线路合并,线路之间不能有交点,并且只在线路末尾有公共交点
        // lineMerger 和union区别,union可以在两条相交的线中生成交点(noded)
        WKTReader wktReader = new WKTReader();
        LineMerger lineMerger = new LineMerger();
        List<Geometry> list = new ArrayList<Geometry>();
        list.add(wktReader.read("LINESTRING (3 3,2 2,0 0)"));
        list.add(wktReader.read("LINESTRING (3 3,6 6,0 10)"));
        list.add(wktReader.read("LINESTRING (0 10,3 1,10 1)"));
        lineMerger.add(list);
        Collection<Geometry> mergerLineStrings = lineMerger.getMergedLineStrings();
        for (Geometry tempg : mergerLineStrings) {
            System.out.println(tempg.toText()); //LINESTRING (0 0, 2 2, 3 3, 6 6, 0 10, 3 1, 10 1)
        }

    }
View Code