Geotools操作總結(jié)

我家的那條河

前言

最近工作上需要用到geotools工具進(jìn)行開發(fā),發(fā)現(xiàn)資料真的少得可憐,可能很少人用吧。后來發(fā)現(xiàn)這個(gè)工具類對于簡單的地理信息處理還是蠻厲害,高難度(縫隙檢測、道路線壓蓋面之類,這些可以用arcpy或者ArcEngine)的就壓根沒有對應(yīng)的api了。本著既然用過了就總結(jié)一下,萬一以后遇到就直接可以用了唄。

正文

1、 從shp文件讀取要素集

這里主要是針對shp文件,操作類似于Java連接數(shù)據(jù)庫,比如mybatis的sqlSession

 /**
     * 獲取源shp的要素
     */
    private SimpleFeatureStore getSFeatureSource(String layerShpPath) {
        try {
            String path = layerShpPath + ".shp";
            File file = new File(path);
            if (file.exists()) {
                Map params = new HashMap();
                params.put("url", file.toURI().toURL());
                for (Iterator i = DataStoreFinder.getAvailableDataStores(); i.hasNext(); ) {
                    DataStoreFactorySpi factory = (DataStoreFactorySpi) i.next();
                    if (factory.canProcess(params)) {
                        //獲取到shp數(shù)據(jù)源
                        DataStore dataStore = factory.createNewDataStore(params);
                        // 設(shè)置編碼后可以正確讀取
                        ((ShapefileDataStore) dataStore).setCharset(Charset.forName("GBK"));
                        //根據(jù)圖層名稱來獲取要素的source
                        SimpleFeatureStore featureSource = (SimpleFeatureStore) dataStore.getFeatureSource(dataStore.getTypeNames()[0]);
                        return featureSource;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2、輸出要素到shp文件

輸出文件就相當(dāng)于我們平時(shí)定義好自己的表結(jié)構(gòu),然后獲取連接數(shù)據(jù)庫的連接,將表數(shù)據(jù)插入到shp文件中。

/**
     * 獲取到輸出的ds
     *
     * @param targetFilePath
     * @param sourceSchema 指定表映射
     * @return
     * @throws IOException
     */
    public static ShapefileDataStore getOutputDataStore(String targetFilePath, SimpleFeatureType sourceSchema) {
        try {
            File targetFile = new File(targetFilePath);
            if (!targetFile.exists()) {
                targetFile.createNewFile();
            }
            Map<String, Serializable> params1 = new HashMap<String, Serializable>();
            params1.put(ShapefileDataStoreFactory.URLP.key, targetFile.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params1);
            // create new schema
            SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
            builder.setName(sourceSchema.getName());
            builder.setSuperType((SimpleFeatureType) sourceSchema.getSuper());
            //自定義字段名
            builder.add("rowId", Integer.class);
            builder.add("ruleId", Integer.class);
            builder.add("sId", String.class);
            builder.add("curFld", String.class);
            builder.add("curVal", String.class);
            builder.add("refLayCode", String.class);
            builder.add("refLayer", String.class);
            builder.add("errDesc", String.class);
            builder.add(sourceSchema.getDescriptor("the_geom"));
            SimpleFeatureType nSchema = builder.buildFeatureType();
            ds.createSchema(nSchema);//將圖層表頭設(shè)置給target shape
            ds.setCharset(Charset.forName("GBK"));
            return ds;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

3、獲取要素字段屬性

獲取shp文件的字段屬性可以通過getSchema().getAttributeDescriptors()來完成。

List<AttributeDescriptor> attrList = sourceFeatureStore.getSchema().getAttributeDescriptors();
for (AttributeDescriptor attr : attrList) {
      //字段名
      String fieldName =  attr.getLocalName();
      //字段類型
      String typeName = attr.getType().getBinding().getSimpleName();
      //字段限制
      String restr = attr.getType().getRestrictions().toString();
}

4、遍歷要素集

這里的遍歷是用迭代器來實(shí)現(xiàn)的,所以務(wù)必記得遍歷完之后需要關(guān)閉數(shù)據(jù)連接,不然會報(bào)警告的。

SimpleFeatureCollection features = sourceFeatureStore.getFeatures();
 SimpleFeatureIterator iterator = features.features();
while (iterator .hasNext()) {
      SimpleFeature next = iterator.next();
      Object geom = next.getAttribute(geometryPropertyName);
}

iterator.close();

5、按條件查詢要素集

這里類似于mybatis的查詢數(shù)據(jù)庫,這里可以實(shí)現(xiàn)空間檢索,也就是說通過經(jīng)緯度圖形,可以找到與它有相交的周邊的所有要素。

Object geom = feature.getAttribute(geometryPropertyName);
Geometry geometry = reader.read(geom.toString());
Geometry boundary = geometry.getBoundary();
Filter filter = ff.intersects(ff.property(geometryPropertyName), ff.literal(boundary));
SimpleFeatureCollection features = sourceFeatureStore.getFeatures();
 SimpleFeatureIterator iterator = features.features();
while (iterator.hasNext()) {
      SimpleFeature next = iterator.next();
      Object geom = next.getAttribute(geometryPropertyName);
}

6、構(gòu)建或獲取要素幾何圖形

一、SimpleFeatureBuilder方式創(chuàng)建

        //創(chuàng)建GeometryFactory工廠
        GeometryFactory geometryFactory = new GeometryFactory();
        SimpleFeatureCollection collection =null;
        //獲取類型
        SimpleFeatureType TYPE = featureSource.getSchema();
        System.out.println(TYPE);
        //創(chuàng)建要素集合
        List<SimpleFeature> features = new ArrayList<>();
        //創(chuàng)建要素模板
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
        //創(chuàng)建要素并添加道集合
        double latitude = Double.parseDouble("39.9");
        double longitude = Double.parseDouble("116.3");
        String name ="beijing";
        int number = Integer.parseInt("16");
        //創(chuàng)建一個(gè)點(diǎn)geometry
        Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude));
        //添加的數(shù)據(jù)一定按照SimpleFeatureType給的字段順序進(jìn)行賦值
        //添加name屬性
        featureBuilder.add(name);
        //添加number屬性
        featureBuilder.add(number);
        //添加geometry屬性
        featureBuilder.add(point);
        //構(gòu)建要素
        SimpleFeature feature = featureBuilder.buildFeature(null);

Note:featureBuilder添加的數(shù)據(jù)一定按照SimpleFeatureType給的字段順序進(jìn)行賦值!?。。。。。。。。?/p>

二、getFeatureWriter方式創(chuàng)建

            SimpleFeatureSource featureSource = null;
            //根據(jù)圖層名稱來獲取要素的source
            featureSource = shpDataStore.getFeatureSource (typeName);
            //根據(jù)參數(shù)創(chuàng)建shape存儲空間
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            SimpleFeatureType sft = featureSource.getSchema();
            //創(chuàng)建要素模板
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            //設(shè)置坐標(biāo)系
            tb.setCRS(DefaultGeographicCRS.WGS84);            
            tb.setName("shapefile");
                        //創(chuàng)建
            ds.createSchema(tb.buildFeatureType());
            //設(shè)置編碼
            ds.setCharset(charset);
             
            //設(shè)置Writer,并設(shè)置為自動提交
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
             //循環(huán)寫入要素
            while (itertor.hasNext())
            {
                //獲取要寫入的要素
                SimpleFeature feature = itertor.next();
                //將要寫入位置
                SimpleFeature featureBuf = writer.next();
                //設(shè)置寫入要素所有屬性
                featureBuf.setAttributes(feature.getAttributes());
                //獲取the_geom屬性的值
                Geometry geo =(Geometry) feature.getAttribute("the_geom");
                Geometry geoBuffer = geoR.calBuffer(geo, 0.1);
                System.out.println(geoBuffer);
                //重新覆蓋the_geom屬性的值,這里的geoBuffer必須為Geometry類型
                featureBuf.setAttribute("the_geom", geoBuffer);
            } 
            //將所有數(shù)據(jù)寫入
            writer.write();
            //關(guān)閉寫入流
            writer.close();
            itertor.close();
        }
        catch(Exception e){
            e.printStackTrace();
        }

總結(jié):
兩種都差不多,個(gè)人感覺第二種方式創(chuàng)建更為靈活一點(diǎn),關(guān)于第一種必須保證寫入字段的Value的順序,第二種是采用Key,value方式更為保險(xiǎn)安全,第一種可讀性更為好點(diǎn)。

7、獲取幾何圖形邊界

沒啥好講的,就是為了直接掉API

Geometry geometry = reader.read("MULTIPOINT(109.013388 32.715519,119.32488 31.435678)");
Geometry boundary = geometry.getBoundary();

8、JWT幾何關(guān)系

幾何信息和拓?fù)潢P(guān)系是地理信息系統(tǒng)中描述地理要素的空間位置和空間關(guān)系的不可缺少的基本信息。其中幾何信息主要涉及幾何目標(biāo)的坐標(biāo)位置、方向、角度、距離和面積等信息,它通常用解析幾何的方法來分析。而空間關(guān)系信息主要涉及幾何關(guān)系的“相連”、“相鄰”、“包含”等信息,它通常用拓?fù)潢P(guān)系或拓?fù)浣Y(jié)構(gòu)的方法來分析。拓?fù)潢P(guān)系是明確定的

