Java GeoTools实践-合并(Union)featureCollection(成功)两个featureCollection取交(intersection)(失败)

24 篇文章 5 订阅
6 篇文章 0 订阅

项目需要对多个shp文件做合并和求交,而geotools常用的几何工具都是针对单个Geometry的,若手动获取shp里的要素集合并遍历每个要素的geometry,可能效率会很低,所以找到了geotools的process工具,测试了一下

合并两个shp文件

用到的工具
UnionFeatureCollection
需要的依赖

        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-process</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-process-feature</artifactId>
            <version>${geotools.version}</version>
        </dependency>

代码

    // ShapeFileReaderUtils和ShapeFileWriterUtils是自己定义的,内容见下面地址
    // https://blog.csdn.net/Neuromancerr/article/details/119981046
    public static void mergeTest() throws Exception {
        // 待合并的两个文件地址
        String pathHead = "D:\\mapresources\\test\\";
        String file1 = pathHead + "test1.shp";
        String file2 = pathHead + "test2.shp";
        // 获取要素集
        ContentFeatureCollection features1 = ShapeFileReaderUtils.getFeatureSourceFromShapeFile(file1).getFeatures();
        ContentFeatureCollection features2 = ShapeFileReaderUtils.getFeatureSourceFromShapeFile(file2).getFeatures();
        // 定义输出路径
        String outPut = "D:\\mapresources\\test\\testOut.shp";
        // 初始化
        UnionFeatureCollection collection2 = new UnionFeatureCollection();
        // 执行合并
        SimpleFeatureCollection result = collection2.execute(
                features1,
                features2
        );
        // 输出结果生成shp文件
        ShapeFileWriterUtils.buildShp(result, outPut);
    }

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

结果成功
合并前
合并后

两个shp求交

用到的是 IntersectionFeatureCollection
以下是测试代码

// ShapeFileReaderUtils和ShapeFileWriterUtils是自己定义的,内容见下面地址
// https://blog.csdn.net/Neuromancerr/article/details/119981046
public static void mergeTest() throws Exception {
    // 待合并的两个文件地址
    String pathHead = "D:\\mapresources\\test\\";
    String file1 = pathHead + "test1.shp";
    String file2 = pathHead + "test2.shp";
    // 获取要素集
    ContentFeatureCollection features1 = ShapeFileReaderUtils.getFeatureSourceFromShapeFile(file1).getFeatures();
    ContentFeatureCollection features2 = ShapeFileReaderUtils.getFeatureSourceFromShapeFile(file2).getFeatures();
    // 定义输出路径
    String outPut = "D:\\mapresources\\test\\testOut3.shp";
    // 初始化
    IntersectionFeatureCollection collection = new IntersectionFeatureCollection();
    List<String> attr1 = new ArrayList<>();
    features1.features().next().getAttributes().forEach(attr -> {
        attr1.add(attr.toString());
    });
    List<String> attr2 = new ArrayList<>();
    features2.features().next().getAttributes().forEach(attr -> {
        attr2.add(attr.toString());
    });
    // 执行合并
    SimpleFeatureCollection result = collection.execute(
            features1,
            features2,
            attr1,
            attr2,
            IntersectionFeatureCollection.IntersectionMode.FIRST,
            true,
            true
    );

    // 这一步是为了消除多边形自相交的几何错误
    SimpleFeature[] resArr = (SimpleFeature[]) result.toArray();
    DefaultFeatureCollection res2 = new DefaultFeatureCollection();
    for (SimpleFeature simpleFeature : resArr) {
        simpleFeature.setDefaultGeometry(parseGeom((Geometry) simpleFeature.getDefaultGeometry()));
        res2.add(simpleFeature);
    }

    // 输出结果生成shp文件
    ShapeFileWriterUtils.buildShp(res2, outPut);
}
// Geometry转multiPolygon
private static MultiPolygon parseGeom(Geometry geometry) {

    MultiPolygon multiPolygon = null;
    // 防止自相交
    geometry = geometry.intersection(geometry);

    if (geometry.getGeometryType().equals("MultiPolygon")) {
        multiPolygon = (MultiPolygon) geometry;
    } else if (geometry.getGeometryType().equals("Polygon")) {
        GeometryFactory gf = new GeometryFactory();
        Polygon[] polys = new Polygon[1];
        polys[0] = (Polygon) geometry;
        multiPolygon = gf.createMultiPolygon(polys);
    }
    return multiPolygon;
}

但结果并不是期望中两个要素的相交部分,而是IntersectionFeatureCollection.execute()方法传入的第二个要素集的整个复制。这把我搞懵了,经过各种参数调整测试,都没啥用,只能暂时放弃。

求交的另一种思路

用的方法比较笨,先用UnionFeatureCollection把需要求交的shp都合成一个巨大的数据集,然后遍历其中的要素,分别对每个geometry求交。我是这么写的

// 传入一整个要素集
private void mergeShp(DefaultFeatureCollection features) throws Exception {
    String outPut = "D:\\mapresources\\jiangsu\\output\\test.shp";
    // 输出要素集
    DefaultFeatureCollection featureCollection = new DefaultFeatureCollection();
    // 输入要素集转数组
    SimpleFeature[] featuresArray = new SimpleFeature[features.size()];
    featuresArray = features.toArray(featuresArray);
    for (int i = 0; i < featuresArray.length; i++) {
        // 取出单个要素和他的geometry
        SimpleFeature feature1 = featuresArray[i];
        MultiPolygon polygon1 = parseGeom((Geometry) feature1.getDefaultGeometry());
        boolean intersected = false;
        for (int j = 0; j < i; j++) {
            SimpleFeature feature2 = featuresArray[j];
            MultiPolygon polygon2 = parseGeom((Geometry) feature2.getDefaultGeometry());
            assert polygon1 != null;
            assert polygon2 != null;
            if (polygon1.intersects(polygon2)) {
                try {
                    intersected = true;
                    SimpleFeature newFeature;
                    // 按照定义的mdate字段,较新的属性覆盖旧的
                    if (Long.parseLong((String) feature1.getAttribute("mdate")) > Long.parseLong(((String) feature2.getAttribute("mdate")))) {
                        newFeature = SimpleFeatureBuilder.copy(feature1);
                    } else {
                        newFeature = SimpleFeatureBuilder.copy(feature2);
                    }
                    newFeature.setDefaultGeometry(polygon1.union(polygon2));
                    featureCollection.add(newFeature);
                    System.out.println("featureCollection add:" + newFeature.getID() + " intersected " + feature1.getID() + "," + feature2.getID());
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        }

        if (!intersected) {
            featureCollection.add(feature1);
            System.out.println("featureCollection add:" + feature1.getID());
        }
    }

    ShapeFileWriterUtils.buildShp(featureCollection, outPut);
}

问题首先是效率,对两个各有799个要素的shp求交,耗时数分钟。同时若有多个几何同时相交,会重复产生新要素,比如A、B、C相交,会产生A-B和B-C两个要素,B的部分重负了。
虽然算法上可以并应当优化,但负责python的同事可以接手这部分工作,遂放弃。在这里记录一下。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值