Merge branch 'android-annotations' of git://github.com/hallahan/mapbox-gl-native into hallahan-android-annotations

This commit is contained in:
Brad Leege
2015-07-22 10:15:34 -05:00
22 changed files with 1584 additions and 6 deletions

View File

@@ -16,6 +16,8 @@
#include <mbgl/android/jni.hpp>
#include <mbgl/android/native_map_view.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/annotation/point_annotation.hpp>
#include <mbgl/annotation/shape_annotation.hpp>
#include <mbgl/platform/event.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/storage/network_status.hpp>
@@ -39,6 +41,30 @@ jmethodID latLngConstructorId = nullptr;
jfieldID latLngLatitudeId = nullptr;
jfieldID latLngLongitudeId = nullptr;
jclass markerClass = nullptr;
jmethodID markerConstructorId = nullptr;
jfieldID markerPositionId = nullptr;
jfieldID markerSpriteId = nullptr;
jclass polylineClass = nullptr;
jmethodID polylineConstructorId = nullptr;
jfieldID polylineAlphaId = nullptr;
jfieldID polylineVisibleId = nullptr;
jfieldID polylineColorId = nullptr;
jfieldID polylineWidthId = nullptr;
jfieldID polylinePointsId = nullptr;
jclass polygonClass = nullptr;
jmethodID polygonConstructorId = nullptr;
jfieldID polygonAlphaId = nullptr;
jfieldID polygonVisibleId = nullptr;
jfieldID polygonFillColorId = nullptr;
jfieldID polygonStrokeColorId = nullptr;
jfieldID polygonStrokeWidthId = nullptr;
jfieldID polygonPointsId = nullptr;
jfieldID polygonHolesId = nullptr;
jclass latLngZoomClass = nullptr;
jmethodID latLngZoomConstructorId = nullptr;
jfieldID latLngZoomLatitudeId = nullptr;
@@ -155,6 +181,56 @@ std::vector<std::string> std_vector_string_from_jobject(JNIEnv *env, jobject jli
return vector;
}
mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobject jlist) {
mbgl::AnnotationSegment segment;
if (jlist == nullptr) {
if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) {
env->ExceptionDescribe();
return segment;
}
return segment;
}
jobjectArray array =
reinterpret_cast<jobjectArray>(env->CallObjectMethod(jlist, listToArrayId));
if (env->ExceptionCheck() || (array == nullptr)) {
env->ExceptionDescribe();
return segment;
}
jsize len = env->GetArrayLength(array);
if (len < 0) {
env->ExceptionDescribe();
return segment;
}
segment.reserve(len);
for (jsize i = 0; i < len; i++) {
jobject latLng = reinterpret_cast<jobject>(env->GetObjectArrayElement(array, i));
if (latLng == nullptr) {
env->ExceptionDescribe();
return segment;
}
jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return segment;
}
jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return segment;
}
segment.push_back(mbgl::LatLng(latitude, longitude));
}
return segment;
}
jobject std_vector_string_to_jobject(JNIEnv *env, std::vector<std::string> vector) {
jobject jlist = env->NewObject(arrayListClass, arrayListConstructorId);
if (jlist == nullptr) {
@@ -433,6 +509,176 @@ void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, j
nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration));
}
jlong JNICALL nativeAddMarker(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject marker) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
jobject position = env->GetObjectField(marker, markerPositionId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
jstring jsprite = (jstring)env->GetObjectField(marker, markerSpriteId);
std::string sprite = std_string_from_jstring(env, jsprite);
jdouble latitude = env->GetDoubleField(position, latLngLatitudeId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
jdouble longitude = env->GetDoubleField(position, latLngLongitudeId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
// Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
return (jlong) nativeMapView->getMap().addPointAnnotation(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), sprite));
}
jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polyline) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolyline");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
// ***** Java fields ***** //
// float alpha;
// boolean visible;
// int color
// float width
// List<LatLng> points
jfloat alpha = env->GetFloatField(polyline, polylineAlphaId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
jboolean visible = env->GetBooleanField(polyline, polylineVisibleId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
visible = JNI_TRUE;
jint color = env->GetIntField(polyline, polylineColorId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
int r = (color>>16)&0xFF;
int g = (color>>8)&0xFF;
int b = (color)&0xFF;
int a = (color>>24)&0xFF;
jfloat width = env->GetFloatField(polyline, polylineWidthId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
mbgl::StyleProperties shapeProperties;
mbgl::LineProperties lineProperties;
lineProperties.opacity = alpha;
lineProperties.color = {{ (float)r, (float)g, (float)b, (float)a }};
lineProperties.width = width;
shapeProperties.set<mbgl::LineProperties>(lineProperties);
jobject points = env->GetObjectField(polyline, polylinePointsId);
mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
std::vector<mbgl::ShapeAnnotation> shapes;
shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties);
std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
uint32_t id = shapeAnnotationIDs.at(0);
return (jlong) id;
}
jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polygon) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygon");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
// ***** Java fields ***** //
// float alpha;
// boolean visible;
// int fillColor
// int strokeColor
// float strokeWidth
// List<LatLng> points
// List<List<LatLng>> holes
jfloat alpha = env->GetFloatField(polygon, polygonAlphaId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
jboolean visible = env->GetBooleanField(polygon, polygonVisibleId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
visible = JNI_TRUE;
jint fillColor = env->GetIntField(polygon, polygonFillColorId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return -1;
}
int rF = (fillColor>>16)&0xFF;
int gF = (fillColor>>8)&0xFF;
int bF = (fillColor)&0xFF;
int aF = (fillColor>>24)&0xFF;
int rS = (strokeColor>>16)&0xFF;
int gS = (strokeColor>>8)&0xFF;
int bS = (strokeColor)&0xFF;
int aS = (strokeColor>>24)&0xFF;
// jfloat strokeWidth = env->GetFloatField(polygon, polygonStrokeWidthId);
// if (env->ExceptionCheck()) {
// env->ExceptionDescribe();
// return -1;
// }
mbgl::StyleProperties shapeProperties;
mbgl::FillProperties fillProperties;
fillProperties.opacity = alpha;
fillProperties.stroke_color = {{ (float)rS, (float)gS, (float)bS, (float)aS }};
fillProperties.fill_color = {{ (float)rF, (float)gF, (float)bF, (float)aF }};
shapeProperties.set<mbgl::FillProperties>(fillProperties);
jobject points = env->GetObjectField(polygon, polygonPointsId);
mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
std::vector<mbgl::ShapeAnnotation> shapes;
shapes.emplace_back(mbgl::AnnotationSegments {{ segment }}, shapeProperties);
std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
uint32_t id = shapeAnnotationIDs.at(0);
return (jlong) id;
}
void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong annotationId) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().removeAnnotation((uint32_t)annotationId);
}
jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng");
assert(nativeMapViewPtr != 0);
@@ -783,6 +1029,126 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_ERR;
}
markerClass = env->FindClass("com/mapbox/mapboxgl/annotations/Marker");
if (markerClass == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
markerConstructorId = env->GetMethodID(markerClass, "<init>", "()V");
if (markerConstructorId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
markerPositionId = env->GetFieldID(markerClass, "position", "Lcom/mapbox/mapboxgl/geometry/LatLng;");
if (markerPositionId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
markerSpriteId = env->GetFieldID(markerClass, "sprite", "Ljava/lang/String;");
if (markerSpriteId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineClass = env->FindClass("com/mapbox/mapboxgl/annotations/Polyline");
if (polylineClass == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineConstructorId = env->GetMethodID(polylineClass, "<init>", "()V");
if (polylineConstructorId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineAlphaId = env->GetFieldID(polylineClass, "alpha", "F");
if (polylineAlphaId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineVisibleId = env->GetFieldID(polylineClass, "visible", "Z");
if (polylineVisibleId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineColorId = env->GetFieldID(polylineClass, "color", "I");
if (polylineColorId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineWidthId = env->GetFieldID(polylineClass, "width", "F");
if (polylineWidthId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylinePointsId = env->GetFieldID(polylineClass, "points", "Ljava/util/List;");
if (polylineWidthId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonClass = env->FindClass("com/mapbox/mapboxgl/annotations/Polygon");
if (polygonClass == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonConstructorId = env->GetMethodID(polygonClass, "<init>", "()V");
if (polygonConstructorId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonAlphaId = env->GetFieldID(polygonClass, "alpha", "F");
if (polygonAlphaId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonVisibleId = env->GetFieldID(polygonClass, "visible", "Z");
if (polygonVisibleId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonFillColorId = env->GetFieldID(polygonClass, "fillColor", "I");
if (polygonFillColorId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonStrokeColorId = env->GetFieldID(polygonClass, "strokeColor", "I");
if (polygonStrokeColorId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonStrokeWidthId = env->GetFieldID(polygonClass, "strokeWidth", "F");
if (polygonStrokeWidthId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonPointsId = env->GetFieldID(polygonClass, "points", "Ljava/util/List;");
if (polygonPointsId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonHolesId = env->GetFieldID(polygonClass, "holes", "Ljava/util/List;");
if (polygonHolesId == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom");
if (latLngZoomClass == nullptr) {
env->ExceptionDescribe();
@@ -976,6 +1342,13 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
{"nativeMoveBy", "(JDDJ)V", reinterpret_cast<void *>(&nativeMoveBy)},
{"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V",
reinterpret_cast<void *>(&nativeSetLatLng)},
{"nativeAddMarker", "(JLcom/mapbox/mapboxgl/annotations/Marker;)J",
reinterpret_cast<void *>(&nativeAddMarker)},
{"nativeAddPolyline", "(JLcom/mapbox/mapboxgl/annotations/Polyline;)J",
reinterpret_cast<void *>(&nativeAddPolyline)},
{"nativeAddPolygon", "(JLcom/mapbox/mapboxgl/annotations/Polygon;)J",
reinterpret_cast<void *>(&nativeAddPolygon)},
{"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast<void *>(&nativeRemoveAnnotation)},
{"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;",
reinterpret_cast<void *>(&nativeGetLatLng)},
{"nativeResetPosition", "(J)V", reinterpret_cast<void *>(&nativeResetPosition)},
@@ -1026,6 +1399,24 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_ERR;
}
markerClass = reinterpret_cast<jclass>(env->NewGlobalRef(markerClass));
if (markerClass == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polylineClass = reinterpret_cast<jclass>(env->NewGlobalRef(polylineClass));
if (polylineClass == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
polygonClass = reinterpret_cast<jclass>(env->NewGlobalRef(polygonClass));
if (polygonClass == nullptr) {
env->ExceptionDescribe();
return JNI_ERR;
}
latLngZoomClass = reinterpret_cast<jclass>(env->NewGlobalRef(latLngZoomClass));
if (latLngZoomClass == nullptr) {
env->ExceptionDescribe();
@@ -1109,6 +1500,33 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
latLngLongitudeId = nullptr;
latLngLatitudeId = nullptr;
env->DeleteGlobalRef(markerClass);
markerClass = nullptr;
markerConstructorId = nullptr;
markerPositionId = nullptr;
markerSpriteId = nullptr;
env->DeleteGlobalRef(polylineClass);
polylineClass = nullptr;
polylineConstructorId = nullptr;
polylineAlphaId = nullptr;
polylineVisibleId = nullptr;
polylineColorId = nullptr;
polylineWidthId = nullptr;
polylinePointsId = nullptr;
env->DeleteGlobalRef(polygonClass);
polygonClass = nullptr;
polygonConstructorId = nullptr;
polygonAlphaId = nullptr;
polygonVisibleId = nullptr;
polygonFillColorId = nullptr;
polygonStrokeColorId = nullptr;
polygonStrokeWidthId = nullptr;
polygonPointsId = nullptr;
polygonHolesId = nullptr;
env->DeleteGlobalRef(latLngZoomClass);
latLngZoomClass = nullptr;
latLngZoomConstructorId = nullptr;

View File

@@ -0,0 +1,64 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.views.MapView;
public abstract class Annotation {
/**
* The annotation id
*
* Internal C++ id is stored as unsigned int.
*/
protected Long id; // null unless added to a MapView
private MapView mapView;
float alpha = 1;
boolean visible = true;
public Annotation() {}
public float getAlpha() {
return alpha;
}
public long getId() {
return id;
}
public boolean isVisible() {
return visible;
}
public void remove() {
if (mapView == null) return;
mapView.removeAnnotation(this);
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
public void setId(Long id) {
this.id = id;
}
public void setMapView(MapView mapView) {
this.mapView = mapView;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
// TODO: Implement getZIndex of Google Maps Android API
// public float getZIndex() {
//
// }
// TODO: Implement setZIndex of Google Maps Android API
// public void setZIndex(float zIndex) {
//
// }
}

View File

@@ -0,0 +1,22 @@
package com.mapbox.mapboxgl.annotations;
public abstract class AnnotationOptions {
protected Annotation annotation;
public AnnotationOptions() {}
public AnnotationOptions alpha(float alpha) {
annotation.alpha = alpha;
return this;
}
public float getAlpha() {
return annotation.alpha;
}
public boolean isVisible() {
return annotation.visible;
}
}

View File

@@ -0,0 +1,67 @@
package com.mapbox.mapboxgl.annotations;
import android.graphics.Color;
import com.mapbox.mapboxgl.geometry.LatLng;
/**
* UNIMPLEMENTED: Needs implementation in Native.
*
* https://github.com/mapbox/mapbox-gl-native/issues/1882
* https://github.com/mapbox/mapbox-gl-native/issues/1726
*/
public class Circle extends Annotation {
LatLng center;
int fillColor = Color.BLACK;
double radius;
int strokeColor = Color.BLACK;
float strokeWidth = 10; // Google Maps API defaults to 10
public LatLng getCenter() {
return center;
}
public int getFillColor() {
return fillColor;
}
/**
* Returns the circle's radius, in meters.
*
* @return radius in meters
*/
public double getRadius() {
return radius;
}
public int getStrokeColor() {
return strokeColor;
}
public float getStrokeWidth() {
return strokeWidth;
}
public void setCenter(LatLng center) {
this.center = center;
}
public void setFillColor(int color) {
fillColor = color;
}
public void setRadius(double radius) {
this.radius = radius;
}
public void setStrokeColor (int color) {
strokeColor = color;
}
public void setStrokeWidth (float width) {
strokeWidth = width;
}
}

View File

@@ -0,0 +1,64 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
/**
* UNIMPLEMENTED: Needs implementation in Native.
*
* https://github.com/mapbox/mapbox-gl-native/issues/1882
* https://github.com/mapbox/mapbox-gl-native/issues/1726
*/
public class CircleOptions extends AnnotationOptions {
private Circle circle;
public CircleOptions() {
circle = new Circle();
}
public CircleOptions center(LatLng center) {
circle.center = center;
return this;
}
public CircleOptions fillColor(int color) {
circle.fillColor = color;
return this;
}
public LatLng getCenter() {
return circle.center;
}
public int getFillColor() {
return circle.fillColor;
}
public double getRadius() {
return circle.radius;
}
public int getStrokeColor () {
return circle.strokeColor;
}
public float getStrokeWidth() {
return circle.strokeWidth;
}
public CircleOptions radius (double radius) {
circle.radius = radius;
return this;
}
public CircleOptions strokeColor(int color) {
circle.strokeColor = color;
return this;
}
public CircleOptions strokeWidth (float width) {
circle.strokeWidth = width;
return this;
}
}

View File

@@ -0,0 +1,154 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
public class Marker extends Annotation {
float anchorU;
float anchorV;
boolean draggable;
boolean flat;
float infoWindowAnchorU;
float infoWindowAnchorV;
LatLng position;
float rotation;
String snippet;
String sprite = "default_marker";
String title;
private boolean infoWindowShown = false;
public Marker() {}
/**
* If two markers have the same LatLng, they are equal.
*
* @param other object
* @return boolean - do they have the same LatLng
*/
public boolean equals(Object other) {
if (!(other instanceof Marker)) return false;
double lat = position.getLatitude();
double lng = position.getLongitude();
LatLng otherPosition = ((Marker)other).getPosition();
double otherLat = otherPosition.getLatitude();
double otherLng = otherPosition.getLongitude();
return (lat == otherLat && otherLng == lng);
}
public float getAlpha() {
return alpha;
}
public float getAnchorU() {
return anchorU;
}
public float getAnchorV() {
return anchorV;
}
/**
* NOTE: Google Maps Android API uses String for IDs.
*
* Internal C++ id is stored as unsigned int.
*
* @return the annotation id
*/
public long getId() {
return id;
}
public LatLng getPosition() {
return position;
}
public float getRotation() {
return rotation;
}
public String getSnippet() {
return snippet;
}
public String getTitle() {
return title;
}
public void hideInfoWindow() {
//TODO hideInfoWindow
infoWindowShown = false;
}
public boolean isDraggable() {
return draggable;
}
public boolean isFlat() {
return flat;
}
public boolean isInfoWindowShown () {
return infoWindowShown;
}
void setAnchor(float u, float v) {
this.anchorU = u;
this.anchorV = v;
}
void setDraggable(boolean draggable) {
this.draggable = draggable;
}
void setFlat(boolean flat) {
this.flat = flat;
}
void setInfoWindowAnchor(float u, float v) {
infoWindowAnchorU = u;
infoWindowAnchorV = v;
}
void setPosition(LatLng latlng) {
this.position = position;
}
void setRotation(float rotation) {
this.rotation = rotation;
}
void setSnippet(String snippet) {
this.snippet = snippet;
}
/**
* You can specify the name of a sprite to get a marker other than the default marker.
* This name can be found in the sprite json file:
*
* https://github.com/mapbox/mapbox-gl-styles/blob/mb-pages/sprites/mapbox-streets.json
*
* @param sprite
*/
void setSprite(String sprite) {
this.sprite = sprite;
}
void setTitle(String title) {
this.title = title;
}
void showInfoWindow() {
infoWindowShown = true;
}
// TODO Method in Google Maps Android API
// public int hashCode()
// TODO: Implement this method of Google Maps Android API
// void setIcon(BitmapDescriptor icon) {
//
// }
}

View File

@@ -0,0 +1,125 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
public class MarkerOptions extends AnnotationOptions {
public MarkerOptions() {
annotation = new Marker();
}
public MarkerOptions anchor(float u, float v) {
((Marker)annotation).anchorU = u;
((Marker)annotation).anchorV = v;
return this;
}
public MarkerOptions draggable(boolean draggable) {
((Marker)annotation).draggable = draggable;
return this;
}
public MarkerOptions flat(boolean flat) {
((Marker)annotation).flat = flat;
return this;
}
public float getAnchorU() {
return ((Marker)annotation).anchorU;
}
public float getAnchorV() {
return ((Marker)annotation).anchorV;
}
// TODO: Implement this method of Google Maps Android API
// public BitmapDescriptor getIcon () {
//
// }
public float getInfoWindowAnchorU() {
return ((Marker)annotation).infoWindowAnchorU;
}
public float getInfoWindowAnchorV() {
return ((Marker)annotation).infoWindowAnchorV;
}
public Marker getMarker() {
return (Marker)annotation;
}
public LatLng getPosition() {
return ((Marker)annotation).position;
}
public float getRotation() {
return ((Marker)annotation).rotation;
}
public String getSnippet() {
return ((Marker)annotation).snippet;
}
public String getTitle() {
return ((Marker)annotation).title;
}
public MarkerOptions infoWindowAnchor(float u, float v) {
((Marker)annotation).infoWindowAnchorU = u;
((Marker)annotation).infoWindowAnchorV = v;
return this;
}
public boolean isDraggable() {
return ((Marker)annotation).draggable;
}
public boolean isFlat() {
return ((Marker)annotation).flat;
}
public boolean isVisible() {
return ((Marker)annotation).visible;
}
public MarkerOptions position(LatLng position) {
((Marker)annotation).position = position;
return this;
}
public MarkerOptions rotation(float rotation) {
((Marker)annotation).rotation = rotation;
return this;
}
public MarkerOptions snippet(String snippet) {
((Marker)annotation).snippet = snippet;
return this;
}
public MarkerOptions sprite(String sprite) {
((Marker)annotation).sprite = sprite;
return this;
}
public MarkerOptions title(String title) {
((Marker)annotation).title = title;
return this;
}
public MarkerOptions visible(boolean visible) {
annotation.visible = visible;
return this;
}
// TODO: Implement this method of Google Maps Android API
// public MarkerOptions icon(BitmapDescriptor icon) {
//
// }
// TODO: Implement this method of Google Maps Android API
// public void writeToParcel (Parcel out, int flags)
}

View File

@@ -0,0 +1,53 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
import java.util.ArrayList;
import java.util.List;
public abstract class MultiPoint extends Annotation {
List<LatLng> points;
public MultiPoint() {
super();
points = new ArrayList<>();
}
/**
* Returns a copy of the points.
*
* @return points - as a copy
*/
public List<LatLng> getPoints() {
return new ArrayList<>(points);
}
/**
* Sets the points of this polyline. This method will take a copy
* of the points, so further mutations to points will have no effect
* on this polyline.
*
* @param points
*/
void setPoints(List<LatLng> points) {
this.points = new ArrayList<>(points);
}
// TODO: Implement hashCode of Google Maps Android API
// public int hashCode() {
//
// }
// TODO: Implement isGeodesic of Google Maps Android API
// public boolean isGeodesic() {
//
// }
// TODO: Implement setGeodesic of Google Maps Android API
// public void setGeodesic(boolean geodesic) {
//
// }
}

View File

@@ -0,0 +1,15 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
import java.util.List;
public abstract class MultiPointOptions extends AnnotationOptions {
public MultiPointOptions() {}
public List<LatLng> getPoints() {
// the getter gives us a copy, which is the safe thing to do...
return ((MultiPoint)annotation).getPoints();
}
}

View File

@@ -0,0 +1,99 @@
package com.mapbox.mapboxgl.annotations;
import android.graphics.Color;
import com.mapbox.mapboxgl.geometry.LatLng;
import java.util.ArrayList;
import java.util.List;
public class Polygon extends MultiPoint {
int fillColor = Color.BLACK; // default fillColor is black
float strokeAlpha = 1;
int strokeColor = Color.BLACK; // default strokeColor is black
float strokeWidth = 10; // As specified by Google API Docs (in pixels)
List<List<LatLng>> holes;
public Polygon() {
super();
holes = new ArrayList<>();
}
public int getFillColor() {
return fillColor;
}
public List<List<LatLng>> getHoles () {
return holes;
}
public int getStrokeColor() {
return strokeColor;
}
/**
* UNIMPLEMENTED: Needs implementation in Native.
* https://github.com/mapbox/mapbox-gl-native/issues/1737
* @return stroke width as float
*/
public float getStrokeWidth() {
return strokeWidth;
}
public void setFillAlpha(float alpha) {
this.alpha = alpha;
}
public void setFillColor(int color) {
fillColor = color;
}
/**
* Sets the holes of this polygon. This method will take a copy of the holes,
* so further mutations to holes parameter will have no effect on this polygon.
*
* @param holes
*/
public void setHoles(List<? extends List<LatLng>> holes) {
this.holes = new ArrayList<>();
for (List<LatLng> hole : holes) {
this.holes.add(new ArrayList<>(hole));
}
}
/**
* Sets the alpha (opacity) of the stroke
*
* UNIMPLEMENTED: Needs implementation in Native.
*/
public void setStrokeAlpha(float alpha) {
strokeAlpha = alpha;
}
public void setStrokeColor(int color) {
strokeColor = color;
}
/**
* UNIMPLEMENTED: Needs implementation in Native.
* https://github.com/mapbox/mapbox-gl-native/issues/1737
* @return stroke width as float
*/
public void setStrokeWidth(float width) {
strokeWidth = width;
}
// TODO: Implement equals of Google Maps Android API
// public boolean equals (Object other) {
//
// }
// TODO: Implement hashCode of Google Maps Android API
// public int hashCode () {
//
// }
}

View File

@@ -0,0 +1,125 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
import java.util.ArrayList;
import java.util.List;
public class PolygonOptions extends MultiPointOptions {
public PolygonOptions() {
annotation = new Polygon();
}
public PolygonOptions add(LatLng point) {
((MultiPoint)annotation).points.add(point);
return this;
}
public PolygonOptions add(LatLng... points) {
for (LatLng point : points) {
add(point);
}
return this;
}
public PolygonOptions addAll(Iterable<LatLng> points) {
for (LatLng point : points) {
add(point);
}
return this;
}
/**
* UNIMPLEMENTED: Needs implementation in Native.
* https://github.com/mapbox/mapbox-gl-native/issues/1729
*
* @param points - an iterable (list) of points for cutting a hole
* @return PolygonOptions - the options object
*/
public PolygonOptions addHole (Iterable<LatLng> points) {
List<LatLng> hole = new ArrayList<>();
for (LatLng point : points) {
hole.add(point);
}
((Polygon)annotation).holes.add(hole);
return this;
}
/**
* Sets the color of the polygon.
*
* @param color - the color in ARGB format
* @return PolygonOptions - the options object
*/
public PolygonOptions fillColor(int color) {
((Polygon)annotation).fillColor = color;
return this;
}
public int getFillColor() {
return ((Polygon)annotation).fillColor;
}
/**
* UNIMPLEMENTED: Needs implementation in Native.
* https://github.com/mapbox/mapbox-gl-native/issues/1729
*
* @return a list of lists of points for cutting holes
*/
public List<List<LatLng>> getHoles() {
return ((Polygon)annotation).holes;
}
public Polygon getPolygon() {
return ((Polygon)annotation);
}
public int getStrokeColor() {
return ((Polygon)annotation).strokeColor;
}
/**
* UNIMPLEMENTED: Needs implementation in Native.
* https://github.com/mapbox/mapbox-gl-native/issues/1737
*
* @return stroke width as float
*/
public float getStrokeWidth() {
return ((Polygon)annotation).strokeWidth;
}
/**
* Sets the color of the stroke of the polygon.
*
* @param color - the color in ARGB format
* @return PolygonOptions - the options object
*/
public PolygonOptions strokeColor(int color) {
((Polygon)annotation).strokeColor = color;
return this;
}
/**
* UNIMPLEMENTED: Needs implementation in Native.
* https://github.com/mapbox/mapbox-gl-native/issues/1737
*
* @return stroke width as float
*/
public PolygonOptions strokeWidth(float width) {
((Polygon)annotation).strokeWidth = width;
return this;
}
public PolygonOptions visible(boolean visible) {
annotation.visible = visible;
return this;
}
// TODO: Implement writeToParcel of Google Maps Android API
// public void writeToParcel(Parcel out, int flags) {
//
// }
}

View File

@@ -0,0 +1,51 @@
package com.mapbox.mapboxgl.annotations;
import android.graphics.Color;
import com.mapbox.mapboxgl.geometry.LatLng;
import java.util.List;
public class Polyline extends MultiPoint {
int color = Color.BLACK; // default color is black
float width = 10; // As specified by Google API Docs (in pixels)
public Polyline() {
super();
}
public int getColor() {
return color;
}
public float getWidth() {
return width;
}
/**
* Sets the color of the polyline.
*
* @param color - the color in ARGB format
*/
public void setColor(int color) {
this.color = color;
}
/**
* Sets the width of the polyline.
*
* @param width in pixels
* @return
*/
public void setWidth(float width) {
this.width = width;
}
// TODO: Implement equals of Google Maps Android API
// public boolean equals(Object other) {
//
// }
}

View File

@@ -0,0 +1,75 @@
package com.mapbox.mapboxgl.annotations;
import com.mapbox.mapboxgl.geometry.LatLng;
import java.util.List;
public class PolylineOptions extends MultiPointOptions {
public PolylineOptions() {
annotation = new Polyline();
}
public PolylineOptions add(LatLng point) {
((MultiPoint)annotation).points.add(point);
return this;
}
public PolylineOptions add(LatLng... points) {
for (LatLng point : points) {
add(point);
}
return this;
}
public PolylineOptions addAll(Iterable<LatLng> points) {
for (LatLng point : points) {
add(point);
}
return this;
}
/**
* Sets the color of the polyline.
*
* @param color - the color in ARGB format
*/
public PolylineOptions color(int color) {
((Polyline)annotation).color = color;
return this;
}
public int getColor() {
return ((Polyline)annotation).color;
}
public Polyline getPolyline() {
return ((Polyline)annotation);
}
public float getWidth() {
return ((Polyline)annotation).width;
}
public PolylineOptions visible(boolean visible) {
annotation.visible = visible;
return this;
}
/**
* Sets the width of the polyline.
*
* @param width in pixels
* @return
*/
public PolylineOptions width(float width) {
((Polyline)annotation).width = width;
return this;
}
// TODO: Implement writeToParcel of Google Maps Android API
// public void writeToParcel(Parcel out, int flags) {
//
// }
}

View File

@@ -26,10 +26,16 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.ZoomButtonsController;
import android.util.Log;
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
import com.mapbox.mapboxgl.annotations.Annotation;
import com.mapbox.mapboxgl.annotations.Marker;
import com.mapbox.mapboxgl.annotations.MarkerOptions;
import com.mapbox.mapboxgl.annotations.Polygon;
import com.mapbox.mapboxgl.annotations.PolygonOptions;
import com.mapbox.mapboxgl.annotations.Polyline;
import com.mapbox.mapboxgl.annotations.PolylineOptions;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.geometry.LatLngZoom;
@@ -63,6 +69,11 @@ public class MapView extends SurfaceView {
private static final String STATE_CLASSES = "classes";
private static final String STATE_DEFAULT_TRANSITION_DURATION = "defaultTransitionDuration";
/**
* Every annotation that has been added to the map.
*/
private List<Annotation> annotations = new ArrayList<>();
//
// Instance members
//
@@ -205,6 +216,48 @@ public class MapView extends SurfaceView {
}
}
public Marker addMarker(MarkerOptions markerOptions) {
Marker marker = markerOptions.getMarker();
Long id = mNativeMapView.addMarker(marker);
marker.setId(id); // the annotation needs to know its id
marker.setMapView(this); // the annotation needs to know which map view it is in
annotations.add(marker);
return marker;
}
public Polyline addPolyline(PolylineOptions polylineOptions) {
Polyline polyline = polylineOptions.getPolyline();
Long id = mNativeMapView.addPolyline(polyline);
polyline.setId(id);
polyline.setMapView(this);
annotations.add(polyline);
return polyline;
}
public Polygon addPolygon(PolygonOptions polygonOptions) {
Polygon polygon = polygonOptions.getPolygon();
Long id = mNativeMapView.addPolygon(polygon);
polygon.setId(id);
polygon.setMapView(this);
annotations.add(polygon);
return polygon;
}
public void removeAnnotation(Annotation annotation) {
long id = annotation.getId();
mNativeMapView.removeAnnotation(id);
}
public void removeAnnotation(long annotationId) {
mNativeMapView.removeAnnotation(annotationId);
}
public void removeAnnotations() {
for (Annotation annotation : annotations) {
annotation.remove();
}
}
//
// Property methods
//

View File

@@ -2,8 +2,10 @@ package com.mapbox.mapboxgl.views;
import android.graphics.PointF;
import android.view.Surface;
import android.util.Log;
import com.mapbox.mapboxgl.annotations.Marker;
import com.mapbox.mapboxgl.annotations.Polygon;
import com.mapbox.mapboxgl.annotations.Polyline;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.geometry.LatLngZoom;
import com.mapbox.mapboxgl.geometry.ProjectedMeters;
@@ -214,6 +216,24 @@ class NativeMapView {
nativeSetLatLng(mNativeMapViewPtr, latLng, duration);
}
public long addMarker(Marker marker) {
return nativeAddMarker(mNativeMapViewPtr, marker);
}
public long addPolyline(Polyline polyline) {
// NH TODO Throw exception if returns -1
return nativeAddPolyline(mNativeMapViewPtr, polyline);
}
public long addPolygon(Polygon polygon) {
// NH TODO Throw exception if returns -1
return nativeAddPolygon(mNativeMapViewPtr, polygon);
}
public void removeAnnotation(long id) {
nativeRemoveAnnotation(mNativeMapViewPtr, id);
}
public LatLng getLatLng() {
return nativeGetLatLng(mNativeMapViewPtr);
}
@@ -446,6 +466,14 @@ class NativeMapView {
private native void nativeSetLatLng(long nativeMapViewPtr, LatLng latLng,
long duration);
private native long nativeAddMarker(long nativeMapViewPtr, Marker marker);
private native long nativeAddPolyline(long nativeMapViewPtr, Polyline polyline);
private native long nativeAddPolygon(long mNativeMapViewPtr, Polygon polygon);
private native void nativeRemoveAnnotation(long nativeMapViewPtr, long id);
private native LatLng nativeGetLatLng(long nativeMapViewPtr);
private native void nativeResetPosition(long nativeMapViewPtr);

View File

@@ -0,0 +1 @@
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"LineString","coordinates":[[-121.3714599609375,38.64583568648869],[-121.48681640624999,38.64047263931154],[-121.53076171875,38.61579745317875],[-121.56509399414061,38.57823196583313],[-121.75186157226561,38.533127435052776],[-121.97021484374999,38.35350340353833],[-122.08007812499999,38.24680876017446],[-122.16796875,38.19718009396176],[-122.23800659179686,38.09457899232253],[-122.27371215820312,38.01455819225337],[-122.33551025390625,37.94094845586459],[-122.27371215820312,37.81846319511331],[-122.4151611328125,37.7652868250379]]}}]}

View File

@@ -0,0 +1 @@
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-122.28813171386719,38.617406963286136],[-122.26959228515624,38.6833657775237],[-122.18238830566406,38.55568323796419],[-122.10617065429688,38.51378825951165],[-122.11509704589845,38.50465406475561],[-122.18307495117188,38.542795073979015],[-122.19955444335938,38.496593518947556],[-122.28813171386719,38.617406963286136]]]}}]}

View File

@@ -1,6 +1,7 @@
package com.mapbox.mapboxgl.testapp;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.hardware.GeomagneticField;
@@ -23,6 +24,12 @@ import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import com.mapbox.mapboxgl.annotations.Marker;
import com.mapbox.mapboxgl.annotations.MarkerOptions;
import com.mapbox.mapboxgl.annotations.Polygon;
import com.mapbox.mapboxgl.annotations.PolygonOptions;
import com.mapbox.mapboxgl.annotations.Polyline;
import com.mapbox.mapboxgl.annotations.PolylineOptions;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.views.MapView;
import com.mapzen.android.lost.api.LocationListener;
@@ -30,6 +37,9 @@ import com.mapzen.android.lost.api.LocationRequest;
import com.mapzen.android.lost.api.LocationServices;
import com.mapzen.android.lost.api.LostApiClient;
import org.json.JSONException;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends ActionBarActivity {
@@ -77,6 +87,11 @@ public class MainActivity extends ActionBarActivity {
private float mCompassBearing;
private boolean mCompassValid = false;
// Used for markers
private boolean mIsMarkersOn = false;
private Marker marker;
//
// Lifecycle events
//
@@ -210,6 +225,10 @@ public class MainActivity extends ActionBarActivity {
}
return true;
case R.id.action_markers:
// Toggle markers
toggleMarkers(!mIsMarkersOn);
default:
return super.onOptionsItemSelected(item);
}
@@ -249,6 +268,80 @@ public class MainActivity extends ActionBarActivity {
}
}
/**
* Enable / Disable markers.
*
* @param enableMarkers
*/
private void toggleMarkers(boolean enableMarkers) {
if (enableMarkers) {
if (!mIsMarkersOn) {
mIsMarkersOn = true;
addMarkers();
addPolyline();
addPolygon();
}
} else {
if (mIsMarkersOn) {
mIsMarkersOn = false;
removeAnnotations();
}
}
}
private void addMarkers() {
LatLng backLot = new LatLng(38.649441, -121.369064);
MapView map = mMapFragment.getMap();
marker = map.addMarker(new MarkerOptions()
.position(backLot)
.title("Back Lot")
.snippet("The back lot behind my house"));
LatLng cheeseRoom = new LatLng(38.531577,-122.010646);
map.addMarker(new MarkerOptions()
.position(cheeseRoom)
.sprite("dog-park-15")
.title("Cheese Room")
.snippet("The only air conditioned room on the property!"));
}
private void addPolyline() {
try {
String geojsonStr = Util.loadStringFromAssets(this, "small_line.geojson");
LatLng[] latLngs = Util.parseGeoJSONCoordinates(geojsonStr);
MapView map = mMapFragment.getMap();
Polyline line = map.addPolyline(new PolylineOptions()
.add(latLngs)
.width(2)
.color(Color.RED));
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void addPolygon() {
String geojsonStr = null;
try {
geojsonStr = Util.loadStringFromAssets(this, "small_poly.geojson");
LatLng[] latLngs = Util.parseGeoJSONCoordinates(geojsonStr);
MapView map = mMapFragment.getMap();
Polygon polygon = map.addPolygon(new PolygonOptions()
.add(latLngs)
.strokeColor(Color.MAGENTA)
.fillColor(Color.BLUE));
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void removeAnnotations() {
mMapFragment.getMap().removeAnnotations();
}
// This class forwards location updates to updateLocation()
private class GpsListener implements LocationListener {

View File

@@ -7,6 +7,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.views.MapView;
import java.io.BufferedReader;
@@ -77,6 +78,8 @@ public class MapFragment extends Fragment {
// Need to pass on to view
mMap.onStart();
mMap.setCenterCoordinate(new LatLng(38.247887,-121.843872));
mMap.setZoomLevel(7);
}
// Called when the fragment is invisible

View File

@@ -0,0 +1,61 @@
package com.mapbox.mapboxgl.testapp;
import android.content.Context;
import android.text.TextUtils;
import com.mapbox.mapboxgl.geometry.LatLng;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
public class Util {
public static String loadStringFromAssets(final Context context, final String fileName) throws IOException {
if (TextUtils.isEmpty(fileName)) {
throw new NullPointerException("No GeoJSON File Name passed in.");
}
InputStream is = context.getAssets().open(fileName);
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
return readAll(rd);
}
public static LatLng[] parseGeoJSONCoordinates(String geojsonStr) throws JSONException {
JSONObject jsonObject = new JSONObject(geojsonStr);
JSONArray features = jsonObject.getJSONArray("features");
JSONObject feature = features.getJSONObject(0);
JSONObject geometry = feature.getJSONObject("geometry");
String type = geometry.getString("type");
JSONArray coordinates;
if (type.equals("Polygon")) {
coordinates = geometry.getJSONArray("coordinates").getJSONArray(0);
} else {
coordinates = geometry.getJSONArray("coordinates");
}
int len = coordinates.length();
LatLng[] latLngs = new LatLng[coordinates.length()];
for (int i = 0; i < len; ++i) {
JSONArray coord = coordinates.getJSONArray(i);
double lng = coord.getDouble(0);
double lat = coord.getDouble(1);
latLngs[i] = new LatLng(lat, lng);
}
return latLngs;
}
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
}

View File

@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_gps"
android:icon="@drawable/ic_action_location_searching"
android:title="@string/action_gps"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_debug"
android:icon="@drawable/ic_action_about"
android:title="@string/action_debug"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_markers"
android:icon="@android:drawable/ic_menu_myplaces"
android:title="@string/action_point_annotations"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_gps"
android:icon="@drawable/ic_action_location_searching"
android:title="@string/action_gps"
app:showAsAction="ifRoom" />
</menu>

View File

@@ -7,6 +7,8 @@
<string name="action_debug">Toggle debug mode</string>
<string name="action_point_annotations">Toggle point annotations</string>
<string name="label_fps">FPS:</string>
<string name="compass_desc">Map compass. Click to reset the map rotation to North.</string>