diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java index d2aaea1d178..dc4f73cc7b1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java @@ -11,11 +11,13 @@ public abstract class MultiPoint extends Annotation { private List points; + private List> holes; private float alpha = 1.0f; protected MultiPoint() { super(); points = new ArrayList<>(); + holes = new ArrayList<>(); } /** @@ -27,6 +29,14 @@ public List getPoints() { return new ArrayList<>(points); } + /* + * Returns a copy of the holes. + * @return holes - as a copy + */ + public List> getHoles() { + return new ArrayList<>(holes); + } + /** * Sets the points of this polyline. This method will take a copy * of the points, so further mutations to points will have no effect @@ -42,6 +52,10 @@ void addPoint(LatLng point) { points.add(point); } + void addHole(List hole) { + holes.add(hole); + } + public float getAlpha() { return alpha; } 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 30847807b99..81a4d6721df 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 @@ -73,6 +73,17 @@ public PolygonOptions addAll(Iterable points) { return this; } + public PolygonOptions addHole(Iterable points) { + List hole = new ArrayList(); + for (LatLng point : points) { + hole.add(point); + } + + polygon.addHole(hole); + + return this; + } + public PolygonOptions alpha(float alpha) { polygon.setAlpha(alpha); return this; @@ -126,6 +137,10 @@ public List getPoints() { return polygon.getPoints(); } + public List> getHoles() { + return polygon.getHoles(); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -136,6 +151,7 @@ public boolean equals(Object o) { if (Float.compare(polygon.getAlpha(), getAlpha()) != 0) return false; if (getFillColor() != polygon.getFillColor()) return false; if (getStrokeColor() != polygon.getStrokeColor()) return false; + if (getHoles() != null ? !getHoles().equals(polygon.getHoles()) : polygon.getHoles() != null) return false; return !(getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null); } @@ -146,6 +162,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 f08d65163bf..6c8be09a8d0 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 @@ -71,8 +71,52 @@ public void onMapReady(MapboxMap mapboxMap) { polygon.add(new LatLng(45.515369, -122.678489)); polygon.add(new LatLng(45.506346, -122.702007)); polygon.add(new LatLng(45.522585, -122.685699)); + + double lat = 0; + double lon = 0; + int points = 0; + for (LatLng latLng : polygon) { + points++; + lat += latLng.getLatitude(); + lon += latLng.getLongitude(); + } + + lat = lat / points; + lon = lon / points; + + List hole1 = new ArrayList<>(); + hole1.add(new LatLng(lat, lon)); + hole1.add(new LatLng(lat + 0.01, lon)); + hole1.add(new LatLng(lat + 0.01, lon + 0.01)); + hole1.add(new LatLng(lat, lon + 0.01)); + hole1.add(new LatLng(lat, lon)); + + lat = lat - 0.001; + lon = lon - 0.001; + + List hole2 = new ArrayList<>(); + hole2.add(new LatLng(lat, lon)); + hole2.add(new LatLng(lat - 0.005, lon)); + hole2.add(new LatLng(lat - 0.005, lon - 0.005)); + hole2.add(new LatLng(lat, lon - 0.005)); + hole2.add(new LatLng(lat, lon)); + + lat = lat + 0.008; + lon = lon - 0.01; + + List hole3 = new ArrayList<>(); + hole3.add(new LatLng(lat, lon)); + hole3.add(new LatLng(lat - 0.005, lon)); + hole3.add(new LatLng(lat - 0.005, lon - 0.005)); + hole3.add(new LatLng(lat, lon - 0.005)); + hole3.add(new LatLng(lat, lon)); + mapboxMap.addPolygon(new PolygonOptions() .addAll(polygon) + .addHole(hole1) + .addHole(hole2) + .addHole(hole3) + .alpha(0.5f) .fillColor(Color.parseColor("#3bb2d0"))); } }); diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index d87eb434b19..472c47e5ea3 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -74,6 +74,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; @@ -248,6 +249,52 @@ jni::jarray* std_vector_uint_to_jobject(JNIEnv *env, std::vector* jarray = + reinterpret_cast*>(jni::CallMethod(*env, jlist, *listToArrayId)); + + NullCheck(*env, jarray); + std::size_t len = jni::GetArrayLength(*env, *jarray); + + for (std::size_t i = 0; i < len; i++) { + mbgl::AnnotationSegment segment; + + jni::jobject* latLngList = reinterpret_cast(jni::GetObjectArrayElement(*env, *jarray, i)); + NullCheck(*env, latLngList); + + jni::jarray* holePoints = + reinterpret_cast*>(jni::CallMethod(*env, latLngList, *listToArrayId)); + NullCheck(*env, holePoints); + + std::size_t holePointsLen = jni::GetArrayLength(*env, *holePoints); + + for (std::size_t j = 0; j < holePointsLen; j++) { + jni::jobject* latLng = reinterpret_cast(jni::GetObjectArrayElement(*env, *holePoints, j)); + NullCheck(*env, latLng); + + jdouble latitude = jni::GetField(*env, latLng, *latLngLatitudeId); + jdouble longitude = jni::GetField(*env, latLng, *latLngLongitudeId); + + segment.push_back(mbgl::LatLng(latitude, longitude)); + jni::DeleteLocalRef(*env, latLng); + } + + jni::DeleteLocalRef(*env, holePoints); + + segments.push_back(segment); + } + + jni::DeleteLocalRef(*env, jarray); + jarray = nullptr; + + return segments; +} + mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jni::jobject* jlist) { mbgl::AnnotationSegment segment; @@ -277,7 +324,7 @@ mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jni::j return segment; } -std::pair annotation_std_pair_from_polygon_jobject(JNIEnv *env, jni::jobject* polygon) { +std::pair annotation_std_pair_from_polygon_jobject(JNIEnv *env, jni::jobject* polygon) { jfloat alpha = jni::GetField(*env, polygon, *polygonAlphaId); jint fillColor = jni::GetField(*env, polygon, *polygonFillColorId); jint strokeColor = jni::GetField(*env, polygon, *polygonStrokeColorId); @@ -303,7 +350,14 @@ std::pair annotation mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points); jni::DeleteLocalRef(*env, points); - return std::make_pair(segment, shapeProperties); + jni::jobject* holes = jni::GetField(*env, polygon, *polygonHolesId); + mbgl::AnnotationSegments segments = annotation_segments_from_jlist_of_latlng_jlist(env, holes); + jni::DeleteLocalRef(*env, holes); + + // Insert the shell segment at the beginning of the list + segments.insert(segments.begin(), segment); + + return std::make_pair(segments, shapeProperties); } static std::vector metadata_from_java(JNIEnv* env, jni::jarray& j) { @@ -892,11 +946,12 @@ jlong nativeAddPolygon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, j NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); std::vector shapes; - std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); + std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); - shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second); + shapes.emplace_back(segment.first, segment.second); std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes); + uint32_t id = shapeAnnotationIDs.at(0); return id; } @@ -918,8 +973,8 @@ jni::jarray* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nati for (std::size_t i = 0; i < len; i++) { jni::jobject* polygon = jni::GetObjectArrayElement(*env, *jarray, i); - std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); - shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second); + std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon); + shapes.emplace_back(segment.first, segment.second); jni::DeleteLocalRef(*env, polygon); } @@ -1755,6 +1810,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { 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;");