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

io.github.sebasbaumh.mapbox.vectortile.util.JtsGeomStats Maven / Gradle / Ivy

package io.github.sebasbaumh.mapbox.vectortile.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.annotation.DefaultLocation;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateSequence;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;

import io.github.sebasbaumh.mapbox.vectortile.VectorTile;
import io.github.sebasbaumh.mapbox.vectortile.adapt.jts.JtsAdapter;

@NonNullByDefault({DefaultLocation.PARAMETER,DefaultLocation.RETURN_TYPE})
public final class JtsGeomStats {

    public static final class FeatureStats {
        public int totalPts;
        public int repeatedPts;

        @Override
        public String toString() {
            return "FeatureStats{" +
                    "totalPts=" + totalPts +
                    ", repeatedPts=" + repeatedPts +
                    '}';
        }
    }

    public Map featureCounts;
    public List featureStats;

    private JtsGeomStats() {
        final VectorTile.Tile.GeomType[] geomTypes = VectorTile.Tile.GeomType.values();
        featureCounts = new HashMap<>(geomTypes.length);

        for(VectorTile.Tile.GeomType nextGeomType : geomTypes) {
            featureCounts.put(nextGeomType, 0);
        }

        this.featureStats = new ArrayList<>();
    }

    @Override
    public String toString() {
        return "JtsGeomStats{" +
                "featureCounts=" + featureCounts +
                ", featureStats=" + featureStats +
                '}';
    }

    /**
     * Get feature counts and feature statistics (points and repeated points).
     *
     * @param flatGeomList geometry under analysis
     * @return the resulting statistics
     */
    public static JtsGeomStats getStats(List flatGeomList) {
        final JtsGeomStats stats = new JtsGeomStats();

        for(Geometry nextGeom : flatGeomList) {
            final VectorTile.Tile.GeomType geomType = JtsAdapter.toGeomType(nextGeom);

            // Count features by type
            Integer value = stats.featureCounts.get(geomType);
            value = value == null ? 1 : value + 1;
            stats.featureCounts.put(geomType, value);

            // Get stats per feature
            stats.featureStats.add(getStats(nextGeom, geomType));
        }

        return stats;
    }

    private static FeatureStats getStats(Geometry geom, VectorTile.Tile.GeomType type) {
        FeatureStats featureStats;

        switch (type) {
            case POINT:
                featureStats = pointStats(geom);
                break;
            case LINESTRING:
                featureStats = lineStats(geom);
                break;
            case POLYGON:
                featureStats = polyStats(geom);
                break;
            default:
                featureStats = new FeatureStats();
        }

        return featureStats;
    }

    private static FeatureStats pointStats(Geometry geom) {
        final FeatureStats featureStats = new FeatureStats();

        final HashSet pointSet = new HashSet<>(geom.getNumPoints());
        featureStats.totalPts = geom.getNumPoints();

        for(int i = 0; i < geom.getNumGeometries(); ++i) {
            final Point p = (Point) geom.getGeometryN(i);
            featureStats.repeatedPts += pointSet.add(p) ? 0 : 1;
        }

        return featureStats;
    }

    private static FeatureStats lineStats(Geometry geom) {
        final FeatureStats featureStats = new FeatureStats();

        for(int i = 0; i < geom.getNumGeometries(); ++i) {
            final LineString lineString = (LineString) geom.getGeometryN(i);
            featureStats.totalPts += lineString.getNumPoints();
            featureStats.repeatedPts += checkRepeatedPoints2d(lineString);
        }

        return featureStats;
    }

    private static FeatureStats polyStats(Geometry geom) {
        final FeatureStats featureStats = new FeatureStats();

        for(int i = 0; i < geom.getNumGeometries(); ++i) {
            final Polygon nextPoly = (Polygon) geom.getGeometryN(i);

            // Stats: exterior ring
            final LineString exteriorRing = nextPoly.getExteriorRing();
            featureStats.totalPts += exteriorRing.getNumPoints();
            featureStats.repeatedPts += checkRepeatedPoints2d(exteriorRing);

            // Stats: interior rings
            for(int ringIndex = 0; ringIndex < nextPoly.getNumInteriorRing(); ++ringIndex) {

                final LineString nextInteriorRing = nextPoly.getInteriorRingN(ringIndex);
                featureStats.totalPts += nextInteriorRing.getNumPoints();
                featureStats.repeatedPts += checkRepeatedPoints2d(nextInteriorRing);
            }
        }

        return featureStats;
    }

    private static int checkRepeatedPoints2d(LineString lineString) {
        int repeatedPoints = 0;

        final CoordinateSequence coordSeq = lineString.getCoordinateSequence();
        Coordinate nextCoord = null, prevCoord;
        for(int i = 0; i < coordSeq.size(); ++i) {
            prevCoord = nextCoord;
            nextCoord = coordSeq.getCoordinate(i);
            if(nextCoord.equals(prevCoord)) {
                ++repeatedPoints;
            }
        }

        return repeatedPoints;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy