From d8c1991764ce2e4df6b418d803651ce500c27777 Mon Sep 17 00:00:00 2001 From: Guardiola31337 Date: Fri, 7 Apr 2017 19:33:44 +0200 Subject: [PATCH] add support for multiple holes --- .../annotations/BasePointCollection.java | 32 --------- .../mapbox/mapboxsdk/annotations/Hole.java | 53 +++++++++++++++ .../mapbox/mapboxsdk/annotations/Polygon.java | 37 ++++++++++- .../mapboxsdk/annotations/PolygonOptions.java | 66 ++++++++++++++++++- .../activity/annotation/PolygonActivity.java | 33 ++++++++-- .../src/main/res/menu/menu_polygon.xml | 4 ++ .../src/main/res/values/strings.xml | 1 + .../android/src/annotation/multi_point.hpp | 21 ++---- platform/android/src/annotation/polygon.cpp | 21 ++++-- platform/android/src/annotation/polygon.hpp | 2 +- platform/android/src/annotation/polyline.cpp | 11 +--- platform/android/src/annotation/polyline.hpp | 2 - 12 files changed, 206 insertions(+), 77 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Hole.java diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BasePointCollection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BasePointCollection.java index a0062f1503f..e57821b5411 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BasePointCollection.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BasePointCollection.java @@ -11,13 +11,11 @@ public abstract class BasePointCollection extends Annotation { private List points; - private List holePoints; private float alpha = 1.0f; protected BasePointCollection() { super(); points = new ArrayList<>(); - holePoints = new ArrayList<>(); } /** @@ -50,36 +48,6 @@ public void addPoint(LatLng point) { update(); } - /** - * Returns a copy of the hole points. - * - * @return A {@link List} of points. - */ - public List getHolePoints() { - return new ArrayList<>(holePoints); - } - - /** - * Sets the points of this polyline hole. This method will take a copy of the points, so further - * mutations to points will have no effect on this polyline hole. - * - * @param holePoints A {@link List} of {@link LatLng} points making up the polyline hole. - */ - public void setHolePoints(List holePoints) { - this.holePoints = new ArrayList<>(holePoints); - update(); - } - - /** - * Add a point to the polyline hole. - * - * @param holePoint A {@link LatLng} point to be added. - */ - public void addHolePoint(LatLng holePoint) { - holePoints.add(holePoint); - update(); - } - /** * Value between 0 and 1 defining the polyline alpha. * diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Hole.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Hole.java new file mode 100644 index 00000000000..cabe16cc5c2 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Hole.java @@ -0,0 +1,53 @@ +package com.mapbox.mapboxsdk.annotations; + + +import android.os.Parcel; +import android.os.Parcelable; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.ArrayList; +import java.util.List; + +/** + * Encapsulates a {@link List} of {@link LatLng} points defining a hole + */ +public class Hole extends ArrayList implements Parcelable { + + public Hole() { + super(); + } + + /** + * Creates a Hole. + * + * @param holePoints {@link List} list of {@link LatLng} points defining a hole + */ + public Hole(List holePoints) { + super(holePoints); + } + + protected Hole(Parcel in) { + in.readTypedList(this, LatLng.CREATOR); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeTypedList(this); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public Hole createFromParcel(Parcel in) { + return new Hole(in); + } + + public Hole[] newArray(int size) { + return new Hole[size]; + } + }; +} 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 4a72cb7d89c..9245d9cdc80 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 @@ -4,6 +4,9 @@ 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. */ @@ -11,9 +14,11 @@ public final class Polygon extends BasePointCollection { private int fillColor = Color.BLACK; // default fillColor is black private int strokeColor = Color.BLACK; // default strokeColor is black + private List holes; Polygon() { super(); + holes = new ArrayList<>(); } /** @@ -26,7 +31,7 @@ public int getFillColor() { } /** - * Get the color fo the stroke of the polygon. + * Get the color of the stroke of the polygon. * * @return The color of the stroke. */ @@ -34,6 +39,15 @@ public int getStrokeColor() { return strokeColor; } + /** + * Returns a copy of the holes. + * + * @return A {@link List} of holes. + */ + public List getHoles() { + return new ArrayList<>(holes); + } + /** * Sets the color of the fill region of the polygon. * @@ -54,6 +68,27 @@ public void setStrokeColor(int color) { update(); } + /** + * 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 holes A {@link List} of {@link Hole} points making up the holes. + */ + public void setHoles(List holes) { + this.holes = new ArrayList<>(holes); + update(); + } + + /** + * Add a hole to the polygon. + * + * @param hole A {@link Hole} hole to be added. + */ + void addHole(Hole hole) { + holes.add(hole); + update(); + } + @Override void update() { MapboxMap mapboxMap = getMapboxMap(); 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..7405ebfb4a1 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 @@ -30,6 +30,9 @@ private PolygonOptions(Parcel in) { ArrayList pointsList = new ArrayList<>(); in.readList(pointsList, LatLng.class.getClassLoader()); addAll(pointsList); + ArrayList holes = new ArrayList<>(); + in.readTypedList(holes, Hole.CREATOR); + addAllHoles(holes); alpha(in.readFloat()); fillColor(in.readInt()); strokeColor(in.readInt()); @@ -56,6 +59,7 @@ public int describeContents() { @Override public void writeToParcel(Parcel out, int flags) { out.writeList(getPoints()); + out.writeTypedList(getHoles()); out.writeFloat(getAlpha()); out.writeInt(getFillColor()); out.writeInt(getStrokeColor()); @@ -108,6 +112,43 @@ public PolygonOptions addAll(Iterable points) { return this; } + /** + * Adds a hole to the outline of the polygon being built. + * + * @param hole {@link Hole} 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(Hole hole) { + polygon.addHole(hole); + return this; + } + + /** + * Adds holes to the outline of the polygon being built. + * + * @param holes {@link Hole} holes to be added to polygon geometry. + * @return This {@link PolygonOptions} object with the given holes added to the outline. + */ + public PolygonOptions addHole(Hole... holes) { + for (Hole hole : holes) { + addHole(hole); + } + return this; + } + + /** + * Adds holes to the outline of the polygon being built. + * + * @param holes {@link Iterable} list made up of {@link Hole} holes defining the hole geometry + * @return This {@link PolygonOptions} object with the given holes added to the outline. + */ + public PolygonOptions addAllHoles(Iterable holes) { + for (Hole hole : holes) { + addHole(hole); + } + return this; + } + /** * Set the alpha value of the polyline. * @@ -177,18 +218,33 @@ public int getStrokeColor() { return polygon.getStrokeColor(); } + /** + * Gets the points set for this {@link PolygonOptions} object. + * + * @return The list made up of {@link LatLng} points defining the polygon. + */ public List getPoints() { // the getter gives us a copy, which is the safe thing to do... return polygon.getPoints(); } + /** + * Gets the holes set for this {@link PolygonOptions} object. + * + * @return The list made up of {@link List} of {@link LatLng} points defining the holes. + */ + 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. * * @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} + * {@link PolygonOptions} object. Else, false. */ @Override public boolean equals(Object o) { @@ -210,7 +266,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 +287,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 e12cbedaf72..429509e1d23 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 @@ -6,6 +6,7 @@ import android.view.Menu; import android.view.MenuItem; +import com.mapbox.mapboxsdk.annotations.Hole; import com.mapbox.mapboxsdk.annotations.Polygon; import com.mapbox.mapboxsdk.annotations.PolygonOptions; import com.mapbox.mapboxsdk.camera.CameraPosition; @@ -18,6 +19,7 @@ import com.mapbox.mapboxsdk.testapp.R; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.BLUE_COLOR; @@ -26,8 +28,8 @@ import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.NO_ALPHA; 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_HOLES; import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.STAR_SHAPE_POINTS; -import static com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity.Config.TRIANGLE_HOLE_SHAPE_POINTS; /** * Test activity to showcase the Polygon annotation API & programmatically creating a MapView. @@ -45,6 +47,7 @@ public class PolygonActivity extends AppCompatActivity implements OnMapReadyCall private boolean visible = true; private boolean color = true; private boolean allPoints; + private boolean holes; @Override protected void onCreate(Bundle savedInstanceState) { @@ -136,12 +139,15 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.action_id_points: allPoints = !allPoints; polygon.setPoints(allPoints ? STAR_SHAPE_POINTS : BROKEN_SHAPE_POINTS); - polygon.setHolePoints(TRIANGLE_HOLE_SHAPE_POINTS); return true; case R.id.action_id_color: color = !color; polygon.setFillColor(color ? BLUE_COLOR : RED_COLOR); return true; + case R.id.action_id_holes: + holes = !holes; + polygon.setHoles(holes ? STAR_SHAPE_HOLES : Collections.emptyList()); + return true; default: return super.onOptionsItemSelected(item); } @@ -182,12 +188,25 @@ static final class Config { static final List BROKEN_SHAPE_POINTS = STAR_SHAPE_POINTS.subList(0, STAR_SHAPE_POINTS.size() - 3); - static final List TRIANGLE_HOLE_SHAPE_POINTS = new ArrayList() { + static final List STAR_SHAPE_HOLES = new ArrayList() { { - add(new LatLng(45.521743, -122.669091)); - add(new LatLng(45.530483, -122.676833)); - add(new LatLng(45.520483, -122.676833)); - add(new LatLng(45.521743, -122.669091)); + add(new Hole(new ArrayList() { + { + add(new LatLng(45.521743, -122.669091)); + add(new LatLng(45.530483, -122.676833)); + add(new LatLng(45.520483, -122.676833)); + add(new LatLng(45.521743, -122.669091)); + } + })); + add(new Hole(new ArrayList() { + { + add(new LatLng(45.529743, -122.662791)); + add(new LatLng(45.525543, -122.662791)); + add(new LatLng(45.525543, -122.660)); + add(new LatLng(45.527743, -122.660)); + add(new LatLng(45.529743, -122.662791)); + } + })); } }; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_polygon.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_polygon.xml index a7fdf56be51..f2cd9aedbcb 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_polygon.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_polygon.xml @@ -17,4 +17,8 @@ android:id="@+id/action_id_color" android:title="@string/action_color_polygon" mapbox:showAsAction="never" /> + diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml index ac5c528c389..d2442fb161b 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml @@ -132,6 +132,7 @@ Change alpha Change points Change color + Change holes Change width diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp index 1c4a58df802..e1152dfd60c 100644 --- a/platform/android/src/annotation/multi_point.hpp +++ b/platform/android/src/annotation/multi_point.hpp @@ -14,19 +14,17 @@ class MultiPoint : protected mbgl::util::noncopyable { protected: template - static Geometry toGeometry(JNIEnv& env, jni::Object pointsList, jni::Object holePointsList) { + static Geometry toGeometry(JNIEnv& env, jni::Object pointsList) { NullCheck(env, &pointsList); auto jarray = java::util::List::toArray(env, pointsList); NullCheck(env, &jarray); - std::size_t jsize = jarray.Length(env); - auto karray = java::util::List::toArray(env, holePointsList); - std::size_t ksize = karray.Length(env); + std::size_t size = jarray.Length(env); Geometry geometry; - geometry.reserve(jsize + ksize); + geometry.reserve(size); - for (std::size_t i = 0; i < jsize; i++) { + for (std::size_t i = 0; i < size; i++) { auto latLng = jarray.Get(env, i); NullCheck(env, &latLng); @@ -36,17 +34,6 @@ class MultiPoint : protected mbgl::util::noncopyable { } jni::DeleteLocalRef(env, jarray); - - for (std::size_t i = 0; i < ksize; i++) { - auto latLng = karray.Get(env, i); - NullCheck(env, &latLng); - - geometry.push_back(LatLng::getGeometry(env, latLng)); - - jni::DeleteLocalRef(env, latLng); - } - - jni::DeleteLocalRef(env, karray); return geometry; } }; diff --git a/platform/android/src/annotation/polygon.cpp b/platform/android/src/annotation/polygon.cpp index ea0f5225937..fbd849432a6 100644 --- a/platform/android/src/annotation/polygon.cpp +++ b/platform/android/src/annotation/polygon.cpp @@ -9,15 +9,26 @@ jni::Class Polygon::javaClass; mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object polygon) { auto points = Polygon::getPoints(env, polygon); - auto holePoints = Polygon::getHolePoints(env, polygon); + auto holes = Polygon::getHoles(env, polygon); - mbgl::FillAnnotation annotation { mbgl::Polygon { MultiPoint::toGeometry>(env, points, holePoints) } }; + mbgl::Polygon geometry { MultiPoint::toGeometry>(env, points) }; + + auto jHoleListsArray = java::util::List::toArray(env, holes); + std::size_t jHoleListsSize = jHoleListsArray.Length(env); + for (std::size_t i = 0; i < jHoleListsSize; i++) { + auto jHoleList = jHoleListsArray.Get(env, i); + geometry.push_back(MultiPoint::toGeometry>(env, jHoleList)); + jni::DeleteLocalRef(env, jHoleList); + } + jni::DeleteLocalRef(env, jHoleListsArray); + + mbgl::FillAnnotation annotation { geometry }; annotation.opacity = { Polygon::getOpacity(env, polygon) }; annotation.color = { Polygon::getFillColor(env, polygon) }; annotation.outlineColor = { Polygon::getOutlineColor(env, polygon) }; jni::DeleteLocalRef(env, points); - jni::DeleteLocalRef(env, holePoints); + jni::DeleteLocalRef(env, holes); return annotation; } @@ -27,8 +38,8 @@ jni::Object Polygon::getPoints(jni::JNIEnv& env, jni::Object

Polygon::getHolePoints(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField>(env, "holePoints"); +jni::Object Polygon::getHoles(jni::JNIEnv& env, jni::Object polygon) { + static auto field = Polygon::javaClass.GetField>(env, "holes"); return polygon.Get(env, field); } diff --git a/platform/android/src/annotation/polygon.hpp b/platform/android/src/annotation/polygon.hpp index 40fa287a901..a98b2822cf2 100644 --- a/platform/android/src/annotation/polygon.hpp +++ b/platform/android/src/annotation/polygon.hpp @@ -28,7 +28,7 @@ class Polygon : private MultiPoint { static jni::Object getPoints(jni::JNIEnv&, jni::Object); - static jni::Object getHolePoints(jni::JNIEnv&, jni::Object); + static jni::Object getHoles(jni::JNIEnv&, jni::Object); static float getOpacity(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index b3dafa40ebe..3723dc1871d 100644 --- a/platform/android/src/annotation/polyline.cpp +++ b/platform/android/src/annotation/polyline.cpp @@ -9,15 +9,13 @@ jni::Class Polyline::javaClass; mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object polyline) { auto points = Polyline::getPoints(env, polyline); - auto holePoints = Polyline::getHolePoints(env, polyline); - mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, points, - holePoints) }; + + mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, points) }; annotation.opacity = { Polyline::getOpacity(env, polyline) }; annotation.color = { Polyline::getColor(env, polyline) }; annotation.width = { Polyline::getWidth(env, polyline) }; jni::DeleteLocalRef(env, points); - jni::DeleteLocalRef(env, holePoints); return annotation; } @@ -27,11 +25,6 @@ jni::Object Polyline::getPoints(jni::JNIEnv& env, jni::Object< return polyline.Get(env, field); } -jni::Object Polyline::getHolePoints(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField>(env, "holePoints"); - return polyline.Get(env, field); -} - float Polyline::getOpacity(jni::JNIEnv& env, jni::Object polyline) { static auto field = Polyline::javaClass.GetField(env, "alpha"); return polyline.Get(env, field); diff --git a/platform/android/src/annotation/polyline.hpp b/platform/android/src/annotation/polyline.hpp index df377853a69..bcc616a5f74 100644 --- a/platform/android/src/annotation/polyline.hpp +++ b/platform/android/src/annotation/polyline.hpp @@ -28,8 +28,6 @@ class Polyline : private MultiPoint { static jni::Object getPoints(jni::JNIEnv&, jni::Object); - static jni::Object getHolePoints(jni::JNIEnv&, jni::Object); - static float getOpacity(jni::JNIEnv&, jni::Object); static mbgl::Color getColor(jni::JNIEnv&, jni::Object);