@@ -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 tileOverlays = HashMap <String , CapacitorGoogleMapTileOverlay >()
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
@@ -415,6 +427,78 @@ class CapacitorGoogleMap(
415427 }
416428 }
417429
430+ fun addFeatures (type : String , data : JSONObject , idPropertyName : String? , styles : JSONObject ? , callback : (ids: Result <List <String >>) -> Unit ) {
431+ try {
432+ googleMap ? : throw GoogleMapNotAvailable ()
433+ val featureIds: MutableList <String > = mutableListOf ()
434+
435+ CoroutineScope (Dispatchers .Main ).launch {
436+ if (type == " GeoJSON" ) {
437+ val tempLayer = GeoJsonLayer (null , data)
438+ tempLayer.features.forEach {
439+ try {
440+ val layer = GeoJsonLayer (googleMap, JSONObject ())
441+ val featureLayer = CapacitorGoogleMapsFeatureLayer (layer, it, idPropertyName, styles)
442+ layer.addLayerToMap()
443+ if (id != null ) {
444+ featureIds.add(id)
445+ featureLayers[id] = featureLayer
446+ }
447+ callback(Result .success(featureIds))
448+ } catch (e: Exception ) {
449+ callback(Result .failure(e))
450+ }
451+ }
452+ } else {
453+ callback(Result .failure(InvalidArgumentsError (" addFeatures: not supported for this feature type" )))
454+ }
455+ }
456+ } catch (e: GoogleMapsError ) {
457+ callback(Result .failure(e))
458+ }
459+ }
460+
461+ fun getFeatureBounds (featureId : String , callback : (bounds: Result <LatLngBounds ?>) -> Unit ) {
462+ try {
463+ CoroutineScope (Dispatchers .Main ).launch {
464+ val featurelayer = featureLayers[featureId]
465+ var feature: Feature ? = null ;
466+ featurelayer?.layer?.features?.forEach lit@ {
467+ if (it.id == featurelayer.id) {
468+ feature = it
469+ return @lit
470+ }
471+ }
472+ if (feature != null ) {
473+ try {
474+ (feature as GeoJsonFeature ).let {
475+ callback(Result .success(it.boundingBoxFromGeometry()))
476+ }
477+ } catch (e: Exception ) {
478+ callback(Result .failure(InvalidArgumentsError (" getFeatureBounds: not supported for this feature type" )))
479+ }
480+ } else {
481+ callback(Result .failure(InvalidArgumentsError (" Could not find feature for feature id $featureId " )))
482+ }
483+ }
484+ } catch (e: Exception ) {
485+ callback(Result .failure(InvalidArgumentsError (" Could not find feature layer" )))
486+ }
487+ }
488+
489+ fun removeFeature (featureId : String , callback : (error: GoogleMapsError ? ) -> Unit ) {
490+ CoroutineScope (Dispatchers .Main ).launch {
491+ val featurelayer = featureLayers[featureId]
492+ if (featurelayer != null ) {
493+ featurelayer.layer?.removeLayerFromMap()
494+ featureLayers.remove(featureId)
495+ callback(null )
496+ } else {
497+ callback(InvalidArgumentsError (" Could not find feature for feature id $featureId " ))
498+ }
499+ }
500+ }
501+
418502 private fun setClusterManagerRenderer (minClusterSize : Int? ) {
419503 clusterManager?.renderer = CapacitorClusterManagerRenderer (
420504 delegate.bridge.context,
@@ -1032,6 +1116,52 @@ class CapacitorGoogleMap(
10321116 return data
10331117 }
10341118
1119+ private fun GeoJsonFeature.boundingBoxFromGeometry (): LatLngBounds ? {
1120+ val coordinates: MutableList <LatLng > = ArrayList ()
1121+
1122+ if (this .hasGeometry()) {
1123+ when (geometry.geometryType) {
1124+ " Point" -> coordinates.add((geometry as GeoJsonPoint ).coordinates)
1125+ " MultiPoint" -> {
1126+ val points = (geometry as GeoJsonMultiPoint ).points
1127+ for (point in points) {
1128+ coordinates.add(point.coordinates)
1129+ }
1130+ }
1131+
1132+ " LineString" -> coordinates.addAll((geometry as GeoJsonLineString ).coordinates)
1133+ " MultiLineString" -> {
1134+ val lines = (geometry as GeoJsonMultiLineString ).lineStrings
1135+ for (line in lines) {
1136+ coordinates.addAll(line.coordinates)
1137+ }
1138+ }
1139+
1140+ " Polygon" -> {
1141+ val lists = (geometry as GeoJsonPolygon ).coordinates
1142+ for (list in lists) {
1143+ coordinates.addAll(list)
1144+ }
1145+ }
1146+
1147+ " MultiPolygon" -> {
1148+ val polygons = (geometry as GeoJsonMultiPolygon ).polygons
1149+ for (polygon in polygons) {
1150+ for (list in polygon.coordinates) {
1151+ coordinates.addAll(list)
1152+ }
1153+ }
1154+ }
1155+ }
1156+ }
1157+
1158+ val builder = LatLngBounds .builder()
1159+ for (latLng in coordinates) {
1160+ builder.include(latLng)
1161+ }
1162+ return builder.build()
1163+ }
1164+
10351165 override fun onMapClick (point : LatLng ) {
10361166 val data = JSObject ()
10371167 data.put(" mapId" , this @CapacitorGoogleMap.id)
0 commit comments