From 2464520da18f0f4cc7532adb3fb7b1f8f195304e Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Tue, 13 Mar 2018 12:31:56 +0200 Subject: [android] high-level jni bindings for geojson conversion --- platform/android/config.cmake | 2 + .../android/src/geojson/conversion/feature.hpp | 2 +- .../android/src/geojson/conversion/geometry.hpp | 184 +-------------------- platform/android/src/geojson/geometry.cpp | 47 +++++- platform/android/src/geojson/geometry.hpp | 8 +- .../android/src/geojson/geometry_collection.cpp | 63 +++++++ .../android/src/geojson/geometry_collection.hpp | 28 ++++ platform/android/src/geojson/line_string.cpp | 13 +- platform/android/src/geojson/line_string.hpp | 10 +- platform/android/src/geojson/multi_line_string.cpp | 11 ++ platform/android/src/geojson/multi_line_string.hpp | 9 +- platform/android/src/geojson/multi_point.cpp | 10 ++ platform/android/src/geojson/multi_point.hpp | 10 +- platform/android/src/geojson/multi_polygon.cpp | 23 +++ platform/android/src/geojson/multi_polygon.hpp | 9 +- platform/android/src/geojson/point.cpp | 5 + platform/android/src/geojson/point.hpp | 9 +- platform/android/src/geojson/polygon.cpp | 10 ++ platform/android/src/geojson/polygon.hpp | 8 +- platform/android/src/geojson/util.hpp | 38 +++++ platform/android/src/java/util.cpp | 2 + platform/android/src/java/util.hpp | 15 ++ platform/android/src/jni.cpp | 2 + 23 files changed, 320 insertions(+), 198 deletions(-) create mode 100644 platform/android/src/geojson/geometry_collection.cpp create mode 100644 platform/android/src/geojson/geometry_collection.hpp 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, mbgl::Feature> { auto properties = jni::Object(*convert(env, value.properties)); // Convert geometry - auto geometry = jni::Object(*convert(env, value.geometry)); + auto geometry = *convert>(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 +#include "../geometry.hpp" #include -#include "../../jni/local_object.hpp" namespace mbgl { namespace android { namespace conversion { /** - * Turn mapbox::geometry type into Java GeoJson Geometries - */ -template -class GeometryEvaluator { -public: - - jni::JNIEnv& env; - - /** - * static Point fromLngLat(double longitude,double latitude) - */ - jni::jobject* operator()(const mapbox::geometry::point &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::CallStaticMethod(env, *javaClass, *fromLngLat, geometry.x, geometry.y)); - } - - /** - * static LineString fromLngLats(double [][]) - */ - jni::jobject* operator()(const mapbox::geometry::line_string &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> lngLatsArray = - jni::NewLocalObject(env, toLngLatArray(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, lngLatsArray.get())); - } - - /** - * static MultiPoint fromLngLats(double [][]) - */ - jni::jobject* operator()(const mapbox::geometry::multi_point &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> lngLatsArray = - jni::NewLocalObject(env, toLngLatArray(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, lngLatsArray.get())); - } - - /** - * static Polygon fromLngLats(double [][][]) - */ - jni::jobject* operator()(const mapbox::geometry::polygon &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> shape = - jni::NewLocalObject(env, shapeToLngLatArray<>(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, shape.get())); - } - - /** - * static MultiLineString fromLngLats(double [][][]) - */ - jni::jobject* operator()(const mapbox::geometry::multi_line_string &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> shape = - jni::NewLocalObject(env,shapeToLngLatArray<>(env, geometry)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, shape.get())); - } - - /** - * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D - */ - jni::jobject* operator()(const mapbox::geometry::multi_polygon &geometry) const { - - static jni::jclass* arrayClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[[D")).release(); - jni::LocalObject> jarray = - jni::NewLocalObject(env, &jni::NewObjectArray(env, geometry.size(), *arrayClass)); - - for(size_t i = 0; i < geometry.size(); i = i + 1) { - jni::LocalObject> 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::CallStaticMethod(env, *javaClass, *fromGeometries, jarray.get())); - } - - /** - * GeometryCollection - */ - jni::jobject* operator()(const mapbox::geometry::geometry_collection &collection) const { - static jni::jclass* geometryClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Geometry")).release(); - jni::LocalObject> 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 converted = jni::NewLocalObject(env, mapbox::geometry::geometry::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 list = jni::NewLocalObject(env, toArrayList<>(env, *jarray)); - return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometries, list.get())); - } - -private: - - /** - * x, y -> jarray ([x,y]) - * - */ - static jni::jarray *toLngLatArray(JNIEnv &env, double x, double y) { - jni::jarray &jarray = jni::NewArray(env, 2); - jni::jdouble array[] = {x, y}; - jni::SetArrayRegion(env, jarray, 0, 2, array); - return &jarray; - } - - /** - * vector> -> jarray -> [D + Object array == [[D (double[][]) - */ - static jni::jarray* toLngLatArray(JNIEnv &env, - std::vector> points) { - - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[D")).release(); - jni::jarray& jarray = jni::NewObjectArray(env, points.size(), *javaClass); - - for(size_t i = 0; i < points.size(); i = i + 1) { - mapbox::geometry::point point = points.at(i); - jni::jarray *lngLatArray = toLngLatArray(env, point.x, point.y); - jni::SetObjectArrayElement(env, jarray, i, lngLatArray); - } - - return &jarray; - } - - /** - * polygon - * multi_line_string -> jarray -> [[D + Object array == [[[D (double[][][]) - */ - template - static jni::jarray* shapeToLngLatArray(JNIEnv &env, SHAPE value) { - static jni::jclass *javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[D")).release(); - jni::jarray &jarray = jni::NewObjectArray(env, value.size(), *javaClass); - - for (size_t i = 0; i < value.size(); i = i + 1) { - jni::LocalObject> lngLatsArray = - jni::NewLocalObject(env, toLngLatArray(env, value.at(i))); - jni::SetObjectArrayElement(env, jarray, i, lngLatsArray.get()); - } - - return &jarray; - } -}; - -/** - * mapbox::geometry::geometry -> Java GeoJson Geometry<> + * mapbox::geometry::geometry -> Java GeoJson Geometry */ template -struct Converter> { - Result operator()(jni::JNIEnv& env, const mapbox::geometry::geometry& value) const { - GeometryEvaluator evaluator { env } ; - jni::jobject* converted = mapbox::geometry::geometry::visit(value, evaluator); - return {converted}; +struct Converter, mapbox::geometry::geometry> { + Result> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry& 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 @@ -13,7 +14,49 @@ namespace mbgl { namespace android { namespace geojson { -mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object jGeometry) { +/** + * Turn mapbox::geometry type into Java GeoJson Geometries + */ +class GeometryEvaluator { +public: + + jni::JNIEnv& env; + + jni::Object operator()(const mbgl::Point &geometry) const { + return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass); + } + + jni::Object operator()(const mbgl::LineString &geometry) const { + return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass); + } + + jni::Object operator()(const mbgl::MultiLineString &geometry) const { + return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass); + } + + jni::Object operator()(const mbgl::MultiPoint &geometry) const { + return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass); + } + + jni::Object operator()(const mbgl::Polygon &geometry) const { + return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass); + } + + jni::Object operator()(const mbgl::MultiPolygon &geometry) const { + return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass); + } + + jni::Object operator()(const mapbox::geometry::geometry_collection &geometry) const { + return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass); + } +}; + +jni::Object Geometry::New(jni::JNIEnv& env, mbgl::Geometry geometry) { + GeometryEvaluator evaluator { env } ; + return mbgl::Geometry::visit(geometry, evaluator); +} + +mbgl::Geometry Geometry::convert(jni::JNIEnv &env, jni::Object jGeometry) { auto type = Geometry::getType(env, jGeometry); if (type == Point::Type()) { return { Point::convert(env, jni::Object(jGeometry.Get())) }; @@ -27,6 +70,8 @@ mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object(jGeometry.Get())) }; } else if (type == MultiPolygon::Type()) { return { MultiPolygon::convert(env, jni::Object(jGeometry.Get())) }; + } else if (type == GeometryCollection::Type()) { + return { GeometryCollection::convert(env, jni::Object(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 +#include #include +#include "../java/util.hpp" + #include 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); + static jni::Object New(jni::JNIEnv&, mbgl::Geometry); + + static mbgl::Geometry convert(jni::JNIEnv&, jni::Object); static std::string getType(jni::JNIEnv&, jni::Object); 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::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection& collection) { + // Create an array of geometries + auto jarray = jni::Array>::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)>(env, "fromGeometries"); + auto jCollection = javaClass.Call(env, method, jList); + + jni::DeleteLocalRef(env, jList); + return jCollection; +} + +mapbox::geometry::geometry_collection GeometryCollection::convert(jni::JNIEnv &env, jni::Object jCollection) { + // Get geometries + static auto getGeometries = javaClass.GetMethod ()>(env, "getGeometries"); + auto jList = jCollection.Call(env, getGeometries); + + // Turn into array + auto jarray = java::util::List::toArray(env, jList); + jni::DeleteLocalRef(env, jList); + + // Convert each geometry + mapbox::geometry::geometry_collection 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::Find(env).NewGlobalRef(env).release(); +} + +jni::Class 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 + +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 New(jni::JNIEnv&, const mapbox::geometry::geometry_collection&); + + static mapbox::geometry::geometry_collection convert(jni::JNIEnv&, jni::Object); + + static jni::Class 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::New(jni::JNIEnv& env, const mbgl::LineString& lineString) { + auto jList = asPointsList(env, lineString); + + static auto method = javaClass.GetStaticMethod(jni::Object)>(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 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 +#include #include -#include - +#include "geometry.hpp" #include "../java/util.hpp" +#include + 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 New(jni::JNIEnv&, const mbgl::LineString&); + static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object); static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object*/>); 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::New(jni::JNIEnv& env, const mbgl::MultiLineString& multiLineString) { + auto jList = asPointsListsList(env, multiLineString); + + static auto method = javaClass.GetStaticMethod (jni::Object)>(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 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 #include -#include - #include "../java/util.hpp" +#include "geometry.hpp" + +#include 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 New(jni::JNIEnv&, const mbgl::MultiLineString&); + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object); static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object>*/>); 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::New(JNIEnv& env, const mbgl::MultiPoint& multiPoint) { + auto jList = asPointsList(env, multiPoint); + + static auto method = javaClass.GetStaticMethod(jni::Object)>(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 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 +#include #include -#include - +#include "geometry.hpp" #include "../java/util.hpp" +#include + 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 New(jni::JNIEnv&, const mbgl::MultiPoint&); + static mapbox::geojson::multi_point convert(jni::JNIEnv&, jni::Object); static jni::Object coordinates(jni::JNIEnv&, jni::Object); 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::New(JNIEnv& env, const mbgl::MultiPolygon& multiPolygon) { + auto jarray = jni::Array>::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)>(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 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 #include -#include - #include "../java/util.hpp" +#include "geometry.hpp" + +#include 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 New(jni::JNIEnv&, const mbgl::MultiPolygon&); + static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, jni::Object); static jni::Object coordinates(jni::JNIEnv&, jni::Object); 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::New(jni::JNIEnv& env, const mbgl::Point& point) { + static auto method = javaClass.GetStaticMethod (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 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 #include -#include - #include "../java/util.hpp" +#include "geometry.hpp" + +#include 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 New(jni::JNIEnv&, const mbgl::Point&); + static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object); static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object*/>); 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::New(jni::JNIEnv& env, const mbgl::Polygon& polygon) { + auto jList = asPointsListsList(env, polygon); + + static auto method = javaClass.GetStaticMethod (jni::Object)>(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 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 #include +#include "geometry.hpp" +#include "../java/util.hpp" + #include -#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 New(jni::JNIEnv&, const mbgl::Polygon&); + static mapbox::geojson::polygon convert(jni::JNIEnv &, jni::Object); static mapbox::geojson::polygon convert(jni::JNIEnv&, jni::Object>*/>); 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 namespace mbgl { @@ -17,6 +19,42 @@ To convertExplicit(From&& src) { return *reinterpret_cast>(&src); } +/** + * Geometry -> List + */ +template +static jni::Object asPointsList(jni::JNIEnv& env, const T& pointsList) { + auto jarray = jni::Array>::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> + */ +template +static jni::Object asPointsListsList(JNIEnv& env, SHAPE value) { + auto jarray = jni::Array>::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::javaClass; jni::Class List::javaClass; jni::Class Set::javaClass; jni::Class Map::javaClass; jni::Class Map::Entry::javaClass; void registerNative(jni::JNIEnv& env) { + Arrays::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); List::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); Set::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); Map::javaClass = *jni::Class::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 + static jni::Object asList(jni::JNIEnv& env, jni::Array> array) { + static auto asList = Arrays::javaClass.GetStaticMethod(jni::Array>)>(env, "asList"); + return javaClass.Call(env, asList, (jni::Array>) array); + } + + static jni::Class 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); -- cgit v1.2.1