diff --git a/services-turf/src/main/java/com/mapbox/turf/TurfMeasurement.java b/services-turf/src/main/java/com/mapbox/turf/TurfMeasurement.java index c264888f9..e5bc83838 100644 --- a/services-turf/src/main/java/com/mapbox/turf/TurfMeasurement.java +++ b/services-turf/src/main/java/com/mapbox/turf/TurfMeasurement.java @@ -3,6 +3,8 @@ import android.support.annotation.FloatRange; import android.support.annotation.NonNull; +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; @@ -10,6 +12,7 @@ import com.mapbox.geojson.Polygon; import com.mapbox.geojson.MultiPolygon; +import java.util.ArrayList; import java.util.List; /** @@ -333,6 +336,42 @@ public static double[] bbox(MultiPolygon multiPolygon) { return bboxCalculator(resultCoords); } + /** + * Takes an arbitrary {@link Geometry} and calculates a bounding box. + * + * @param geometry a {@link Geometry} object + * @return a double array defining the bounding box in this order {@code [minX, minY, maxX, maxY]} + * @since 2.0.0 + */ + public static double[] bbox(Geometry geometry) { + if (geometry instanceof Point) { + return bbox((Point) geometry); + } else if (geometry instanceof MultiPoint) { + return bbox((MultiPoint) geometry); + } else if (geometry instanceof LineString) { + return bbox((LineString) geometry); + } else if (geometry instanceof MultiLineString) { + return bbox((MultiLineString) geometry); + } else if (geometry instanceof Polygon) { + return bbox((Polygon) geometry); + } else if (geometry instanceof MultiPolygon) { + return bbox((MultiPolygon) geometry); + } else if (geometry instanceof GeometryCollection) { + List points = new ArrayList<>(); + for (Geometry geo : ((GeometryCollection) geometry).geometries()) { + // recursive + double[] bbox = bbox(geo); + points.add(Point.fromLngLat(bbox[0], bbox[1])); + points.add(Point.fromLngLat(bbox[2], bbox[1])); + points.add(Point.fromLngLat(bbox[2], bbox[3])); + points.add(Point.fromLngLat(bbox[0], bbox[3])); + } + return TurfMeasurement.bbox(MultiPoint.fromLngLats(points)); + } else { + throw new RuntimeException(("Unknown geometry class: " + geometry.getClass())); + } + } + private static double[] bboxCalculator(List resultCoords) { double[] bbox = new double[4]; diff --git a/services-turf/src/test/java/com/mapbox/turf/TurfMeasurementTest.java b/services-turf/src/test/java/com/mapbox/turf/TurfMeasurementTest.java index e170ee053..1ca83e2f3 100644 --- a/services-turf/src/test/java/com/mapbox/turf/TurfMeasurementTest.java +++ b/services-turf/src/test/java/com/mapbox/turf/TurfMeasurementTest.java @@ -1,18 +1,16 @@ package com.mapbox.turf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.mapbox.geojson.Feature; -import com.mapbox.geojson.MultiLineString; import com.mapbox.core.TestUtils; +import com.mapbox.geojson.Feature; import com.mapbox.geojson.FeatureCollection; -import com.mapbox.geojson.Polygon; +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 org.junit.Assert; import org.junit.Rule; @@ -23,6 +21,11 @@ import java.util.ArrayList; import java.util.List; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; + public class TurfMeasurementTest extends TestUtils { private static final String LINE_DISTANCE_ROUTE_ONE = "turf-line-distance/route1.geojson"; @@ -30,6 +33,7 @@ public class TurfMeasurementTest extends TestUtils { private static final String LINE_DISTANCE_POLYGON = "turf-line-distance/polygon.geojson"; private static final String TURF_ALONG_DC_LINE = "turf-along/dc-line.geojson"; private static final String TURF_BBOX_POINT = "turf-bbox/point.geojson"; + private static final String TURF_BBOX_MULTI_POINT = "turf-bbox/multipoint.geojson"; private static final String TURF_BBOX_LINESTRING = "turf-bbox/linestring.geojson"; private static final String TURF_BBOX_POLYGON = "turf-bbox/polygon.geojson"; private static final String TURF_BBOX_MULTILINESTRING = "turf-bbox/multilinestring.geojson"; @@ -301,4 +305,40 @@ public void bboxFromMultiPolygon() throws IOException, TurfException { assertEquals(103, bbox[2], DELTA); assertEquals(3, bbox[3], DELTA); } + + @Test + public void bboxFromGeometry() throws IOException, TurfException { + Geometry geometry = MultiPolygon.fromJson(loadJsonFixture(TURF_BBOX_MULTIPOLYGON)); + double[] bbox = TurfMeasurement.bbox(geometry); + + assertEquals(4, bbox.length); + assertEquals(100, bbox[0], DELTA); + assertEquals(0, bbox[1], DELTA); + assertEquals(103, bbox[2], DELTA); + assertEquals(3, bbox[3], DELTA); + } + + @Test + public void bboxFromGeometryCollection() throws IOException, TurfException { + // Check that geometry collection and direct bbox are equal + MultiPolygon multiPolygon = MultiPolygon.fromJson(loadJsonFixture(TURF_BBOX_MULTIPOLYGON)); + assertArrayEquals(TurfMeasurement.bbox(multiPolygon), TurfMeasurement.bbox(GeometryCollection.fromGeometry(multiPolygon)), DELTA); + + // Check all geometry types + List geometries = new ArrayList<>(); + geometries.add(Feature.fromJson(loadJsonFixture(TURF_BBOX_POINT)).geometry()); + geometries.add(MultiPoint.fromJson(loadJsonFixture(TURF_BBOX_MULTI_POINT))); + geometries.add(LineString.fromJson(loadJsonFixture(TURF_BBOX_LINESTRING))); + geometries.add(MultiLineString.fromJson(loadJsonFixture(TURF_BBOX_MULTILINESTRING))); + geometries.add(Feature.fromJson(loadJsonFixture(TURF_BBOX_POLYGON)).geometry()); + geometries.add(MultiPolygon.fromJson(loadJsonFixture(TURF_BBOX_MULTIPOLYGON))); + geometries.add(GeometryCollection.fromGeometry(Point.fromLngLat(-1., -1.))); + double[] bbox = TurfMeasurement.bbox(GeometryCollection.fromGeometries(geometries)); + + assertEquals(4, bbox.length); + assertEquals(-1, bbox[0], DELTA); + assertEquals(-10, bbox[1], DELTA); + assertEquals(130, bbox[2], DELTA); + assertEquals(4, bbox[3], DELTA); + } } diff --git a/services-turf/src/test/resources/turf-bbox/multipoint.geojson b/services-turf/src/test/resources/turf-bbox/multipoint.geojson new file mode 100644 index 000000000..b8bf17715 --- /dev/null +++ b/services-turf/src/test/resources/turf-bbox/multipoint.geojson @@ -0,0 +1,21 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [ + 102, + -10 + ], + [ + 103, + 1 + ], + [ + 104, + 0 + ], + [ + 130, + 4 + ] + ] +}