幾何關(guān)系 說明
相等(Equals): 幾何形狀拓?fù)渖舷嗟取?/td>
脫節(jié)(Disjoint): 幾何形狀沒有共有的點(diǎn)。
相交(Intersects): 幾何形狀至少有一個(gè)共有點(diǎn)(區(qū)別于脫節(jié))
接觸(Touches): 幾何形狀有至少一個(gè)公共的邊界點(diǎn),但是沒有內(nèi)部點(diǎn)。
交叉(Crosses): 幾何形狀共享一些但不是所有的內(nèi)部點(diǎn)。
內(nèi)含(Within): 幾何形狀A(yù)的線都在幾何形狀B內(nèi)部。
包含(Contains): 幾何形狀B的線都在幾何形狀A(yù)內(nèi)部(區(qū)別于內(nèi)含)
重疊(Overlaps): 幾何形狀共享一部分但不是所有的公共點(diǎn),而且相交處有他們自己相同的區(qū)域。
package com.mapbar.geo.jts;
 
import org.geotools.geometry.jts.JTSFactoryFinder;
 
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
 
/**  
 * Class GeometryRelated.java 
 * Description 二元比較集合。二元比較以兩個(gè)幾何對象作為參數(shù),返回一個(gè)Boolean類型的值,
 * 來指明這兩個(gè)幾何對象是否具有指定的空間關(guān)系。支持的空間關(guān)系包括:
 * equals、disjoint、intersects, touches, crosses, within, contains, overlaps
 */
public class GeometryRelated {
    
    private GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
    
    public Point createPoint(String lon,String lat){
        Coordinate coord = new Coordinate(Double.parseDouble(lon), Double.parseDouble(lat));
        Point point = geometryFactory.createPoint( coord );
        return point;
    }
    
    /**
     *  will return true as the two line strings define exactly the same shape.
     *  兩個(gè)幾何對象是否是重疊的
     * @return
     * @throws ParseException
     */
    public boolean equalsGeo() throws ParseException{
        WKTReader reader = new WKTReader( geometryFactory );
        LineString geometry1 = (LineString) reader.read("LINESTRING(0 0, 2 0, 5 0)");
        LineString geometry2 = (LineString) reader.read("LINESTRING(5 0, 0 0)");
        // return geometry1 ==geometry2;  false
        //check if two geometries are exactly equal; right down to the coordinate level.
        // return geometry1.equalsExact(geometry2);   false
        return geometry1.equals(geometry2);//true
    }
    
    /**
     * The geometries have no points in common
     * 幾何對象沒有交點(diǎn)(相鄰)
     * @return
     * @throws ParseException
     */
    public boolean disjointGeo() throws ParseException{
        WKTReader reader = new WKTReader( geometryFactory );
        LineString geometry1 = (LineString) reader.read("LINESTRING(0 0, 2 0, 5 0)");
        LineString geometry2 = (LineString) reader.read("LINESTRING(0 1, 0 2)");
        return geometry1.disjoint(geometry2);
    }
    
    /**
     * The geometries have at least one point in common.
     * 至少一個(gè)公共點(diǎn)(相交)
     * @return
     * @throws ParseException
     */
    public boolean intersectsGeo() throws ParseException{
        WKTReader reader = new WKTReader( geometryFactory );
        LineString geometry1 = (LineString) reader.read("LINESTRING(0 0, 2 0, 5 0)");
        LineString geometry2 = (LineString) reader.read("LINESTRING(0 0, 0 2)");
        Geometry interPoint = geometry1.intersection(geometry2);//相交點(diǎn)
        System.out.println(interPoint.toText());//輸出 POINT (0 0)
        return geometry1.intersects(geometry2);
    }
    /**
     * @param args
     * @throws ParseException 
     */
    public static void main(String[] args) throws ParseException {
        GeometryRelated gr = new GeometryRelated();
        System.out.println(gr.equalsGeo());
        System.out.println(gr.disjointGeo());
        System.out.println(gr.intersectsGeo());
    }
 
}

9、Geotools創(chuàng)建Feature的兩種方式

一、SimpleFeatureBuilder方式創(chuàng)建

        //創(chuàng)建GeometryFactory工廠
        GeometryFactory geometryFactory = new GeometryFactory();
        SimpleFeatureCollection collection =null;
        //獲取類型
        SimpleFeatureType TYPE = featureSource.getSchema();
        System.out.println(TYPE);
        //創(chuàng)建要素集合
        List<SimpleFeature> features = new ArrayList<>();
        //創(chuàng)建要素模板
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
        //創(chuàng)建要素并添加道集合
        double latitude = Double.parseDouble("39.9");
        double longitude = Double.parseDouble("116.3");
        String name ="beijing";
        int number = Integer.parseInt("16");
        //創(chuàng)建一個(gè)點(diǎn)geometry
        Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude));
        //添加的數(shù)據(jù)一定按照SimpleFeatureType給的字段順序進(jìn)行賦值
        //添加name屬性
        featureBuilder.add(name);
        //添加number屬性
        featureBuilder.add(number);
        //添加geometry屬性
        featureBuilder.add(point);
        //構(gòu)建要素
        SimpleFeature feature = featureBuilder.buildFeature(null);

Note:featureBuilder添加的數(shù)據(jù)一定按照SimpleFeatureType給的字段順序進(jìn)行賦值?。。。。。。。。。?br> 二、getFeatureWriter方式創(chuàng)建

            SimpleFeatureSource featureSource = null;
            //根據(jù)圖層名稱來獲取要素的source
            featureSource = shpDataStore.getFeatureSource (typeName);
            //根據(jù)參數(shù)創(chuàng)建shape存儲空間
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            SimpleFeatureType sft = featureSource.getSchema();
            //創(chuàng)建要素模板
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            //設(shè)置坐標(biāo)系
            tb.setCRS(DefaultGeographicCRS.WGS84);            
            tb.setName("shapefile");
                        //創(chuàng)建
            ds.createSchema(tb.buildFeatureType());
            //設(shè)置編碼
            ds.setCharset(charset);
             
            //設(shè)置Writer,并設(shè)置為自動提交
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
             //循環(huán)寫入要素
            while (itertor.hasNext())
            {
                //獲取要寫入的要素
                SimpleFeature feature = itertor.next();
                //將要寫入位置
                SimpleFeature featureBuf = writer.next();
                //設(shè)置寫入要素所有屬性
                featureBuf.setAttributes(feature.getAttributes());
                //獲取the_geom屬性的值
                Geometry geo =(Geometry) feature.getAttribute("the_geom");
                Geometry geoBuffer = geoR.calBuffer(geo, 0.1);
                System.out.println(geoBuffer);
                //重新覆蓋the_geom屬性的值,這里的geoBuffer必須為Geometry類型
                featureBuf.setAttribute("the_geom", geoBuffer);
            } 
            //將所有數(shù)據(jù)寫入
            writer.write();
            //關(guān)閉寫入流
            writer.close();
            itertor.close();
        }
        catch(Exception e){
            e.printStackTrace();
        }

總結(jié):
兩種都差不多,個(gè)人感覺第二種方式創(chuàng)建更為靈活一點(diǎn),關(guān)于第一種必須保證寫入字段的Value的順序,第二種是采用Key,value方式更為保險(xiǎn)安全,第一種可讀性更為好點(diǎn)。

參考文章

https://blog.csdn.net/weixin_40184249/article/details/84480652
http://www.aiuxian.com/article/p-455672.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容