All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.baozi926.geo.FeatureCollectionUtil Maven / Gradle / Ivy

package io.github.baozi926.geo;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.BooleanUtil;
import io.github.baozi926.geo.exception.GeoException;
import org.geotools.data.DataUtilities;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.Geometries;
import org.geotools.util.logging.Logging;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.operation.valid.IsValidOp;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.FeatureType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

/**
 * @author 蔡惠民
 * 用于处理featureCollection的工具类
 */
public class FeatureCollectionUtil {

    private FeatureCollectionUtil() {
        throw new IllegalStateException("Utility class");
    }

    private static final Logger LOGGER = Logging.getLogger(FeatureCollectionUtil.class);

    public static SimpleFeatureCollection makeValid(SimpleFeatureCollection featureCollection) {


        try {
            Geometries geometryType = getGeometryType(featureCollection);

            switch (geometryType) {
                case MULTIPOLYGON:
                case POLYGON: {
                    List results = new ArrayList<>();

                    List geometryList = readGeometries(featureCollection);

                    for (Geometry target : geometryList) {
                        results.add(GeometryUtil.validate(target));
                    }

                    return getSimpleFeatureCollection(results);

                }
                case POINT:
                case MULTIPOINT:
                default:
                    break;
            }
            return featureCollection;
        } catch (Exception exp) {
            return featureCollection;
        }

    }

    // 剪裁不应该丢失属性
    public static SimpleFeatureCollection intersection(SimpleFeatureCollection featureCollection, Geometry intersectionGeometry, String geometryType) {

        if (intersectionGeometry == null) {
            return featureCollection;
        }

        List geometryList = readGeometries(featureCollection);
        List intersectionGeometryList = new ArrayList<>();
        for (Geometry geometry : geometryList) {
            if (geometry != null) {
                IsValidOp isValidOp = new IsValidOp(geometry);
                if (BooleanUtil.isTrue(isValidOp.isValid())) {

                    Geometry intersectionResultGeometry = geometry.intersection(intersectionGeometry);
                    if (intersectionResultGeometry.isValid()) {
                        intersectionGeometryList.add(intersectionResultGeometry);
                    }
                }
            }


        }

        return getSimpleFeatureCollection(intersectionGeometryList, geometryType);
    }

    public static SimpleFeatureCollection union(SimpleFeatureCollection featureCollection) throws Exception {

        return union(featureCollection, null);


    }

    public static SimpleFeatureCollection union(SimpleFeatureCollection featureCollection, String geometryType) throws GeoException {

        List geometryList = readGeometries(featureCollection);

        if (!CharSequenceUtil.isEmpty(geometryType)) {
            List geometryListAfterProcess = new ArrayList<>();

            for (Geometry geometry : geometryList) {

                if (geometry != null) {
                    if (CharSequenceUtil.endWith(geometryType, geometry.getGeometryType())) {
                        geometryListAfterProcess.add(GeometryUtil.validate(geometry));
                    } else if (CharSequenceUtil.equals(geometry.getGeometryType(), "GeometryCollection")) {

                        String suffixGeometryType = CharSequenceUtil.removePrefix(geometryType, "Multi");

                        for (int index = 0; index < geometry.getNumGeometries(); index++) {
                            Geometry tmp = geometry.getGeometryN(0);
                            //如果是同一类型的,就加进来
                            if (CharSequenceUtil.equals(geometryType, tmp.getGeometryType()) || CharSequenceUtil.equals(suffixGeometryType, tmp.getGeometryType())) {
                                geometryListAfterProcess.add(GeometryUtil.validate(tmp));
                            }

                        }
                    }
                }


            }
            return getSimpleFeatureCollection(GeometryUtil.union(geometryListAfterProcess), geometryType);
        }


        return getSimpleFeatureCollection(GeometryUtil.union(geometryList), geometryType);


    }


    /**
     * 根据属性合并
     *
     * @param featureCollection featureCollection
     * @param mergeField        mergeField
     * @param geometryType      geometryType
     * @param mergeFieldType    mergeFieldType
     * @return SimpleFeatureCollection
     * @throws GeoException    GeoException
     * @throws SchemaException SchemaException
     */
    public static FeatureCollection mergeByField(FeatureCollection featureCollection, String mergeField, String geometryType, String mergeFieldType) throws GeoException, SchemaException {
        return mergeByField(DataUtilities.collection(featureCollection), mergeField, geometryType, mergeFieldType);
    }

