diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2018-03-13 12:31:56 +0200 |
---|---|---|
committer | Ivo van Dongen <ivovandongen@users.noreply.github.com> | 2018-03-19 11:19:09 +0200 |
commit | 2464520da18f0f4cc7532adb3fb7b1f8f195304e (patch) | |
tree | 8a391da645a7a84fce5ba2e05a0ef2422474d0cd | |
parent | f2fbe69b32d7683d489b1f259b6db49070736980 (diff) | |
download | qtlocation-mapboxgl-2464520da18f0f4cc7532adb3fb7b1f8f195304e.tar.gz |
[android] high-level jni bindings for geojson conversion
23 files changed, 320 insertions, 198 deletions
diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 2694068dac..80d0810564 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -229,6 +229,8 @@ add_library(mbgl-android STATIC platform/android/src/geojson/feature_collection.hpp platform/android/src/geojson/geometry.cpp platform/android/src/geojson/geometry.hpp + platform/android/src/geojson/geometry_collection.cpp + platform/android/src/geojson/geometry_collection.hpp platform/android/src/geojson/line_string.cpp platform/android/src/geojson/line_string.hpp platform/android/src/geojson/multi_line_string.cpp diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp index 86aa5fc03c..8fc62a2789 100644 --- a/platform/android/src/geojson/conversion/feature.hpp +++ b/platform/android/src/geojson/conversion/feature.hpp @@ -182,7 +182,7 @@ struct Converter<jni::Object<android::geojson::Feature>, mbgl::Feature> { auto properties = jni::Object<gson::JsonObject>(*convert<jni::jobject*>(env, value.properties)); // Convert geometry - auto geometry = jni::Object<android::geojson::Geometry>(*convert<jni::jobject*>(env, value.geometry)); + auto geometry = *convert<jni::Object<android::geojson::Geometry>>(env, value.geometry); // Create feature auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid); diff --git a/platform/android/src/geojson/conversion/geometry.hpp b/platform/android/src/geojson/conversion/geometry.hpp index 48b9089692..242a68df02 100644 --- a/platform/android/src/geojson/conversion/geometry.hpp +++ b/platform/android/src/geojson/conversion/geometry.hpp @@ -1,192 +1,24 @@ #pragma once -#include "../../conversion/constant.hpp" -#include "../../conversion/collection.hpp" - #include <mapbox/geometry.hpp> +#include "../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; - - /** - * static Point fromLngLat(double longitude,double latitude) - */ - jni::jobject* operator()(const mapbox::geometry::point<T> &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Point")).release(); - static jni::jmethodID* fromLngLat = &jni::GetStaticMethodID(env, *javaClass, "fromLngLat", "(DD)Lcom/mapbox/geojson/Point;"); - - return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLat, geometry.x, geometry.y)); - } - - /** - * static LineString fromLngLats(double [][]) - */ - jni::jobject* operator()(const mapbox::geometry::line_string<T> &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/LineString")).release(); - static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "([[D)Lcom/mapbox/geojson/LineString;"); - - // Create - jni::LocalObject<jni::jarray<jni::jobject>> lngLatsArray = - jni::NewLocalObject(env, toLngLatArray(env, geometry)); - return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, lngLatsArray.get())); - } - - /** - * static MultiPoint fromLngLats(double [][]) - */ - jni::jobject* operator()(const mapbox::geometry::multi_point<T> &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/MultiPoint")).release(); - static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "([[D)Lcom/mapbox/geojson/MultiPoint;"); - - // Create - jni::LocalObject<jni::jarray<jni::jobject>> lngLatsArray = - jni::NewLocalObject(env, toLngLatArray(env, geometry)); - return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, lngLatsArray.get())); - } - - /** - * static Polygon fromLngLats(double [][][]) - */ - jni::jobject* operator()(const mapbox::geometry::polygon<T> &geometry) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Polygon")).release(); - static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "([[[D)Lcom/mapbox/geojson/Polygon;"); - - // Create - jni::LocalObject<jni::jarray<jni::jobject>> shape = - jni::NewLocalObject(env, shapeToLngLatArray<>(env, geometry)); - return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, shape.get())); - } - - /** - * static MultiLineString fromLngLats(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/geojson/MultiLineString")).release(); - static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "([[[D)Lcom/mapbox/geojson/MultiLineString;"); - - // Create - jni::LocalObject<jni::jarray<jni::jobject>> shape = - jni::NewLocalObject(env,shapeToLngLatArray<>(env, geometry)); - return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, shape.get())); - } - - /** - * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D - */ - jni::jobject* operator()(const mapbox::geometry::multi_polygon<T> &geometry) const { - - static jni::jclass* arrayClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[[D")).release(); - jni::LocalObject<jni::jarray<jni::jobject>> jarray = - jni::NewLocalObject(env, &jni::NewObjectArray(env, geometry.size(), *arrayClass)); - - for(size_t i = 0; i < geometry.size(); i = i + 1) { - jni::LocalObject<jni::jarray<jni::jobject>> shape = - jni::NewLocalObject(env, shapeToLngLatArray<>(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/geojson/MultiPolygon")).release(); - static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "([[[[D)Lcom/mapbox/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/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/geojson/GeometryCollection")).release(); - static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromGeometries", "(Ljava/util/List;)Lcom/mapbox/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> *toLngLatArray(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> -> [D + Object array == [[D (double[][]) - */ - static jni::jarray<jni::jobject>* toLngLatArray(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::jarray<jni::jdouble> *lngLatArray = toLngLatArray(env, point.x, point.y); - jni::SetObjectArrayElement(env, jarray, i, lngLatArray); - } - - return &jarray; - } - - /** - * polygon<T> - * multi_line_string<T> -> jarray<jobject> -> [[D + Object array == [[[D (double[][][]) - */ - template <class SHAPE> - static jni::jarray<jni::jobject>* shapeToLngLatArray(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>> lngLatsArray = - jni::NewLocalObject(env, toLngLatArray(env, value.at(i))); - jni::SetObjectArrayElement(env, jarray, i, lngLatsArray.get()); - } - - return &jarray; - } -}; - -/** - * mapbox::geometry::geometry<T> -> Java GeoJson Geometry<> + * 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}; +struct Converter<jni::Object<android::geojson::Geometry>, mapbox::geometry::geometry<T>> { + Result<jni::Object<android::geojson::Geometry>> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry<T>& value) const { + return { android::geojson::Geometry::New(env, value) }; } }; -} -} -} +} // conversion +} // android +} // mbgl diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp index ca19d8fb03..5635b5a0f5 100644 --- a/platform/android/src/geojson/geometry.cpp +++ b/platform/android/src/geojson/geometry.cpp @@ -6,6 +6,7 @@ #include "multi_line_string.hpp" #include "polygon.hpp" #include "multi_polygon.hpp" +#include "geometry_collection.hpp" #include <string> @@ -13,7 +14,49 @@ namespace mbgl { namespace android { namespace geojson { -mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) { +/** + * Turn mapbox::geometry type into Java GeoJson Geometries + */ +class GeometryEvaluator { +public: + + jni::JNIEnv& env; + + jni::Object<Geometry> operator()(const mbgl::Point<double> &geometry) const { + return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass); + } + + jni::Object<Geometry> operator()(const mbgl::LineString<double> &geometry) const { + return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass); + } + + jni::Object<Geometry> operator()(const mbgl::MultiLineString<double> &geometry) const { + return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass); + } + + jni::Object<Geometry> operator()(const mbgl::MultiPoint<double> &geometry) const { + return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass); + } + + jni::Object<Geometry> operator()(const mbgl::Polygon<double> &geometry) const { + return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass); + } + + jni::Object<Geometry> operator()(const mbgl::MultiPolygon<double> &geometry) const { + return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass); + } + + jni::Object<Geometry> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const { + return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass); + } +}; + +jni::Object<Geometry> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) { + GeometryEvaluator evaluator { env } ; + return mbgl::Geometry<double>::visit(geometry, evaluator); +} + +mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) { auto type = Geometry::getType(env, jGeometry); if (type == Point::Type()) { return { Point::convert(env, jni::Object<Point>(jGeometry.Get())) }; @@ -27,6 +70,8 @@ mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object<Geomet return { Polygon::convert(env, jni::Object<Polygon>(jGeometry.Get())) }; } else if (type == MultiPolygon::Type()) { return { MultiPolygon::convert(env, jni::Object<MultiPolygon>(jGeometry.Get())) }; + } else if (type == GeometryCollection::Type()) { + return { GeometryCollection::convert(env, jni::Object<GeometryCollection>(jGeometry.Get())) }; } throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type); diff --git a/platform/android/src/geojson/geometry.hpp b/platform/android/src/geojson/geometry.hpp index b7f8909f6f..a1bb886683 100644 --- a/platform/android/src/geojson/geometry.hpp +++ b/platform/android/src/geojson/geometry.hpp @@ -1,8 +1,10 @@ #pragma once -#include <mbgl/util/geojson.hpp> +#include <mbgl/util/geometry.hpp> #include <mbgl/util/noncopyable.hpp> +#include "../java/util.hpp" + #include <jni/jni.hpp> namespace mbgl { @@ -13,7 +15,9 @@ class Geometry : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; }; - static mapbox::geojson::geometry convert(jni::JNIEnv&, jni::Object<Geometry>); + static jni::Object<Geometry> New(jni::JNIEnv&, mbgl::Geometry<double>); + + static mbgl::Geometry<double> convert(jni::JNIEnv&, jni::Object<Geometry>); static std::string getType(jni::JNIEnv&, jni::Object<Geometry>); diff --git a/platform/android/src/geojson/geometry_collection.cpp b/platform/android/src/geojson/geometry_collection.cpp new file mode 100644 index 0000000000..eb3a790404 --- /dev/null +++ b/platform/android/src/geojson/geometry_collection.cpp @@ -0,0 +1,63 @@ +#include "geometry_collection.hpp" +#include "../java/util.hpp" + +namespace mbgl { +namespace android { +namespace geojson { + +jni::Object<GeometryCollection> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) { + // Create an array of geometries + auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size(), Geometry::javaClass); + + for (size_t i = 0; i < collection.size(); i++) { + auto& geometry = collection.at(i); + auto jGeometry = Geometry::New(env, geometry); + jarray.Set(env, i, jGeometry); + jni::DeleteLocalRef(env, jGeometry); + } + + // Turn into array list + auto jList = java::util::Arrays::asList(env, jarray); + jni::DeleteLocalRef(env, jarray); + + // create the GeometryCollection + static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(env, "fromGeometries"); + auto jCollection = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jCollection; +} + +mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, jni::Object<GeometryCollection> jCollection) { + // Get geometries + static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "getGeometries"); + auto jList = jCollection.Call(env, getGeometries); + + // Turn into array + auto jarray = java::util::List::toArray<Geometry>(env, jList); + jni::DeleteLocalRef(env, jList); + + // Convert each geometry + mapbox::geometry::geometry_collection<double> collection{}; + + auto size = jarray.Length(env); + for (jni::jsize i = 0; i < size; i++) { + auto element = jarray.Get(env, i); + collection.push_back(Geometry::convert(env, element)); + jni::DeleteLocalRef(env, element); + } + + jni::DeleteLocalRef(env, jarray); + return collection; +} + +void GeometryCollection::registerNative(jni::JNIEnv &env) { + // Lookup the class + javaClass = *jni::Class<GeometryCollection>::Find(env).NewGlobalRef(env).release(); +} + +jni::Class<GeometryCollection> GeometryCollection::javaClass; + +} // namespace geojson +} // namespace android +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/geometry_collection.hpp b/platform/android/src/geojson/geometry_collection.hpp new file mode 100644 index 0000000000..9ed9953b0d --- /dev/null +++ b/platform/android/src/geojson/geometry_collection.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "geometry.hpp" + +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { +namespace geojson { + +class GeometryCollection : public Geometry { +public: + static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; }; + + static constexpr auto Type() { return "GeometryCollection"; }; + + static jni::Object<GeometryCollection> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&); + + static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, jni::Object<GeometryCollection>); + + static jni::Class<GeometryCollection> javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace geojson +} // namespace android +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/line_string.cpp b/platform/android/src/geojson/line_string.cpp index 8eebd53550..a5f1a468ce 100644 --- a/platform/android/src/geojson/line_string.cpp +++ b/platform/android/src/geojson/line_string.cpp @@ -1,11 +1,22 @@ #include "line_string.hpp" - #include "point.hpp" +#include "util.hpp" +#include "../java/util.hpp" namespace mbgl { namespace android { namespace geojson { +jni::Object<LineString> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) { + auto jList = asPointsList(env, lineString); + + static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(env, "fromLngLats"); + auto jLineString = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jLineString; +} + mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object<LineString> jLineString) { mapbox::geojson::line_string lineString; diff --git a/platform/android/src/geojson/line_string.hpp b/platform/android/src/geojson/line_string.hpp index 86033c2e6a..98dc414642 100644 --- a/platform/android/src/geojson/line_string.hpp +++ b/platform/android/src/geojson/line_string.hpp @@ -1,23 +1,27 @@ #pragma once #include <mbgl/util/geojson.hpp> +#include <mbgl/util/geometry.hpp> #include <mbgl/util/noncopyable.hpp> -#include <jni/jni.hpp> - +#include "geometry.hpp" #include "../java/util.hpp" +#include <jni/jni.hpp> + namespace mbgl { namespace android { namespace geojson { -class LineString : private mbgl::util::noncopyable { +class LineString : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/LineString"; }; static constexpr auto Type() { return "LineString"; }; + static jni::Object<LineString> New(jni::JNIEnv&, const mbgl::LineString<double>&); + static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object<LineString>); static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object<java::util::List/*<Point>*/>); diff --git a/platform/android/src/geojson/multi_line_string.cpp b/platform/android/src/geojson/multi_line_string.cpp index c748d4786f..4a6ea37dd1 100644 --- a/platform/android/src/geojson/multi_line_string.cpp +++ b/platform/android/src/geojson/multi_line_string.cpp @@ -1,11 +1,22 @@ #include "multi_line_string.hpp" #include "line_string.hpp" +#include "util.hpp" namespace mbgl { namespace android { namespace geojson { +jni::Object<MultiLineString> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) { + auto jList = asPointsListsList(env, multiLineString); + + static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(env, "fromLngLats"); + auto jMultiLineString = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jMultiLineString; +} + mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object<MultiLineString> jMultiLineString) { mapbox::geojson::multi_line_string multiLineString; diff --git a/platform/android/src/geojson/multi_line_string.hpp b/platform/android/src/geojson/multi_line_string.hpp index 358a6b5dda..934a0cb6b5 100644 --- a/platform/android/src/geojson/multi_line_string.hpp +++ b/platform/android/src/geojson/multi_line_string.hpp @@ -3,20 +3,23 @@ #include <mbgl/util/geojson.hpp> #include <mbgl/util/noncopyable.hpp> -#include <jni/jni.hpp> - #include "../java/util.hpp" +#include "geometry.hpp" + +#include <jni/jni.hpp> namespace mbgl { namespace android { namespace geojson { -class MultiLineString : private mbgl::util::noncopyable { +class MultiLineString : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; }; static constexpr auto Type() { return "MultiLineString"; }; + static jni::Object<MultiLineString> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&); + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object<MultiLineString>); static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object<java::util::List/*<java::util::List<Point>>*/>); diff --git a/platform/android/src/geojson/multi_point.cpp b/platform/android/src/geojson/multi_point.cpp index 4f9ff596b2..6f62541209 100644 --- a/platform/android/src/geojson/multi_point.cpp +++ b/platform/android/src/geojson/multi_point.cpp @@ -8,6 +8,16 @@ namespace mbgl { namespace android { namespace geojson { +jni::Object<MultiPoint> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) { + auto jList = asPointsList(env, multiPoint); + + static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(env, "fromLngLats"); + auto jMultiPoint = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jMultiPoint; +} + mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object<MultiPoint> jMultiPoint) { mapbox::geojson::multi_point multiPoint; diff --git a/platform/android/src/geojson/multi_point.hpp b/platform/android/src/geojson/multi_point.hpp index e893e879af..cfe80cd34c 100644 --- a/platform/android/src/geojson/multi_point.hpp +++ b/platform/android/src/geojson/multi_point.hpp @@ -1,22 +1,26 @@ #pragma once #include <mbgl/util/geojson.hpp> +#include <mbgl/util/geometry.hpp> #include <mbgl/util/noncopyable.hpp> -#include <jni/jni.hpp> - +#include "geometry.hpp" #include "../java/util.hpp" +#include <jni/jni.hpp> + namespace mbgl { namespace android { namespace geojson { -class MultiPoint : private mbgl::util::noncopyable { +class MultiPoint : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; }; static constexpr auto Type() { return "MultiPoint"; }; + static jni::Object<MultiPoint> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&); + static mapbox::geojson::multi_point convert(jni::JNIEnv&, jni::Object<MultiPoint>); static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPoint>); diff --git a/platform/android/src/geojson/multi_polygon.cpp b/platform/android/src/geojson/multi_polygon.cpp index aadba8c8a6..cc872d4955 100644 --- a/platform/android/src/geojson/multi_polygon.cpp +++ b/platform/android/src/geojson/multi_polygon.cpp @@ -1,11 +1,34 @@ #include "multi_polygon.hpp" #include "polygon.hpp" +#include "util.hpp" namespace mbgl { namespace android { namespace geojson { +jni::Object<MultiPolygon> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) { + auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size(), java::util::List::javaClass); + + for (size_t i = 0; i < multiPolygon.size(); i++) { + auto& geometry = multiPolygon.at(i); + auto jPolygon = asPointsListsList(env, geometry); + jarray.Set(env, i, jPolygon); + jni::DeleteLocalRef(env, jPolygon); + } + + // Turn into array list + auto jList = java::util::Arrays::asList(env, jarray); + jni::DeleteLocalRef(env, jarray); + + // create the MultiPolygon + static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats"); + auto jMultiPolygon = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jMultiPolygon; +} + mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object<MultiPolygon> jMultiPolygon) { mapbox::geojson::multi_polygon multiPolygon; diff --git a/platform/android/src/geojson/multi_polygon.hpp b/platform/android/src/geojson/multi_polygon.hpp index 6e1dfacfc8..b4657af09d 100644 --- a/platform/android/src/geojson/multi_polygon.hpp +++ b/platform/android/src/geojson/multi_polygon.hpp @@ -3,20 +3,23 @@ #include <mbgl/util/geojson.hpp> #include <mbgl/util/noncopyable.hpp> -#include <jni/jni.hpp> - #include "../java/util.hpp" +#include "geometry.hpp" + +#include <jni/jni.hpp> namespace mbgl { namespace android { namespace geojson { -class MultiPolygon : private mbgl::util::noncopyable { +class MultiPolygon : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; }; static constexpr auto Type() { return "MultiPolygon"; }; + static jni::Object<MultiPolygon> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&); + static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, jni::Object<MultiPolygon>); static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPolygon>); diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index e95376cd2e..aa9dc1a7f6 100644 --- a/platform/android/src/geojson/point.cpp +++ b/platform/android/src/geojson/point.cpp @@ -7,6 +7,11 @@ namespace mbgl { namespace android { namespace geojson { +jni::Object<Point> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) { + static auto method = javaClass.GetStaticMethod<jni::Object<Point> (jni::jdouble, jni::jdouble)>(env, "fromLngLat"); + return javaClass.Call(env, method, point.x, point.y); +} + mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object<Point> jPoint) { mapbox::geojson::point point; diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp index c6412299bf..627bd1b649 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -3,20 +3,23 @@ #include <mbgl/util/geojson.hpp> #include <mbgl/util/noncopyable.hpp> -#include <jni/jni.hpp> - #include "../java/util.hpp" +#include "geometry.hpp" + +#include <jni/jni.hpp> namespace mbgl { namespace android { namespace geojson { -class Point : private mbgl::util::noncopyable { +class Point : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Point"; }; static constexpr auto Type() { return "Point"; }; + static jni::Object<Point> New(jni::JNIEnv&, const mbgl::Point<double>&); + static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object<Point>); static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object<java::util::List/*<Double>*/>); diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp index 30ba996640..96058b63b3 100644 --- a/platform/android/src/geojson/polygon.cpp +++ b/platform/android/src/geojson/polygon.cpp @@ -8,6 +8,16 @@ namespace mbgl { namespace android { namespace geojson { +jni::Object<Polygon> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) { + auto jList = asPointsListsList(env, polygon); + + static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(env, "fromLngLats"); + auto jPolygon = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jPolygon; +} + mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object<Polygon> jPolygon) { mapbox::geojson::polygon polygon; diff --git a/platform/android/src/geojson/polygon.hpp b/platform/android/src/geojson/polygon.hpp index a8b2b93827..f3c23b4d7b 100644 --- a/platform/android/src/geojson/polygon.hpp +++ b/platform/android/src/geojson/polygon.hpp @@ -3,20 +3,24 @@ #include <mbgl/util/geojson.hpp> #include <mbgl/util/noncopyable.hpp> +#include "geometry.hpp" +#include "../java/util.hpp" + #include <jni/jni.hpp> -#include "../java/util.hpp" namespace mbgl { namespace android { namespace geojson { -class Polygon : private mbgl::util::noncopyable { +class Polygon : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; }; static constexpr auto Type() { return "Polygon"; }; + static jni::Object<Polygon> New(jni::JNIEnv&, const mbgl::Polygon<double>&); + static mapbox::geojson::polygon convert(jni::JNIEnv &, jni::Object<Polygon>); static mapbox::geojson::polygon convert(jni::JNIEnv&, jni::Object<java::util::List/*<java::util::List<Point>>*/>); diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp index ece8e52433..5e6d90a953 100644 --- a/platform/android/src/geojson/util.hpp +++ b/platform/android/src/geojson/util.hpp @@ -1,5 +1,7 @@ #pragma once +#include "point.hpp" + #include <type_traits> namespace mbgl { @@ -17,6 +19,42 @@ To convertExplicit(From&& src) { return *reinterpret_cast<std::add_pointer_t<To>>(&src); } +/** + * Geometry -> List<Point> + */ +template <class T> +static jni::Object<java::util::List> asPointsList(jni::JNIEnv& env, const T& pointsList) { + auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size(), Point::javaClass); + + for (jni::jsize i = 0; i < pointsList.size(); i++) { + auto jPoint = Point::New(env, pointsList.at(i)); + jarray.Set(env, i, jPoint); + jni::DeleteLocalRef(env, jPoint); + } + + auto jList = java::util::Arrays::asList(env, jarray); + jni::DeleteLocalRef(env, jarray); + return jList; +} + +/** + * Geometry -> List<List<Point>> + */ +template <class SHAPE> +static jni::Object<java::util::List> asPointsListsList(JNIEnv& env, SHAPE value) { + auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size(), java::util::List::javaClass); + + for (size_t i = 0; i < value.size(); i = i + 1) { + auto pointsList = asPointsList(env, value[i]); + jarray.Set(env, i, pointsList); + jni::DeleteLocalRef(env, pointsList); + } + + auto jList = java::util::Arrays::asList(env, jarray); + jni::DeleteLocalRef(env, jarray); + return jList; +} + } // namespace geojson } // namespace android } // namespace mbgl diff --git a/platform/android/src/java/util.cpp b/platform/android/src/java/util.cpp index effd2ae0d0..89c4c77794 100644 --- a/platform/android/src/java/util.cpp +++ b/platform/android/src/java/util.cpp @@ -5,12 +5,14 @@ namespace android { namespace java { namespace util { +jni::Class<Arrays> Arrays::javaClass; jni::Class<List> List::javaClass; jni::Class<Set> Set::javaClass; jni::Class<Map> Map::javaClass; jni::Class<Map::Entry> Map::Entry::javaClass; void registerNative(jni::JNIEnv& env) { + Arrays::javaClass = *jni::Class<Arrays>::Find(env).NewGlobalRef(env).release(); List::javaClass = *jni::Class<List>::Find(env).NewGlobalRef(env).release(); Set::javaClass = *jni::Class<Set>::Find(env).NewGlobalRef(env).release(); Map::javaClass = *jni::Class<Map>::Find(env).NewGlobalRef(env).release(); diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp index dedb8ac348..c6b07acac5 100644 --- a/platform/android/src/java/util.hpp +++ b/platform/android/src/java/util.hpp @@ -24,6 +24,21 @@ public: }; +class Arrays : private mbgl::util::noncopyable { +public: + + static constexpr auto Name() { return "java/util/Arrays"; }; + + template <class T> + static jni::Object<List> asList(jni::JNIEnv& env, jni::Array<jni::Object<T>> array) { + static auto asList = Arrays::javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList"); + return javaClass.Call(env, asList, (jni::Array<jni::Object<>>) array); + } + + static jni::Class<Arrays> javaClass; + +}; + class Set : private mbgl::util::noncopyable { public: diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 68db977407..c8c20e939a 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -14,6 +14,7 @@ #include "geojson/feature.hpp" #include "geojson/feature_collection.hpp" #include "geojson/geometry.hpp" +#include "geojson/geometry_collection.hpp" #include "geojson/line_string.hpp" #include "geojson/multi_line_string.hpp" #include "geojson/multi_point.hpp" @@ -116,6 +117,7 @@ void registerNatives(JavaVM *vm) { geojson::Feature::registerNative(env); geojson::FeatureCollection::registerNative(env); geojson::Geometry::registerNative(env); + geojson::GeometryCollection::registerNative(env); geojson::LineString::registerNative(env); geojson::MultiLineString::registerNative(env); geojson::MultiPoint::registerNative(env); |