From c95c4c1368b19963db477eaf5bed2a438c5c9ced Mon Sep 17 00:00:00 2001 From: langsmith Date: Thu, 18 Apr 2019 12:47:41 -0700 Subject: [PATCH] initial additions --- docs/turf-port.md | 2 +- .../java/com/mapbox/turf/TurfConversion.java | 92 +++++++++++++++++++ .../com/mapbox/turf/TurfConversionTest.java | 77 ++++++++++++++++ .../turf-explode/feature_collection.geojson | 72 +++++++++++++++ .../turf-explode/geometrycollection.geojson | 15 +++ .../resources/turf-explode/linestring.geojson | 21 +++++ .../turf-explode/multilinestring.geojson | 25 +++++ .../resources/turf-explode/multipoint.geojson | 21 +++++ .../turf-explode/multipolygon.geojson | 75 +++++++++++++++ .../test/resources/turf-explode/point.geojson | 11 +++ .../resources/turf-explode/polygon.geojson | 31 +++++++ 11 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 services-turf/src/test/resources/turf-explode/feature_collection.geojson create mode 100644 services-turf/src/test/resources/turf-explode/geometrycollection.geojson create mode 100644 services-turf/src/test/resources/turf-explode/linestring.geojson create mode 100644 services-turf/src/test/resources/turf-explode/multilinestring.geojson create mode 100644 services-turf/src/test/resources/turf-explode/multipoint.geojson create mode 100644 services-turf/src/test/resources/turf-explode/multipolygon.geojson create mode 100644 services-turf/src/test/resources/turf-explode/point.geojson create mode 100644 services-turf/src/test/resources/turf-explode/polygon.geojson diff --git a/docs/turf-port.md b/docs/turf-port.md index c0d5363b8..5d830d0d7 100644 --- a/docs/turf-port.md +++ b/docs/turf-port.md @@ -59,7 +59,7 @@ Below's an on going list of the Turf functions which currently exist inside the ## Feature Conversion - [ ] turf-combine -- [ ] turf-explode +- [x] turf-explode - [ ] turf-flatten - [ ] turf-line-to-polygon - [ ] turf-polygonize diff --git a/services-turf/src/main/java/com/mapbox/turf/TurfConversion.java b/services-turf/src/main/java/com/mapbox/turf/TurfConversion.java index 83653fe21..35200ec5e 100644 --- a/services-turf/src/main/java/com/mapbox/turf/TurfConversion.java +++ b/services-turf/src/main/java/com/mapbox/turf/TurfConversion.java @@ -3,9 +3,22 @@ import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; + +import com.mapbox.geojson.Feature; +import com.mapbox.geojson.FeatureCollection; +import com.mapbox.geojson.Geometry; +import com.mapbox.geojson.GeometryCollection; +import com.mapbox.geojson.LineString; +import com.mapbox.geojson.MultiLineString; +import com.mapbox.geojson.MultiPoint; +import com.mapbox.geojson.MultiPolygon; +import com.mapbox.geojson.Point; +import com.mapbox.geojson.Polygon; import com.mapbox.turf.TurfConstants.TurfUnitCriteria; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -163,4 +176,83 @@ public static double convertLength(@FloatRange(from = 0) double distance, } return radiansToLength(lengthToRadians(distance, originalUnit), finalUnit); } + + /** + * Takes a {@link FeatureCollection} and + * returns all positions as {@link Point} objects. + * + * @param featureCollection a {@link FeatureCollection} object + * @return a new {@link FeatureCollection} object with {@link Point} objects + * @since 4.7.0 + */ + public static FeatureCollection explode(@NonNull FeatureCollection featureCollection) { + List featuresForFinalFeatureCollection = new ArrayList<>(); + for (Feature singleFeature : featureCollection.features()) { + for (int i = 0; i < explode(singleFeature.geometry()).features().size(); i++) { + featuresForFinalFeatureCollection.add(explode(singleFeature.geometry()).features().get(i)); + } + } + return FeatureCollection.fromFeatures(featuresForFinalFeatureCollection); + } + + /** + * Takes a {@link Feature} and + * returns its position as a {@link Point} objects. + * + * @param feature a {@link Feature} object + * @return a new {@link FeatureCollection} object with {@link Point} objects + * @since 4.7.0 + */ + public static FeatureCollection explode(@NonNull Feature feature) { + return explode(feature.geometry()); + } + + /** + * Takes a {@link Geometry} object, checks what type of geometry it is, + * and then returns all positions as {@link Point} objects. + * + * @param geometry a {@link Geometry} object + * @return a new {@link FeatureCollection} object with {@link Point} objects + * @since 4.7.0 + */ + private static FeatureCollection explode(@NonNull Geometry geometry) { + List featuresForFinalFeatureCollection = new ArrayList<>(); + if (geometry instanceof Point) { + featuresForFinalFeatureCollection.add(Feature.fromGeometry(geometry)); + } else if (geometry instanceof MultiPoint) { + for (Point singlePoint : TurfMeta.coordAll((MultiPoint) geometry)) { + featuresForFinalFeatureCollection.add(Feature.fromGeometry(singlePoint)); + } + } else if (geometry instanceof LineString) { + for (Point singlePoint : TurfMeta.coordAll((LineString) geometry)) { + featuresForFinalFeatureCollection.add(Feature.fromGeometry(singlePoint)); + } + } else if (geometry instanceof MultiLineString) { + for (Point singlePoint : TurfMeta.coordAll((MultiLineString) geometry)) { + featuresForFinalFeatureCollection.add(Feature.fromGeometry(singlePoint)); + } + } else if (geometry instanceof Polygon) { + for (Point singlePoint : TurfMeta.coordAll((Polygon) geometry, true)) { + featuresForFinalFeatureCollection.add(Feature.fromGeometry(singlePoint)); + } + } else if (geometry instanceof MultiPolygon) { + List resultCoords = TurfMeta.coordAll((MultiPolygon) geometry, true); + for (Point singlePoint : resultCoords) { + featuresForFinalFeatureCollection.add(Feature.fromGeometry(singlePoint)); + } + } else if (geometry instanceof GeometryCollection) { + // recursive + for (Geometry singleGeometry : ((GeometryCollection) geometry).geometries()) { + if (explode(singleGeometry).features() != null + && explode(singleGeometry).features().size() > 0) { + for (Feature singleFeature : explode(singleGeometry).features()) { + featuresForFinalFeatureCollection.add(singleFeature); + } + } + } + } else { + throw new RuntimeException(("Unknown geometry class: " + geometry.getClass())); + } + return FeatureCollection.fromFeatures(featuresForFinalFeatureCollection); + } } diff --git a/services-turf/src/test/java/com/mapbox/turf/TurfConversionTest.java b/services-turf/src/test/java/com/mapbox/turf/TurfConversionTest.java index db1b4e7db..4e618e556 100644 --- a/services-turf/src/test/java/com/mapbox/turf/TurfConversionTest.java +++ b/services-turf/src/test/java/com/mapbox/turf/TurfConversionTest.java @@ -1,13 +1,34 @@ package com.mapbox.turf; +import com.mapbox.geojson.Feature; +import com.mapbox.geojson.FeatureCollection; +import com.mapbox.geojson.GeometryCollection; +import com.mapbox.geojson.LineString; +import com.mapbox.geojson.MultiLineString; +import com.mapbox.geojson.MultiPoint; +import com.mapbox.geojson.MultiPolygon; +import com.mapbox.geojson.Point; +import com.mapbox.geojson.Polygon; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import java.io.IOException; +import java.util.Arrays; + import static org.junit.Assert.assertEquals; public class TurfConversionTest extends TestUtils { + private static final String TURF_EXPLODE_POINT = "turf-explode/point.geojson"; + private static final String TURF_EXPLODE_MULTI_POINT = "turf-explode/multipoint.geojson"; + private static final String TURF_EXPLODE_LINESTRING = "turf-explode/linestring.geojson"; + private static final String TURF_EXPLODE_POLYGON = "turf-explode/polygon.geojson"; + private static final String TURF_EXPLODE_MULTILINESTRING = "turf-explode/multilinestring.geojson"; + private static final String TURF_EXPLODE_MULTIPOLYGON = "turf-explode/multipolygon.geojson"; + private static final String TURF_EXPLODE_GEOMETRY_COLLECTION = "turf-explode/geometrycollection.geojson"; + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -58,4 +79,60 @@ public void convertDistance() throws TurfException { TurfConversion.convertLength(1, TurfConstants.UNIT_METERS, TurfConstants.UNIT_CENTIMETERS), DELTA); } + + @Test + public void explodePointSingleFeature() throws IOException, NullPointerException { + Point point = Point.fromLngLat(102, 0.5); + assertEquals(1, TurfConversion.explode(Feature.fromGeometry(point)).features().size()); + } + + @Test + public void explodeMultiPointSingleFeature() throws IOException, NullPointerException { + MultiPoint multiPoint = MultiPoint.fromJson(loadJsonFixture(TURF_EXPLODE_MULTI_POINT)); + assertEquals(4, TurfConversion.explode(Feature.fromGeometry(multiPoint)).features().size()); + } + + @Test + public void explodeLineStringSingleFeature() throws IOException, NullPointerException { + LineString lineString = LineString.fromJson(loadJsonFixture(TURF_EXPLODE_LINESTRING)); + assertEquals(4, TurfConversion.explode(Feature.fromGeometry(lineString)).features().size()); + } + + @Test + public void explodePolygonSingleFeature() throws IOException, NullPointerException { + Polygon polygon = Polygon.fromLngLats(Arrays.asList( + Arrays.asList( + Point.fromLngLat(0, 101), + Point.fromLngLat(1, 101), + Point.fromLngLat(1, 100), + Point.fromLngLat(0, 100)))); + assertEquals(3, TurfConversion.explode(Feature.fromGeometry(polygon)).features().size()); + } + + @Test + public void explodeMultiLineStringSingleFeature() throws IOException, NullPointerException { + MultiLineString multiLineString = MultiLineString.fromJson(loadJsonFixture(TURF_EXPLODE_MULTILINESTRING)); + assertEquals(4, TurfConversion.explode(Feature.fromGeometry(multiLineString)).features().size()); + } + + @Test + public void explodeMultiPolygonSingleFeature() throws IOException, NullPointerException { + MultiPolygon multiPolygon = MultiPolygon.fromJson(loadJsonFixture(TURF_EXPLODE_MULTIPOLYGON)); + assertEquals(12, TurfConversion.explode(Feature.fromGeometry(multiPolygon)).features().size()); + } + + @Test + public void explodeGeometryCollectionSingleFeature() throws IOException, NullPointerException { + GeometryCollection geometryCollection = GeometryCollection.fromJson(loadJsonFixture(TURF_EXPLODE_GEOMETRY_COLLECTION)); + assertEquals(3, TurfConversion.explode(Feature.fromGeometry(geometryCollection)).features().size()); + } + + @Test + public void explodeFeatureCollection() throws IOException, NullPointerException { + FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] { + Feature.fromGeometry(MultiLineString.fromJson(loadJsonFixture(TURF_EXPLODE_MULTILINESTRING))), + Feature.fromGeometry(MultiPolygon.fromJson(loadJsonFixture(TURF_EXPLODE_MULTIPOLYGON))) + }); + assertEquals(16, TurfConversion.explode(featureCollection).features().size()); + } } diff --git a/services-turf/src/test/resources/turf-explode/feature_collection.geojson b/services-turf/src/test/resources/turf-explode/feature_collection.geojson new file mode 100644 index 000000000..61600aa8c --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/feature_collection.geojson @@ -0,0 +1,72 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 102, + 0.5 + ] + }, + "properties": {} + }, + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 102, + -10 + ], + [ + 103, + 1 + ], + [ + 104, + 0 + ], + [ + 130, + 4 + ] + ] + }, + "properties": {} + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 20, + 0 + ], + [ + 101, + 0 + ], + [ + 101, + 1 + ], + [ + 100, + 1 + ], + [ + 100, + 0 + ] + ] + ] + }, + "properties": {} + } + ] +} diff --git a/services-turf/src/test/resources/turf-explode/geometrycollection.geojson b/services-turf/src/test/resources/turf-explode/geometrycollection.geojson new file mode 100644 index 000000000..446384167 --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/geometrycollection.geojson @@ -0,0 +1,15 @@ +{ + "type": "GeometryCollection", + "geometries": [ + { + "type": "Point", + "coordinates": [100.0, 0.0] + }, + { + "type": "LineString", + "coordinates": [ + [101.0, 0.0], [102.0, 1.0] + ] + } + ] +} \ No newline at end of file diff --git a/services-turf/src/test/resources/turf-explode/linestring.geojson b/services-turf/src/test/resources/turf-explode/linestring.geojson new file mode 100644 index 000000000..93cbc3b88 --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/linestring.geojson @@ -0,0 +1,21 @@ +{ + "type": "LineString", + "coordinates": [ + [ + 102, + -10 + ], + [ + 103, + 1 + ], + [ + 104, + 0 + ], + [ + 130, + 4 + ] + ] +} diff --git a/services-turf/src/test/resources/turf-explode/multilinestring.geojson b/services-turf/src/test/resources/turf-explode/multilinestring.geojson new file mode 100644 index 000000000..b0df20393 --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/multilinestring.geojson @@ -0,0 +1,25 @@ +{ + "type": "MultiLineString", + "coordinates": [ + [ + [ + 100, + 0 + ], + [ + 101, + 1 + ] + ], + [ + [ + 102, + 2 + ], + [ + 103, + 3 + ] + ] + ] +} diff --git a/services-turf/src/test/resources/turf-explode/multipoint.geojson b/services-turf/src/test/resources/turf-explode/multipoint.geojson new file mode 100644 index 000000000..b8bf17715 --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/multipoint.geojson @@ -0,0 +1,21 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [ + 102, + -10 + ], + [ + 103, + 1 + ], + [ + 104, + 0 + ], + [ + 130, + 4 + ] + ] +} diff --git a/services-turf/src/test/resources/turf-explode/multipolygon.geojson b/services-turf/src/test/resources/turf-explode/multipolygon.geojson new file mode 100644 index 000000000..e9df991cf --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/multipolygon.geojson @@ -0,0 +1,75 @@ +{ + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + 102, + 2 + ], + [ + 103, + 2 + ], + [ + 103, + 3 + ], + [ + 102, + 3 + ], + [ + 102, + 2 + ] + ] + ], + [ + [ + [ + 100, + 0 + ], + [ + 101, + 0 + ], + [ + 101, + 1 + ], + [ + 100, + 1 + ], + [ + 100, + 0 + ] + ], + [ + [ + 100.2, + 0.2 + ], + [ + 100.8, + 0.2 + ], + [ + 100.8, + 0.8 + ], + [ + 100.2, + 0.8 + ], + [ + 100.2, + 0.2 + ] + ] + ] + ] +} diff --git a/services-turf/src/test/resources/turf-explode/point.geojson b/services-turf/src/test/resources/turf-explode/point.geojson new file mode 100644 index 000000000..129331f2a --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/point.geojson @@ -0,0 +1,11 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + 102, + 0.5 + ] + } +} \ No newline at end of file diff --git a/services-turf/src/test/resources/turf-explode/polygon.geojson b/services-turf/src/test/resources/turf-explode/polygon.geojson new file mode 100644 index 000000000..9b926efb8 --- /dev/null +++ b/services-turf/src/test/resources/turf-explode/polygon.geojson @@ -0,0 +1,31 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 101, + 0 + ], + [ + 101, + 1 + ], + [ + 100, + 1 + ], + [ + 100, + 0 + ], + [ + 101, + 0 + ] + ] + ] + } +}