    /**
     * 根据属性合并
     *
     * @param featureCollection featureCollection
     * @param mergeField        mergeField
     * @param geometryType      geometryType
     * @param mergeFieldType    mergeFieldType
     * @return SimpleFeatureCollection
     * @throws GeoException    GeoException
     * @throws SchemaException SchemaException
     */
    public static SimpleFeatureCollection mergeByField(SimpleFeatureCollection featureCollection,
                                                       String mergeField,
                                                       String geometryType,
                                                       String mergeFieldType) throws GeoException, SchemaException {


        if (CharSequenceUtil.isEmpty(mergeField)) {
            return featureCollection;
        }

        if (CharSequenceUtil.isEmpty(mergeFieldType)) {
            mergeFieldType = featureCollection.getSchema().getDescriptor(mergeField).getType().getBinding().getSimpleName();

            //Long 会报错。。
            if (CharSequenceUtil.equals(mergeFieldType, "Long")) {
                mergeFieldType = "Integer";
            }
        }


        Map> mergeMap = new HashMap<>();

        if (featureCollection != null) {

            SimpleFeatureIterator iterator = featureCollection.features();


            try {
                while (iterator.hasNext()) {
                    SimpleFeature feature = iterator.next();

                    Object key = feature.getAttribute(mergeField);

                    mergeMap.computeIfAbsent(key, k -> new ArrayList<>());

                    List data = mergeMap.get(key);
                    //如果不做validate可能会出现自相交的问题而导致异常

                    Geometry validateGeometry = GeometryUtil.validate((Geometry) feature.getDefaultGeometry());
                    if (validateGeometry != null) {
                        data.add(validateGeometry);
                    }


                }
            } finally {
                iterator.close();
            }
        }


        final SimpleFeatureType type = DataUtilities.createType("Location", "geometry:" + geometryType + "," + mergeField + ":" + mergeFieldType);

        List features = new ArrayList<>();
        SimpleFeatureCollection collection = new ListFeatureCollection(type, features);

        int id = 0;

        for (Map.Entry> entry : mergeMap.entrySet()) {

            Geometry geometry = GeometryUtil.union(entry.getValue());
            if (geometry != null) {
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
                featureBuilder.add(geometry);
                SimpleFeature feature = featureBuilder.buildFeature(String.valueOf(id));
                feature.setAttribute(mergeField, entry.getKey());
                features.add(feature);
                id++;
            }

        }


        return collection;
    }


    // 在百万级数据的时候性能极差,
    public static Geometries getGeometryType(FeatureCollection featureCollection) {

        try {
            if (featureCollection != null) {

                SimpleFeatureIterator iterator = (SimpleFeatureIterator) featureCollection.features();
                SimpleFeature feature = null;
                if (iterator.hasNext()) {
                    feature = iterator.next();

                }
                iterator.close();

                if (feature == null) {
                    return null;
                }

                return getGeometryType((Geometry) feature.getDefaultGeometry());
            }

            return null;

        } catch (Exception exp) {
            return null;
        }
    }


    // 在百万级数据的时候性能极差,
    public static Geometries getGeometryType(SimpleFeatureCollection featureCollection) {

        try {
            if (featureCollection != null) {

                SimpleFeatureIterator iterator = featureCollection.features();
                SimpleFeature feature = null;
                if (iterator.hasNext()) {
                    feature = iterator.next();

                }
                iterator.close();

                if (feature == null) {
                    return null;
                }

                return getGeometryType((Geometry) feature.getDefaultGeometry());
            }

            return null;

        } catch (Exception exp) {
            return null;
        }
    }


    public static Geometries getGeometryType(Geometry geometry) {

        Geometries geomType = Geometries.get(geometry);

        //如果是GEOMETRYCOLLECTION 需要单独判断
        if (Geometries.GEOMETRYCOLLECTION == geomType && geometry.getNumGeometries() > 0) {

            Geometries subGeometryType = Geometries.get(geometry.getGeometryN(0));
            if (subGeometryType == Geometries.POLYGON) {
                return Geometries.MULTIPOLYGON;
            } else if (subGeometryType == Geometries.POINT) {
                return Geometries.MULTIPOINT;
            } else if (subGeometryType == Geometries.LINESTRING) {
                return Geometries.MULTILINESTRING;
            }

            return Geometries.get(geometry.getGeometryN(0));

        }

        return geomType;
    }

    public static SimpleFeatureCollection getSimpleFeatureCollection(Geometry geometry) {
        List tmp = new ArrayList<>();
        tmp.add(geometry);
        return getSimpleFeatureCollection(tmp);

    }

    public static SimpleFeatureCollection getSimpleFeatureCollection(Geometry geometry, String geometryType) {
        List tmp = new ArrayList<>();
        if (geometry != null) {
            tmp.add(geometry);
        }

        return getSimpleFeatureCollection(tmp, geometryType);

    }

    public static SimpleFeatureCollection getSimpleFeatureCollection(List geometries) {
        return getSimpleFeatureCollection(geometries, null);
    }

