summaryrefslogtreecommitdiff
path: root/platform/android/src/geometry/conversion
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2016-08-04 14:45:50 -0400
committerIvo van Dongen <info@ivovandongen.nl>2016-08-16 11:38:30 +0200
commit4e211548d5029a353aaa8814c40599970a8098bd (patch)
tree9cad650747190f6fbd1bb53f034baee3e86f6517 /platform/android/src/geometry/conversion
parentdcd9e1016cd20f107c4e34be62c631a1f4189af1 (diff)
downloadqtlocation-mapboxgl-4e211548d5029a353aaa8814c40599970a8098bd.tar.gz
[android] #5869 - visible feature querying
Diffstat (limited to 'platform/android/src/geometry/conversion')
-rw-r--r--platform/android/src/geometry/conversion/feature.hpp209
-rw-r--r--platform/android/src/geometry/conversion/geometry.hpp184
2 files changed, 393 insertions, 0 deletions
diff --git a/platform/android/src/geometry/conversion/feature.hpp b/platform/android/src/geometry/conversion/feature.hpp
new file mode 100644
index 0000000000..857b76da50
--- /dev/null
+++ b/platform/android/src/geometry/conversion/feature.hpp
@@ -0,0 +1,209 @@
+#pragma once
+
+#include "../../conversion/constant.hpp"
+#include "../../conversion/conversion.hpp"
+#include "geometry.hpp"
+
+#include <mbgl/util/feature.hpp>
+#include <mapbox/variant.hpp>
+#include <mapbox/geometry.hpp>
+
+#include <jni/jni.hpp>
+#include "../../jni/local_object.hpp"
+
+#include <string>
+#include <array>
+#include <vector>
+#include <sstream>
+
+#include <mbgl/platform/log.hpp>
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+/**
+ * Turn feature identifier into std::string
+ */
+class FeatureIdVisitor {
+public:
+
+ template<class T>
+ std::string operator()(const T& i) const {
+ return std::to_string(i);
+ }
+
+ std::string operator()(const std::string& i) const {
+ return i;
+ }
+
+ std::string operator()(const std::nullptr_t&) const {
+ return "";
+ }
+
+};
+
+/**
+ * Turn properties into Java GSON JsonObject's
+ */
+class PropertyValueEvaluator {
+public:
+ jni::JNIEnv& env;
+
+ /**
+ * null
+ */
+ jni::jobject* operator()(const mapbox::geometry::null_value_t &) const {
+ return (jni::jobject*) nullptr;
+ }
+
+ /**
+ * Boolean primitive
+ */
+ jni::jobject* operator()(const bool& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Z)V");
+
+ //Create JsonPrimitive
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, bool>(env, value));
+ jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted);
+
+ return object;
+ }
+
+ /**
+ * String primitive
+ */
+ jni::jobject* operator()(const std::string& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/String;)V");
+
+ //Create JsonPrimitive
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, value));
+ jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
+
+ return object;
+ }
+
+ /**
+ * Number primitives
+ */
+ template <class Number>
+ jni::jobject* operator()(const Number& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Number;)V");
+
+ //Create JsonPrimitive
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, Number>(env, value));
+ jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
+
+ return object;
+ }
+
+
+ /**
+ * Json Array
+ */
+ jni::jobject* operator()(const std::vector<mbgl::Value> &values) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
+ static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V");
+
+ //Create json array
+ jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor);
+
+ //Add values
+ for (const auto &v : values) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this));
+ jni::CallMethod<void>(env, jarray, *add, converted.get());
+ }
+
+ return jarray;
+ }
+
+ /**
+ * Json Object
+ */
+ jni::jobject* operator()(const std::unordered_map<std::string, mbgl::Value> &value) const {
+ //TODO: clean up duplication here
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
+ static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
+
+ //Create json object
+ jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
+
+ //Add items
+ for (auto &item : value) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this));
+ jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
+ jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
+ }
+
+ return jsonObject;
+ }
+};
+
+template <>
+struct Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>> {
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
+ static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
+
+ //Create json object
+ jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
+
+ //Add items
+ PropertyValueEvaluator evaluator {env};
+ for (auto &item : value) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator));
+ jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
+ jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
+ }
+
+ return {jsonObject};
+ }
+};
+
+
+template <>
+struct Converter<jni::jobject*, mbgl::Feature> {
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release();
+ static jni::jmethodID* fromGeometry = &jni::GetStaticMethodID(env, *javaClass, "fromGeometry", "(Lcom/mapbox/services/commons/geojson/Geometry;Lcom/google/gson/JsonObject;Ljava/lang/String;)Lcom/mapbox/services/commons/geojson/Feature;");
+
+ //Convert Id
+ FeatureIdVisitor idEvaluator;
+ std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : "";
+ jni::LocalObject<jni::jobject> jid = jni::NewLocalObject(env, *convert<jni::jobject*>(env, id));
+
+ //Convert properties
+ jni::LocalObject<jni::jobject> properties = jni::NewLocalObject(env, *convert<jni::jobject*>(env, value.properties));
+
+ //Convert geometry
+ jni::LocalObject<jni::jobject> geometry = jni::NewLocalObject(env, *convert<jni::jobject*>(env, value.geometry));
+
+ //Create feature
+ return {reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometry, geometry.get(), properties.get(), jid.get()))};
+ }
+};
+
+template <>
+struct Converter<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>> {
+ Result<jni::jarray<jni::jobject>*> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const {
+ static jni::jclass* featureClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release();
+ jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *featureClass);
+
+ for(size_t i = 0; i < value.size(); i = i + 1) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, mbgl::Feature>(env, value.at(i)));
+ jni::SetObjectArrayElement(env, jarray, i, converted.get());
+ }
+
+ return {&jarray};
+ }
+};
+
+} // namespace conversion
+} // namespace android
+} // namespace mbgl
diff --git a/platform/android/src/geometry/conversion/geometry.hpp b/platform/android/src/geometry/conversion/geometry.hpp
new file mode 100644
index 0000000000..385ba9034e
--- /dev/null
+++ b/platform/android/src/geometry/conversion/geometry.hpp
@@ -0,0 +1,184 @@
+#pragma once
+
+#include "../../conversion/constant.hpp"
+#include "../../conversion/collection.hpp"
+
+#include <mapbox/geometry.hpp>
+#include <jni/jni.hpp>
+#include "../../jni/local_object.hpp"
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+/**
+ * Turn mapbox::geometry type into Java GeoJson Geometries
+ */
+template <typename T>
+class GeometryEvaluator {
+public:
+
+ jni::JNIEnv& env;
+
+ /**
+ * Point (double[])
+ */
+ jni::jobject* operator()(const mapbox::geometry::point<T> &geometry) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Point")).release();
+ static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([D)Lcom/mapbox/services/commons/geojson/Point;");
+
+ //Create Point
+ jni::LocalObject<jni::jarray<jni::jdouble>> position = jni::NewLocalObject(env, toGeoJsonPosition(env, geometry.x, geometry.y));
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, position.get()));
+ }
+
+ /**
+ * LineString (double[][])
+ */
+ jni::jobject* operator()(const mapbox::geometry::line_string<T> &geometry) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/LineString")).release();
+ static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/LineString;");
+
+ //Create
+ jni::LocalObject<jni::jarray<jni::jobject>> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry));
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, coordinates.get()));
+ }
+
+ /**
+ * MultiPoint (double[][])
+ */
+ jni::jobject* operator()(const mapbox::geometry::multi_point<T> &geometry) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPoint")).release();
+ static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/MultiPoint;");
+
+ //Create
+ jni::LocalObject<jni::jarray<jni::jobject>> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry));
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, coordinates.get()));
+ }
+
+ /**
+ * Polygon (double[][][])
+ */
+ jni::jobject* operator()(const mapbox::geometry::polygon<T> &geometry) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Polygon")).release();
+ static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/Polygon;");
+
+ //Create
+ jni::LocalObject<jni::jarray<jni::jobject>> shape = jni::NewLocalObject(env, toShape<>(env, geometry));
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, shape.get()));
+ }
+
+ /**
+ * MultiLineString (double[][][])
+ */
+ jni::jobject* operator()(const mapbox::geometry::multi_line_string<T> &geometry) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiLineString")).release();
+ static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/MultiLineString;");
+
+ //Create
+ jni::LocalObject<jni::jarray<jni::jobject>> shape = jni::NewLocalObject(env, toShape<>(env, geometry));
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, shape.get()));
+ }
+
+ /**
+ * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D
+ */
+ jni::jobject* operator()(const mapbox::geometry::multi_polygon<T> &geometry) const {
+ static jni::jclass* listClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[[D")).release();
+ jni::LocalObject<jni::jarray<jni::jobject>> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, geometry.size(), *listClass));
+
+ for(size_t i = 0; i < geometry.size(); i = i + 1) {
+ jni::LocalObject<jni::jarray<jni::jobject>> shape = jni::NewLocalObject(env, toShape<>(env, geometry.at(i)));
+ jni::SetObjectArrayElement(env, *jarray, i, shape.get());
+ }
+
+ //Create the MultiPolygon
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPolygon")).release();
+ static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[[D)Lcom/mapbox/services/commons/geojson/MultiPolygon;");
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometries, jarray.get()));
+ }
+
+ /**
+ * GeometryCollection
+ */
+ jni::jobject* operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
+ static jni::jclass* geometryClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Geometry")).release();
+ jni::LocalObject<jni::jarray<jni::jobject>> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, collection.size(), *geometryClass));
+
+ for(size_t i = 0; i < collection.size(); i = i + 1) {
+ auto& geometry = collection.at(i);
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mapbox::geometry::geometry<T>::visit(geometry, *this));
+ jni::SetObjectArrayElement(env, *jarray, i, converted.get());
+ }
+
+ //Turn into array list and create the GeometryCollection
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/GeometryCollection")).release();
+ static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromGeometries", "(Ljava/util/List;)Lcom/mapbox/services/commons/geojson/GeometryCollection;");
+
+ jni::LocalObject<jni::jobject> list = jni::NewLocalObject(env, toArrayList<>(env, *jarray));
+ return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometries, list.get()));
+ }
+
+private:
+
+ /**
+ * x, y -> jarray<jdouble> ([x,y])
+ */
+ static jni::jarray<jni::jdouble>* toGeoJsonPosition(JNIEnv& env, double x, double y) {
+ jni::jarray<jni::jdouble>& jarray = jni::NewArray<jni::jdouble>(env, 2);
+ jni::jdouble array[] = {x, y};
+ jni::SetArrayRegion(env, jarray, 0, 2, array);
+ return &jarray;
+ }
+
+ /**
+ * vector<point<T>> -> jarray<jobject> (double[][]) -> [D + Object array == [[D
+ */
+ static jni::jarray<jni::jobject>* toGeoJsonCoordinates(JNIEnv& env, std::vector<mapbox::geometry::point<T>> points) {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[D")).release();
+ jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, points.size(), *javaClass);
+
+ for(size_t i = 0; i < points.size(); i = i + 1) {
+ mapbox::geometry::point<T> point = points.at(i);
+ jni::LocalObject<jni::jarray<jni::jdouble>> position = jni::NewLocalObject(env, toGeoJsonPosition(env, point.x, point.y));
+ jni::SetObjectArrayElement(env, jarray, i, position.get());
+ }
+
+ return &jarray;
+ }
+
+ /**
+ * polygon<T>
+ * multi_line_string<T>
+ * -> jarray<jobject> (double[][][]) -> [[D + Object array == [[[D
+ */
+ template <class SHAPE>
+ static jni::jarray<jni::jobject>* toShape(JNIEnv& env, SHAPE value) {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[D")).release();
+ jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *javaClass);
+
+ for(size_t i = 0; i < value.size(); i = i + 1) {
+ jni::LocalObject<jni::jarray<jni::jobject>> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, value.at(i)));
+ jni::SetObjectArrayElement(env, jarray, i, coordinates.get());
+ }
+
+ return &jarray;
+ }
+};
+
+/**
+ * mapbox::geometry::geometry<T> -> Java GeoJson Geometry<>
+ */
+template <class T>
+struct Converter<jni::jobject*, mapbox::geometry::geometry<T>> {
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry<T>& value) const {
+ GeometryEvaluator<double> evaluator { env } ;
+ jni::jobject* converted = mapbox::geometry::geometry<double>::visit(value, evaluator);
+ return {converted};
+ }
+};
+
+
+}
+}
+}