diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java index 7b9de86bc4c..94dbb55bb4c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java @@ -2,18 +2,48 @@ import android.graphics.Color; +import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapboxMap; +import java.util.ArrayList; +import java.util.List; + /** * Polygon is a geometry annotation that's a closed loop of coordinates. */ public final class Polygon extends MultiPoint { + private List> holes; private int fillColor = Color.BLACK; // default fillColor is black private int strokeColor = Color.BLACK; // default strokeColor is black Polygon() { super(); + holes = new ArrayList<>(); + } + + /** + * Returns a copy of the holes. + * + * @return A {@link List} of holes. + */ + public List> getHoles() { + return new ArrayList<>(holes); + } + + /** + * Sets the holes of this polygon. This method will take a copy of the holes, so further + * mutations to holes will have no effect on this polygon. + * + * @param points A {@link List} {@link List}s of {@link LatLng} points making up the holes. + */ + public void setHoles(List> holes) { + this.holes = new ArrayList<>(holes); + update(); + } + + void addHole(List hole) { + holes.add(hole); } /** @@ -26,7 +56,7 @@ public int getFillColor() { } /** - * Get the color fo the stroke of the polygon. + * Get the color for the stroke of the polygon. * * @return The color of the stroke. */ diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java index 22f1258fc71..6ed95990ebc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java @@ -108,6 +108,23 @@ public PolygonOptions addAll(Iterable points) { return this; } + /** + * Adds a hole to the outline of the polygon being built. + * + * @param points {@link Iterable} list made up of {@link LatLng} points defining the hole + * @return This {@link PolygonOptions} object with the given hole added to the outline. + */ + public PolygonOptions addHole(Iterable points) { + List hole = new ArrayList(); + for (LatLng point : points) { + hole.add(point); + } + + polygon.addHole(hole); + + return this; + } + /** * Set the alpha value of the polyline. * @@ -182,13 +199,20 @@ public List getPoints() { return polygon.getPoints(); } + /** + * Gets the holes set for this {@link PolygonOptions} object. + */ + public List> getHoles() { + return polygon.getHoles(); + } + /** * Compares this {@link PolygonOptions} object with another {@link PolygonOptions} and - * determines if their color, alpha, stroke color, and vertices match. + * determines if their color, alpha, stroke color, vertices, and holes match. * * @param o Another {@link PolygonOptions} to compare with this object. - * @return True if color, alpha, stroke color, and vertices match this {@link PolygonOptions} - * object. Else, false. + * @return True if color, alpha, stroke color, vertices, and holes match this + * {@link PolygonOptions} object. Else, false. */ @Override public boolean equals(Object o) { @@ -210,7 +234,10 @@ public boolean equals(Object o) { if (getStrokeColor() != polygon.getStrokeColor()) { return false; } - return !(getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null); + if (getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null) { + return false; + } + return !(getHoles() != null ? !getHoles().equals(polygon.getHoles()) : polygon.getHoles() != null); } /** @@ -228,6 +255,7 @@ public int hashCode() { result = 31 * result + getFillColor(); result = 31 * result + getStrokeColor(); result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0); + result = 31 * result + (getHoles() != null ? getHoles().hashCode() : 0); return result; } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java index c37d9bb92e0..451152a38c2 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java @@ -27,6 +27,7 @@ import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.PARTIAL_ALPHA; import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.RED_COLOR; import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.STAR_SHAPE_POINTS; +import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.STAR_SHAPE_HOLES; /** * Activity to test the Polygon annotation API & programmatically creating a MapView. @@ -135,6 +136,7 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.action_id_points: allPoints = !allPoints; polygon.setPoints(allPoints ? STAR_SHAPE_POINTS : BROKEN_SHAPE_POINTS); + polygon.setHoles(STAR_SHAPE_HOLES); return true; case R.id.action_id_color: color = !color; @@ -177,6 +179,38 @@ static final class Config { } }; + static final List> STAR_SHAPE_HOLES = new ArrayList>() { + { + add(new ArrayList() { + { + add(new LatLng(45.522584, -122.672653)); + add(new LatLng(45.532584, -122.672653)); + add(new LatLng(45.532584, -122.682653)); + add(new LatLng(45.522584, -122.682653)); + add(new LatLng(45.522584, -122.672653)); + } + }); + add(new ArrayList() { + { + add(new LatLng(45.521584, -122.671653)); + add(new LatLng(45.516584, -122.671653)); + add(new LatLng(45.516584, -122.676653)); + add(new LatLng(45.521584, -122.676653)); + add(new LatLng(45.521584, -122.671653)); + } + }); + add(new ArrayList() { + { + add(new LatLng(45.529584, -122.661653)); + add(new LatLng(45.524584, -122.661653)); + add(new LatLng(45.524584, -122.656653)); + add(new LatLng(45.529584, -122.656653)); + add(new LatLng(45.529584, -122.661653)); + } + }); + } + }; + static final List BROKEN_SHAPE_POINTS = STAR_SHAPE_POINTS.subList(0, STAR_SHAPE_POINTS.size() - 3); } diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index f273210c778..bdfd85a0b56 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -89,6 +89,7 @@ jni::jfieldID* polygonAlphaId = nullptr; jni::jfieldID* polygonFillColorId = nullptr; jni::jfieldID* polygonStrokeColorId = nullptr; jni::jfieldID* polygonPointsId = nullptr; +jni::jfieldID* polygonHolesId = nullptr; jni::jmethodID* listToArrayId = nullptr; @@ -759,7 +760,26 @@ jni::jarray* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nati jni::jobject* polygon = jni::GetObjectArrayElement(*env, *jarray, i); jni::jobject* points = jni::GetField(*env, polygon, *polygonPointsId); - mbgl::FillAnnotation annotation { mbgl::Polygon { toGeometry>(env, points) } }; + mbgl::Polygon geometry { toGeometry>(env, points) }; + + jni::jobject* holes = jni::GetField(*env, polygon, *polygonHolesId); + NullCheck(*env, holes); + jni::jarray* jarrayHoles = + reinterpret_cast*>(jni::CallMethod(*env, holes, *listToArrayId)); + NullCheck(*env, jarrayHoles); + + std::size_t size = jni::GetArrayLength(*env, *jarrayHoles); + for (std::size_t j = 0; j < size; j++) { + jni::jobject* hole = jni::GetObjectArrayElement(*env, *jarrayHoles, j); + NullCheck(*env, hole); + geometry.push_back(toGeometry>(env, hole)); + jni::DeleteLocalRef(*env, hole); + } + + jni::DeleteLocalRef(*env, jarrayHoles); + jni::DeleteLocalRef(*env, holes); + + mbgl::FillAnnotation annotation { geometry }; annotation.opacity = { jni::GetField(*env, polygon, *polygonAlphaId) }; annotation.outlineColor = { toColor(jni::GetField(*env, polygon, *polygonStrokeColorId)) }; annotation.color = { toColor(jni::GetField(*env, polygon, *polygonFillColorId)) }; @@ -1811,6 +1831,7 @@ void registerNatives(JavaVM *vm) { polygonFillColorId = &jni::GetFieldID(env, *polygonClass, "fillColor", "I"); polygonStrokeColorId = &jni::GetFieldID(env, *polygonClass, "strokeColor", "I"); polygonPointsId = &jni::GetFieldID(env, *polygonClass, "points", "Ljava/util/List;"); + polygonHolesId = &jni::GetFieldID(env, *polygonClass, "holes", "Ljava/util.List;"); jni::jclass* listClass = &jni::FindClass(env, "java/util/List"); listToArrayId = &jni::GetMethodID(env, *listClass, "toArray", "()[Ljava/lang/Object;");