    public static SimpleFeatureCollection getSimpleFeatureCollection(List geometries, String geometryType) {

        try {

            if (geometries == null || geometries.isEmpty()) {
                return null;
            }

            //如果geometryType为空就自己判断
            if (CharSequenceUtil.isEmpty(geometryType)) {
                geometryType = geometries.get(0).getGeometryType();


                //因为几何里面可能存在 单几何和多几何(Polygon,Multipolygon)情况,这里统一按照多几何的情况处理,因为如果按照单几何的情况处理,多几何就会出现错误
                if (CharSequenceUtil.equals(geometryType, "Polygon")) {
                    geometryType = "MultiPolygon";
                } else if (CharSequenceUtil.equals(geometryType, "LingString")) {
                    geometryType = "MultiLingString";
                } else if (CharSequenceUtil.equals(geometryType, "Point")) {
                    geometryType = "MultiPoint";
                }
            }


            final SimpleFeatureType featureType = DataUtilities.createType("Location", "geometry:" + geometryType);

            List features = new ArrayList<>();
            SimpleFeatureCollection collection = new ListFeatureCollection(featureType, features);

            int i = 0;

            for (Geometry geometry : geometries
            ) {
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
                featureBuilder.add(geometry);
                SimpleFeature feature = featureBuilder.buildFeature(String.valueOf(i));
                features.add(feature);
                i++;
            }

            return collection;
        } catch (Exception exp) {

            return null;
        }
    }


    public static List readGeometries(FeatureCollection featureCollection) {

        List geometryList = new ArrayList<>();

        if (featureCollection != null) {

            SimpleFeatureIterator iterator = (SimpleFeatureIterator) featureCollection.features();
            try {
                while (iterator.hasNext()) {
                    SimpleFeature feature = iterator.next();
                    geometryList.add((Geometry) feature.getDefaultGeometry());
                }
            } finally {
                iterator.close();
            }
        }

        return geometryList;
    }


    public static List readGeometries(SimpleFeatureCollection featureCollection) {

        List geometryList = new ArrayList<>();

        if (featureCollection != null) {

            SimpleFeatureIterator iterator = featureCollection.features();
            try {
                while (iterator.hasNext()) {
                    SimpleFeature feature = iterator.next();
                    geometryList.add((Geometry) feature.getDefaultGeometry());
                }
            } finally {
                iterator.close();
            }
        }

        return geometryList;
    }


    /**
     * 拷贝 SimpleFeatureCollection
     *
     * @param simpleFeatureCollection simpleFeatureCollection
     * @return simpleFeatureCollection
     * @author caihuimin
     */
    public static SimpleFeatureCollection copy(SimpleFeatureCollection simpleFeatureCollection) {


        List features = new ArrayList<>();

        SimpleFeatureIterator featureIterator = simpleFeatureCollection.features();

        while (featureIterator.hasNext()) {
            SimpleFeature feature = featureIterator.next();
            if (feature.getDefaultGeometryProperty() != null && feature.getDefaultGeometryProperty().getValue() != null) {
                Geometry geometry = (Geometry) feature.getDefaultGeometryProperty().getValue();
                feature.setAttribute(feature.getDefaultGeometryProperty().getName(), geometry.copy());
                features.add(feature);
            }

        }
        return new ListFeatureCollection(simpleFeatureCollection.getSchema(), features);
    }


    /**
     * 去除空值
     *
     * @param featureCollection featureCollection
     * @return simpleFeatureCollection
     * @author caihuimin
     */
    public static SimpleFeatureCollection removeNullGeometryItem(SimpleFeatureCollection featureCollection) {

        List features = new ArrayList<>();

        SimpleFeatureIterator featureIterator = featureCollection.features();

        while (featureIterator.hasNext()) {
            SimpleFeature feature = featureIterator.next();
            if (feature.getDefaultGeometryProperty() != null && feature.getDefaultGeometryProperty().getValue() != null) {
                Geometry geometry = (Geometry) feature.getDefaultGeometryProperty().getValue();
                if ((geometry.getCoordinate() != null && geometry.getCoordinates() != null)) {
                    features.add(feature);
                } else {
                    LOGGER.info("存在空geometry数据");
                }
            } else {
                LOGGER.info("存在空geometry数据");
            }

        }

        featureIterator.close();

        return new ListFeatureCollection(featureCollection.getSchema(), features);


    }


    /**
     * featureCollection
     *
     * @param featureCollection geojson的字符串
     * @return FeatureCollection
     * @throws GeoException GeoException
     * @author caihuimin
     */
    public static FeatureCollection validate(FeatureCollection featureCollection) throws GeoException {

        if (featureCollection == null || featureCollection.size() == 0) {
            return featureCollection;
        }

        if (featureCollection.getSchema() == null) {
            return featureCollection;
        }

        ListFeatureCollection validateFeatures = new ListFeatureCollection((SimpleFeatureType) featureCollection.getSchema());
        FeatureIterator features = featureCollection.features();
        while (features.hasNext()) {
            SimpleFeature feature = features.next();
            feature.setDefaultGeometry(GeometryUtil.validate((Geometry) feature.getDefaultGeometry()));
            validateFeatures.add(feature);

        }

        return validateFeatures;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy