@@ -16,8 +16,19 @@ import com.google.android.gms.maps.GoogleMap.*
1616import com.google.android.gms.maps.model.*
1717import com.google.maps.android.clustering.Cluster
1818import com.google.maps.android.clustering.ClusterManager
19+ import com.google.maps.android.data.Feature
20+ import com.google.maps.android.data.geojson.GeoJsonFeature
21+ import com.google.maps.android.data.geojson.GeoJsonGeometryCollection
22+ import com.google.maps.android.data.geojson.GeoJsonLayer
23+ import com.google.maps.android.data.geojson.GeoJsonLineString
24+ import com.google.maps.android.data.geojson.GeoJsonMultiLineString
25+ import com.google.maps.android.data.geojson.GeoJsonMultiPoint
26+ import com.google.maps.android.data.geojson.GeoJsonMultiPolygon
27+ import com.google.maps.android.data.geojson.GeoJsonPoint
28+ import com.google.maps.android.data.geojson.GeoJsonPolygon
1929import kotlinx.coroutines.*
2030import kotlinx.coroutines.channels.Channel
31+ import org.json.JSONObject
2132import java.io.InputStream
2233import java.net.URL
2334
@@ -45,7 +56,8 @@ class CapacitorGoogleMap(
4556 private val markers = HashMap <String , CapacitorGoogleMapMarker >()
4657 private val polygons = HashMap <String , CapacitorGoogleMapsPolygon >()
4758 private val circles = HashMap <String , CapacitorGoogleMapsCircle >()
48- private val polylines = HashMap <String , CapacitorGoogleMapPolyline >()
59+ private val polylines = HashMap <String , CapacitorGoogleMapPolyline >()
60+ private val featureLayers = HashMap <String , CapacitorGoogleMapsFeatureLayer >()
4961 private val markerIcons = HashMap <String , Bitmap >()
5062 private var clusterManager: ClusterManager <CapacitorGoogleMapMarker >? = null
5163
@@ -324,6 +336,78 @@ class CapacitorGoogleMap(
324336 }
325337 }
326338
339+ fun addFeatures (type : String , data : JSONObject , idPropertyName : String? , styles : JSONObject ? , callback : (ids: Result <List <String >>) -> Unit ) {
340+ try {
341+ googleMap ? : throw GoogleMapNotAvailable ()
342+ val featureIds: MutableList <String > = mutableListOf ()
343+
344+ CoroutineScope (Dispatchers .Main ).launch {
345+ if (type == " GeoJSON" ) {
346+ val tempLayer = GeoJsonLayer (null , data)
347+ tempLayer.features.forEach {
348+ try {
349+ val layer = GeoJsonLayer (googleMap, JSONObject ())
350+ val featureLayer = CapacitorGoogleMapsFeatureLayer (layer, it, idPropertyName, styles)
351+ layer.addLayerToMap()
352+ if (id != null ) {
353+ featureIds.add(id)
354+ featureLayers[id] = featureLayer
355+ }
356+ callback(Result .success(featureIds))
357+ } catch (e: Exception ) {
358+ callback(Result .failure(e))
359+ }
360+ }
361+ } else {
362+ callback(Result .failure(InvalidArgumentsError (" addFeatures: not supported for this feature type" )))
363+ }
364+ }
365+ } catch (e: GoogleMapsError ) {
366+ callback(Result .failure(e))
367+ }
368+ }
369+
370+ fun getFeatureBounds (featureId : String , callback : (bounds: Result <LatLngBounds ?>) -> Unit ) {
371+ try {
372+ CoroutineScope (Dispatchers .Main ).launch {
373+ val featurelayer = featureLayers[featureId]
374+ var feature: Feature ? = null ;
375+ featurelayer?.layer?.features?.forEach lit@ {
376+ if (it.id == featurelayer.id) {
377+ feature = it
378+ return @lit
379+ }
380+ }
381+ if (feature != null ) {
382+ try {
383+ (feature as GeoJsonFeature ).let {
384+ callback(Result .success(it.boundingBoxFromGeometry()))
385+ }
386+ } catch (e: Exception ) {
387+ callback(Result .failure(InvalidArgumentsError (" getFeatureBounds: not supported for this feature type" )))
388+ }
389+ } else {
390+ callback(Result .failure(InvalidArgumentsError (" Could not find feature for feature id $featureId " )))
391+ }
392+ }
393+ } catch (e: Exception ) {
394+ callback(Result .failure(InvalidArgumentsError (" Could not find feature layer" )))
395+ }
396+ }
397+
398+ fun removeFeature (featureId : String , callback : (error: GoogleMapsError ? ) -> Unit ) {
399+ CoroutineScope (Dispatchers .Main ).launch {
400+ val featurelayer = featureLayers[featureId]
401+ if (featurelayer != null ) {
402+ featurelayer.layer?.removeLayerFromMap()
403+ featureLayers.remove(featureId)
404+ callback(null )
405+ } else {
406+ callback(InvalidArgumentsError (" Could not find feature for feature id $featureId " ))
407+ }
408+ }
409+ }
410+
327411 private fun setClusterManagerRenderer (minClusterSize : Int? ) {
328412 clusterManager?.renderer = CapacitorClusterManagerRenderer (
329413 delegate.bridge.context,
@@ -941,6 +1025,52 @@ class CapacitorGoogleMap(
9411025 return data
9421026 }
9431027
1028+ private fun GeoJsonFeature.boundingBoxFromGeometry (): LatLngBounds ? {
1029+ val coordinates: MutableList <LatLng > = ArrayList ()
1030+
1031+ if (this .hasGeometry()) {
1032+ when (geometry.geometryType) {
1033+ " Point" -> coordinates.add((geometry as GeoJsonPoint ).coordinates)
1034+ " MultiPoint" -> {
1035+ val points = (geometry as GeoJsonMultiPoint ).points
1036+ for (point in points) {
1037+ coordinates.add(point.coordinates)
1038+ }
1039+ }
1040+
1041+ " LineString" -> coordinates.addAll((geometry as GeoJsonLineString ).coordinates)
1042+ " MultiLineString" -> {
1043+ val lines = (geometry as GeoJsonMultiLineString ).lineStrings
1044+ for (line in lines) {
1045+ coordinates.addAll(line.coordinates)
1046+ }
1047+ }
1048+
1049+ " Polygon" -> {
1050+ val lists = (geometry as GeoJsonPolygon ).coordinates
1051+ for (list in lists) {
1052+ coordinates.addAll(list)
1053+ }
1054+ }
1055+
1056+ " MultiPolygon" -> {
1057+ val polygons = (geometry as GeoJsonMultiPolygon ).polygons
1058+ for (polygon in polygons) {
1059+ for (list in polygon.coordinates) {
1060+ coordinates.addAll(list)
1061+ }
1062+ }
1063+ }
1064+ }
1065+ }
1066+
1067+ val builder = LatLngBounds .builder()
1068+ for (latLng in coordinates) {
1069+ builder.include(latLng)
1070+ }
1071+ return builder.build()
1072+ }
1073+
9441074 override fun onMapClick (point : LatLng ) {
9451075 val data = JSObject ()
9461076 data.put(" mapId" , this @CapacitorGoogleMap.id)
0 commit comments