#pragma once #include "../../conversion/constant.hpp" #include "../../conversion/collection.hpp" #include #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(List points) */ 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", "(Ljava/util/List;)Lcom/mapbox/geojson/LineString;"); // Create jni::LocalObject listOfPoints = jni::NewLocalObject(env, toGeoJsonListOfPoints(env, geometry)); return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, listOfPoints.get())); } /** * static MultiPoint fromLngLats(List points) */ 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", "(Ljava/util/List;)Lcom/mapbox/geojson/MultiPoint;"); // Create jni::LocalObject coordinates = jni::NewLocalObject(env, toGeoJsonListOfPoints(env, geometry)); return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, coordinates.get())); } /** * static Polygon fromLngLats(List> coordinates) */ 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", "(Ljava/util/List;)Lcom/mapbox/geojson/Polygon;"); // Create jni::LocalObject shape = jni::NewLocalObject(env, toShape<>(env, geometry)); return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, shape.get())); } /** * static MultiLineString fromLngLats(List> points) */ 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", "(Ljava/util/List;)Lcom/mapbox/geojson/MultiLineString;"); // Create jni::LocalObject shape = jni::NewLocalObject(env, toShape<>(env, geometry)); return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromLngLats, shape.get())); } /** * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D * * static MultiPolygon fromLngLats(List>> points) */ jni::jobject* operator()(const mapbox::geometry::multi_polygon &geometry) const { // ArrayList static jni::jclass* arrayListClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/ArrayList")).release(); static jni::jmethodID* constructor = &jni::GetMethodID(env, *arrayListClass, "", "(I)V"); static jni::jmethodID* add = &jni::GetMethodID(env, *arrayListClass, "add", "(ILjava/lang/Object;)V"); jni::jobject* arrayList = &jni::NewObject(env, *arrayListClass, *constructor, geometry.size()); for(size_t i = 0; i < geometry.size(); i = i + 1) { jni::LocalObject shape = jni::NewLocalObject(env, toShape<>(env, geometry.at(i))); jni::CallMethod(env, arrayList, *add, 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", "(Ljava/util/List;)Lcom/mapbox/geojson/MultiPolygon;"); return reinterpret_cast(jni::CallStaticMethod(env, *javaClass, *fromGeometries, arrayList)); } /** * 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: /** * vector> -> List */ static jni::jobject* toGeoJsonListOfPoints(JNIEnv& env, std::vector> points) { // ArrayList static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/ArrayList")).release(); static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(I)V"); static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(ILjava/lang/Object;)V"); jni::jobject* arrayList = &jni::NewObject(env, *javaClass, *constructor, points.size()); // Point static jni::jclass* pointJavaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Point")).release(); static jni::jmethodID* fromLngLat = &jni::GetStaticMethodID(env, *pointJavaClass, "fromLngLat", "(DD)Lcom/mapbox/geojson/Point;"); for(size_t i = 0; i < points.size(); i = i + 1) { mapbox::geometry::point point = points.at(i); jni::LocalObject pointObject = jni::NewLocalObject(env, jni::CallStaticMethod(env, *pointJavaClass, *fromLngLat, point.x, point.y)); jni::CallMethod(env, arrayList, *add, i, pointObject.get()); } return arrayList; } /** * geometry -> List> */ template static jni::jobject* toShape(JNIEnv& env, SHAPE value) { // ArrayList static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/ArrayList")).release(); static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "", "(I)V"); static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(ILjava/lang/Object;)V"); jni::jobject* arrayList = &jni::NewObject(env, *javaClass, *constructor, value.size()); for(size_t i = 0; i < value.size(); i = i + 1) { jni::LocalObject listOfPoints = jni::NewLocalObject(env, toGeoJsonListOfPoints(env, value.at(i))); jni::CallMethod(env, arrayList, *add, i, listOfPoints.get()); } return arrayList; } }; /** * 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}; } }; } } }