From 5a48b534b2e26be666a9d0a7c768fbc0d791e23b Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 4 Sep 2024 15:33:19 +0500 Subject: [PATCH 01/17] added geojson md file --- docs/mdbook/src/SUMMARY.md | 1 + docs/mdbook/src/android/geojson-guide.md | 0 2 files changed, 1 insertion(+) create mode 100644 docs/mdbook/src/android/geojson-guide.md diff --git a/docs/mdbook/src/SUMMARY.md b/docs/mdbook/src/SUMMARY.md index dd8a871a845..f4597633e68 100644 --- a/docs/mdbook/src/SUMMARY.md +++ b/docs/mdbook/src/SUMMARY.md @@ -15,6 +15,7 @@ - [Annotation: Marker](./android/annotation-guide.md) - [Location Component](./android/location-component-guide.md) - [MapOptions Guide](./android/map-options-guide.md) + - [GeoJson Guide](./android/geojson-guide.md) - [Profiling applications that use MapLibre Native](./profiling/README.md) - [Tracy profiling](./profiling/tracy-profiling.md) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md new file mode 100644 index 00000000000..e69de29bb2d From 8c51236697b5759846503fdc0dfebc80e743e410 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Sun, 27 Oct 2024 17:29:57 +0500 Subject: [PATCH 02/17] filled geojson documentation --- docs/mdbook/src/android/geojson-guide.md | 373 +++++++++++++++++++++++ 1 file changed, 373 insertions(+) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index e69de29bb2d..7eac4ddeffd 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -0,0 +1,373 @@ +# Introduction + +This guide will teach you how to use [`GeoJsonDataSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJson`]("https://geojson.org/") file format. + +You will start with fundamentals of how map renders data under the hood and why [`JSON`]("https://en.wikipedia.org/wiki/JSON") format is preferred in storing geospatial data + +# Goals +After finishing this documentation you should be able to + +1. understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`DataSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other +2. describe `JSON` files +3. explore building blocks of `GeoJson` data +4. use `GeoJson` files in constructing [`GeoJsonDataSources`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") +5. update data at runtime + +### 1. Styles, Layers, and DataSources +- `Style ` defines the visual representation of the map such as colors and appearance. + +- `Layer` controls how data should be presented to the user + +- `Datasource` holds actual data and provides layers with it + +Styles consist of collections of layers and datasources. Layers reference datasources. Hence they require unique source ID when they are constructed + +It would be meaningless if we don't have any data to show so we need know supplying data with datasources. + +Firstly, we need to understand how to store data and passing them into datasources and therefore `JSON` comes into play in the next session. + +### 2. JSON +`JSON` stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. + +It is popular because it is human readable and easy to parse into objects. + +JSON content is treated as string and it makes easy to transmit data across clients. JSON file is saved in .json extension + +A sample json file: +```json +{ + "name": "John Doe", + "age": 30, + "isStudent": false, + "contact": { + "email": "johndoe@example.com", + "phone": "123-456-7890" + }, + "hobbies": ["reading", "traveling", "coding"] +} + +``` +With its straightforward syntax, we can benefit from it by describing our geospatial data inside json + +### 3. GeoJson +[`GeoJson`]("https://geojson.org/") is a json file for encoding various geographical data structures. + +It defines several json objects to represent geospatial information. GeoJson file is saved with `.geojson` extension + +The following list illustrates the most fundamental objects: + +- Geometry +- Feature +- FeatureCollection + +`Geometry` is a single geometric shape that contains one or more coordinates. + +A geometry can be one of the following six types: + +- Point +- MultiPoint +- LineString +- MultilineString +- Polygon +- MultiPolygon + +They are visual objects that seen on map with one or more coordinates. We can use each depending on our requirements + +`Feautue` is a compound object of single geometry and user-defined attributes applied to that geometry such as name, color, etc. + +`FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. + +A typical GeoJson file might look like: +```json + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -77.06867337226866, + 38.90467655551809 + ], + [ + -77.06233263015747, + 38.90479344272695 + ], + [ + -77.06234335899353, + 38.906463238984344 + ], + [ + -77.06290125846863, + 38.907206285691615 + ], + [ + -77.06364154815674, + 38.90684728656818 + ], + [ + -77.06326603889465, + 38.90637140121084 + ], + [ + -77.06321239471436, + 38.905561553883246 + ], + [ + -77.0691454410553, + 38.905436318935635 + ], + [ + -77.06912398338318, + 38.90466820642439 + ], + [ + -77.06867337226866, + 38.90467655551809 + ] + ] + ] + } + } + ] +} +``` +So far we learned describing Geospatial data in geojson files. We will start applying this knowledge into our map applications + +### 4. GeoJsonDataSource +As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJson`. +We will not deal with other sources and only focus on `GeoJsonDataSource`. + +`GeoJsonDataSource` is a type of source that has a unique `String` ID and GeoJson data. There are several ways of creating and adding `GeoJsonDataSource` objects. + +A GeoJsonDataSource might be constructed with several approaches: + +- Locally stored files such as assets and raw folders +- Remote services +- Raw string parsed into FeatureCollections objects +- Geometry, Feature, and FeatureCollection objects that map to GeoJson Base builders + +A sample GeoJsonDatasource: +```kotlin +val source = GeoJsonSource("source", featureCollection) +val lineLayer = LineLayer("layer", "source") + .withProperties( + PropertyFactory.lineColor(Color.RED), + PropertyFactory.lineWidth(10f) + ) + +style.addSource(source) +style.addLayer(lineLayer) +``` + +Note that dataSources can not be simply shown. Layers must reference them. Therefore, you create a layer that gives visual appearance to it. + +- Loading from local files + +with assets folder file +```kotlin + binding.mapView.getMapAsync { map -> + map.moveCamera(CameraUpdateFactory.newLatLngZoom(cameraTarget, cameraZoom)) + map.setStyle( + Style.Builder() + .withImage(imageId, imageIcon) + .withSource(GeoJsonSource(sourceId, URI("asset://points-sf.geojson"))) + .withLayer(SymbolLayer(layerId, sourceId).withProperties(iconImage(imageId))) + ) + } +``` +with raw folder file +```kotlin + val source: Source = try { + GeoJsonSource("amsterdam-spots", ResourceUtils.readRawResource(this, R.raw.amsterdam)) + } catch (ioException: IOException) { + Toast.makeText( + this@RuntimeStyleActivity, + "Couldn't add source: " + ioException.message, + Toast.LENGTH_SHORT + ).show() + return + } + maplibreMap.style!!.addSource(source) + var layer: FillLayer? = FillLayer("parksLayer", "amsterdam-spots") + layer!!.setProperties( + PropertyFactory.fillColor(Color.RED), + PropertyFactory.fillOutlineColor(Color.BLUE), + PropertyFactory.fillOpacity(0.3f), + PropertyFactory.fillAntialias(true) + ) +``` +parsing method: +```kotlin + fun readRawResource(context: Context?, @RawRes rawResource: Int): String { + var json = "" + if (context != null) { + val writer: Writer = StringWriter() + val buffer = CharArray(1024) + context.resources.openRawResource(rawResource).use { `is` -> + val reader: Reader = BufferedReader(InputStreamReader(`is`, "UTF-8")) + var numRead: Int + while (reader.read(buffer).also { numRead = it } != -1) { + writer.write(buffer, 0, numRead) + } + } + json = writer.toString() + } + return json + } +``` +- Loading from remote services +```kotlin + private fun createEarthquakeSource(): GeoJsonSource { + return GeoJsonSource(EARTHQUAKE_SOURCE_ID, URI(EARTHQUAKE_SOURCE_URL)) + } +``` +```kotlin + companion object { + private const val EARTHQUAKE_SOURCE_URL = + "https://maplibre.org/maplibre-gl-js-docs/assets/earthquakes.geojson" + private const val EARTHQUAKE_SOURCE_ID = "earthquakes" + private const val HEATMAP_LAYER_ID = "earthquakes-heat" + private const val HEATMAP_LAYER_SOURCE = "earthquakes" + private const val CIRCLE_LAYER_ID = "earthquakes-circle" + } +``` +- Parsing string with `fromJson` method of FeatureCollection +```kotlin + private fun bufferLineStringGeometry(): Polygon { + // TODO replace static data by Turf#Buffer: mapbox-java/issues/987 + return FeatureCollection.fromJson( + """ + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -77.06867337226866, + 38.90467655551809 + ], + [ + -77.06233263015747, + 38.90479344272695 + ], + [ + -77.06234335899353, + 38.906463238984344 + ], + [ + -77.06290125846863, + 38.907206285691615 + ], + [ + -77.06364154815674, + 38.90684728656818 + ], + [ + -77.06326603889465, + 38.90637140121084 + ], + [ + -77.06321239471436, + 38.905561553883246 + ], + [ + -77.0691454410553, + 38.905436318935635 + ], + [ + -77.06912398338318, + 38.90466820642439 + ], + [ + -77.06867337226866, + 38.90467655551809 + ] + ] + ] + } + } + ] + } + """.trimIndent() + ).features()!![0].geometry() as Polygon + } +``` +- Creating Geometry, Feature, and FeatureCollections from scratch + +Note that GeoJson objects as we discussed above have classes defined in MapLibre SDK. +So we can map json objects into regular Java/Kotlin objects or build straightaway. +```kotlin + val properties = JsonObject() + properties.addProperty("key1", "value1") + val source = GeoJsonSource( + "test-source", + FeatureCollection.fromFeatures( + arrayOf( + Feature.fromGeometry(Point.fromLngLat(17.1, 51.0), properties), + Feature.fromGeometry(Point.fromLngLat(17.2, 51.0), properties), + Feature.fromGeometry(Point.fromLngLat(17.3, 51.0), properties), + Feature.fromGeometry(Point.fromLngLat(17.4, 51.0), properties) + ) + ) + ) + style.addSource(source) + val visible = Expression.eq(Expression.get("key1"), Expression.literal("value1")) + val invisible = Expression.neq(Expression.get("key1"), Expression.literal("value1")) + val layer = CircleLayer("test-layer", source.id) + .withFilter(visible) + style.addLayer(layer) +``` + +### 5. Updating data at runtime +The most important feature of GeoJsonDataSources, once we add one of them, we can set another set of data. +We achieve this with `setGeoJson()` method. + +For example we create a source variable and check if it is not assigned, then we create new source object and add it to style, otherwise we set another data: +```kotlin + private fun createFeatureCollection(): FeatureCollection { + val point = if (isInitialPosition) { + Point.fromLngLat(-74.01618140, 40.701745) + } else { + Point.fromLngLat(-73.988097, 40.749864) + } + val properties = JsonObject() + properties.addProperty(KEY_PROPERTY_SELECTED, isSelected) + val feature = Feature.fromGeometry(point, properties) + return FeatureCollection.fromFeatures(arrayOf(feature)) + } +``` + +```kotlin + private fun updateSource(style: Style?) { + val featureCollection = createFeatureCollection() + if (source != null) { + source!!.setGeoJson(featureCollection) + } else { + source = GeoJsonSource(SOURCE_ID, featureCollection) + style!!.addSource(source!!) + } + } +``` + +Probably the most advanced use case might be animating random objects such as cars. + +```kotlin +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt}} +``` + +# Summary +GeoJsonDataSources come with their pros and cons. They work best if you want to add additional data to your style , or provide features like animating objects on your map. + +It would be difficult if you have large datasets and you want to manipulate and store inside app. In that case you should prefer remote datasources. + +Lastly, you may check [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for full guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") in order learn best practises to adopt in your apps. \ No newline at end of file From 695f230d9cb6cae969fda86abcebbcaf1507bb9a Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Tue, 29 Oct 2024 10:13:29 +0500 Subject: [PATCH 03/17] corrected capitalizations --- docs/mdbook/src/SUMMARY.md | 2 +- docs/mdbook/src/android/geojson-guide.md | 64 ++++++++++++------------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/mdbook/src/SUMMARY.md b/docs/mdbook/src/SUMMARY.md index f4597633e68..2ec9f64ffe5 100644 --- a/docs/mdbook/src/SUMMARY.md +++ b/docs/mdbook/src/SUMMARY.md @@ -15,7 +15,7 @@ - [Annotation: Marker](./android/annotation-guide.md) - [Location Component](./android/location-component-guide.md) - [MapOptions Guide](./android/map-options-guide.md) - - [GeoJson Guide](./android/geojson-guide.md) + - [GeoJSON Guide](./android/geojson-guide.md) - [Profiling applications that use MapLibre Native](./profiling/README.md) - [Tracy profiling](./profiling/tracy-profiling.md) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 7eac4ddeffd..a984b464dbc 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -1,39 +1,39 @@ # Introduction -This guide will teach you how to use [`GeoJsonDataSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJson`]("https://geojson.org/") file format. +This guide will teach you how to use [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJSON`]("https://geojson.org/") file format. -You will start with fundamentals of how map renders data under the hood and why [`JSON`]("https://en.wikipedia.org/wiki/JSON") format is preferred in storing geospatial data +You will start with fundamentals of how map renders data under the hood and why [JSON]("https://en.wikipedia.org/wiki/JSON") format is preferred in storing geospatial data # Goals After finishing this documentation you should be able to -1. understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`DataSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other -2. describe `JSON` files -3. explore building blocks of `GeoJson` data -4. use `GeoJson` files in constructing [`GeoJsonDataSources`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") +1. understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other +2. describe JSON files +3. explore building blocks of `GeoJSON` data +4. use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s 5. update data at runtime -### 1. Styles, Layers, and DataSources +### 1. Styles, Layers, and Data source - `Style ` defines the visual representation of the map such as colors and appearance. - `Layer` controls how data should be presented to the user -- `Datasource` holds actual data and provides layers with it +- `Data source` holds actual data and provides layers with it -Styles consist of collections of layers and datasources. Layers reference datasources. Hence they require unique source ID when they are constructed +Styles consist of collections of layers and data source. Layers reference data source. Hence they require a unique source ID when they are constructed -It would be meaningless if we don't have any data to show so we need know supplying data with datasources. +It would be meaningless if we don't have any data to show so we need know supplying data with data source. -Firstly, we need to understand how to store data and passing them into datasources and therefore `JSON` comes into play in the next session. +Firstly, we need to understand how to store data and passing them into data source and therefore JSON comes into play in the next session. ### 2. JSON -`JSON` stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. +JSON stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. It is popular because it is human readable and easy to parse into objects. JSON content is treated as string and it makes easy to transmit data across clients. JSON file is saved in .json extension -A sample json file: +A sample JSON file: ```json { "name": "John Doe", @@ -47,12 +47,12 @@ A sample json file: } ``` -With its straightforward syntax, we can benefit from it by describing our geospatial data inside json +With its straightforward syntax, we can benefit from it by describing our geospatial data inside JSON -### 3. GeoJson -[`GeoJson`]("https://geojson.org/") is a json file for encoding various geographical data structures. +### 3. GeoJSON +[`GeoJSON`]("https://geojson.org/") is a JSON file for encoding various geographical data structures. -It defines several json objects to represent geospatial information. GeoJson file is saved with `.geojson` extension +It defines several JSON objects to represent geospatial information. GeoJSON file is saved with `.geojson` extension The following list illustrates the most fundamental objects: @@ -77,7 +77,7 @@ They are visual objects that seen on map with one or more coordinates. We can us `FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. -A typical GeoJson file might look like: +A typical GeoJSON file might look like: ```json { "type": "FeatureCollection", @@ -136,22 +136,22 @@ A typical GeoJson file might look like: ] } ``` -So far we learned describing Geospatial data in geojson files. We will start applying this knowledge into our map applications +So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications -### 4. GeoJsonDataSource -As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJson`. -We will not deal with other sources and only focus on `GeoJsonDataSource`. +### 4. GeoJsonSource +As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJSON`. +We will not deal with other sources and only focus on `GeoJsonSource`. -`GeoJsonDataSource` is a type of source that has a unique `String` ID and GeoJson data. There are several ways of creating and adding `GeoJsonDataSource` objects. +`GeoJsonSource` is a type of source that has a unique `String` ID and GeoJSON data. There are several ways of creating and adding `GeoJsonSource` objects. -A GeoJsonDataSource might be constructed with several approaches: +A GeoJsonSource might be constructed with several approaches: - Locally stored files such as assets and raw folders - Remote services - Raw string parsed into FeatureCollections objects -- Geometry, Feature, and FeatureCollection objects that map to GeoJson Base builders +- Geometry, Feature, and FeatureCollection objects that map to GeoJSON Base builders -A sample GeoJsonDatasource: +A sample GeoJsonSource: ```kotlin val source = GeoJsonSource("source", featureCollection) val lineLayer = LineLayer("layer", "source") @@ -164,7 +164,7 @@ style.addSource(source) style.addLayer(lineLayer) ``` -Note that dataSources can not be simply shown. Layers must reference them. Therefore, you create a layer that gives visual appearance to it. +Note that data source can not be simply shown. Layers must reference them. Therefore, you create a layer that gives visual appearance to it. - Loading from local files @@ -304,8 +304,8 @@ parsing method: ``` - Creating Geometry, Feature, and FeatureCollections from scratch -Note that GeoJson objects as we discussed above have classes defined in MapLibre SDK. -So we can map json objects into regular Java/Kotlin objects or build straightaway. +Note that GeoJSON objects as we discussed above have classes defined in MapLibre SDK. +So we can map JSON objects into regular Java/Kotlin objects or build straightaway. ```kotlin val properties = JsonObject() properties.addProperty("key1", "value1") @@ -329,7 +329,7 @@ So we can map json objects into regular Java/Kotlin objects or build straightawa ``` ### 5. Updating data at runtime -The most important feature of GeoJsonDataSources, once we add one of them, we can set another set of data. +The most important feature of GeoJsonSources, once we add one of them, we can set another set of data. We achieve this with `setGeoJson()` method. For example we create a source variable and check if it is not assigned, then we create new source object and add it to style, otherwise we set another data: @@ -366,8 +366,8 @@ Probably the most advanced use case might be animating random objects such as ca ``` # Summary -GeoJsonDataSources come with their pros and cons. They work best if you want to add additional data to your style , or provide features like animating objects on your map. +GeoJsonSources come with their pros and cons. They work best if you want to add additional data to your style , or provide features like animating objects on your map. -It would be difficult if you have large datasets and you want to manipulate and store inside app. In that case you should prefer remote datasources. +It would be difficult if you have large datasets and you want to manipulate and store inside app. In that case you should prefer remote data source. Lastly, you may check [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for full guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") in order learn best practises to adopt in your apps. \ No newline at end of file From d5697dd9f407a4e42da9765cce63062e4fd8ede5 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Tue, 29 Oct 2024 12:19:13 +0500 Subject: [PATCH 04/17] refined and reconstructed with chatgpt --- docs/mdbook/src/android/geojson-guide.md | 94 +++++++++--------------- 1 file changed, 35 insertions(+), 59 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index a984b464dbc..35bdaf91b82 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -1,12 +1,10 @@ # Introduction This guide will teach you how to use [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJSON`]("https://geojson.org/") file format. - -You will start with fundamentals of how map renders data under the hood and why [JSON]("https://en.wikipedia.org/wiki/JSON") format is preferred in storing geospatial data +You will start with fundamentals of how a map renders data internally and why you should prefer [JSON]("https://en.wikipedia.org/wiki/JSON") format in storing geospatial data # Goals -After finishing this documentation you should be able to - +After finishing this documentation you should be able to: 1. understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other 2. describe JSON files 3. explore building blocks of `GeoJSON` data @@ -15,23 +13,17 @@ After finishing this documentation you should be able to ### 1. Styles, Layers, and Data source - `Style ` defines the visual representation of the map such as colors and appearance. - - `Layer` controls how data should be presented to the user - - `Data source` holds actual data and provides layers with it -Styles consist of collections of layers and data source. Layers reference data source. Hence they require a unique source ID when they are constructed - -It would be meaningless if we don't have any data to show so we need know supplying data with data source. - -Firstly, we need to understand how to store data and passing them into data source and therefore JSON comes into play in the next session. +Styles consist of collections of layers and data source. Layers reference data source. Hence they require a unique source ID when you construct them. +It would be meaningless if we don't have any data to show, so we need know how to supply data through a data source. +Firstly, we need to understand how to store data and pass it into a data source; therefore, we will discuss JSON in the next session. ### 2. JSON -JSON stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. - +JSON stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. It is popular because it is human readable and easy to parse into objects. - -JSON content is treated as string and it makes easy to transmit data across clients. JSON file is saved in .json extension +The system treats JSON content as a string, making it easy to transmit data across clients, and saves it as a .json extension A sample JSON file: ```json @@ -51,31 +43,17 @@ With its straightforward syntax, we can benefit from it by describing our geospa ### 3. GeoJSON [`GeoJSON`]("https://geojson.org/") is a JSON file for encoding various geographical data structures. - -It defines several JSON objects to represent geospatial information. GeoJSON file is saved with `.geojson` extension - -The following list illustrates the most fundamental objects: - -- Geometry -- Feature -- FeatureCollection - -`Geometry` is a single geometric shape that contains one or more coordinates. - -A geometry can be one of the following six types: - -- Point -- MultiPoint -- LineString -- MultilineString -- Polygon -- MultiPolygon - -They are visual objects that seen on map with one or more coordinates. We can use each depending on our requirements - -`Feautue` is a compound object of single geometry and user-defined attributes applied to that geometry such as name, color, etc. - -`FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. +It defines several JSON objects to represent geospatial information. We use the`.geojson` extension for GeoJSON files. +We define the most fundamental objects: +- `Geometry` refers to a single geometric shape that contains one or more coordinates. These shapes are visual objects displayed on a map. A geometry can be one of the following six types: + - Point + - MultiPoint + - LineString + - MultilineString + - Polygon + - MultiPolygon +- `Feautue` is a compound object that combines a single geometry with user-defined attributes, such as name, color. +- `FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. A typical GeoJSON file might look like: ```json @@ -140,12 +118,10 @@ So far we learned describing Geospatial data in GeoJSON files. We will start app ### 4. GeoJsonSource As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJSON`. -We will not deal with other sources and only focus on `GeoJsonSource`. - -`GeoJsonSource` is a type of source that has a unique `String` ID and GeoJSON data. There are several ways of creating and adding `GeoJsonSource` objects. - -A GeoJsonSource might be constructed with several approaches: +We will focus exclusively on `GeoJsonSource` and will not address other sources. +`GeoJsonSource` is a type of source that has a unique `String` ID and GeoJSON data. +There are several ways to construct a `GeoJsonSource`: - Locally stored files such as assets and raw folders - Remote services - Raw string parsed into FeatureCollections objects @@ -164,7 +140,8 @@ style.addSource(source) style.addLayer(lineLayer) ``` -Note that data source can not be simply shown. Layers must reference them. Therefore, you create a layer that gives visual appearance to it. +Note that you can not simply show data on a map. Layers must reference them. +Therefore, you create a layer that gives visual appearance to it. - Loading from local files @@ -303,9 +280,9 @@ parsing method: } ``` - Creating Geometry, Feature, and FeatureCollections from scratch - -Note that GeoJSON objects as we discussed above have classes defined in MapLibre SDK. -So we can map JSON objects into regular Java/Kotlin objects or build straightaway. + +Note that the GeoJSON objects we discussed earlier have classes defined in the MapLibre SDK. +Therefore, we can either map JSON objects to regular Java/Kotlin objects or build them directly. ```kotlin val properties = JsonObject() properties.addProperty("key1", "value1") @@ -329,10 +306,8 @@ So we can map JSON objects into regular Java/Kotlin objects or build straightawa ``` ### 5. Updating data at runtime -The most important feature of GeoJsonSources, once we add one of them, we can set another set of data. -We achieve this with `setGeoJson()` method. - -For example we create a source variable and check if it is not assigned, then we create new source object and add it to style, otherwise we set another data: +The key feature of GeoJsonSources is that once we add one, we can set another set of data. +We achieve this using `setGeoJson()` method. For instance, we create a source variable and check if we have not assigned it, then we create a new source object and add it to style; otherwise, we set a different data source: ```kotlin private fun createFeatureCollection(): FeatureCollection { val point = if (isInitialPosition) { @@ -359,15 +334,16 @@ For example we create a source variable and check if it is not assigned, then we } ``` -Probably the most advanced use case might be animating random objects such as cars. + +Another advanced example showcases random cars and a passenger on a map updating their positions with smooth animation. +The example defines two sources for the cars and passenger objects and we assign these sources to appropriate layers. +We use `ValueAnimator` objects and update positions with `onAnimationUpdate()`: ```kotlin {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt}} ``` # Summary -GeoJsonSources come with their pros and cons. They work best if you want to add additional data to your style , or provide features like animating objects on your map. - -It would be difficult if you have large datasets and you want to manipulate and store inside app. In that case you should prefer remote data source. - -Lastly, you may check [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for full guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") in order learn best practises to adopt in your apps. \ No newline at end of file +GeoJsonSources have their pros and cons. They are most effective when you want to add additional data to your style or provide features like animating objects on your map. +However, working with large datasets can be challenging if you need to manipulate and store data within the app; in such cases, it’s better to use a remote data source. +Lastly, you can refer to [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for a comprehensive guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") to learn best practises for your applications. \ No newline at end of file From 1f3bc7f80005f071db7580abc16689e4191a37be Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 12:18:05 +0500 Subject: [PATCH 05/17] corrected headline spacing --- docs/mdbook/src/android/geojson-guide.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 35bdaf91b82..96167966093 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -4,6 +4,7 @@ This guide will teach you how to use [`GeoJsonSource`]("https://maplibre.org/map You will start with fundamentals of how a map renders data internally and why you should prefer [JSON]("https://en.wikipedia.org/wiki/JSON") format in storing geospatial data # Goals + After finishing this documentation you should be able to: 1. understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other 2. describe JSON files @@ -12,6 +13,7 @@ After finishing this documentation you should be able to: 5. update data at runtime ### 1. Styles, Layers, and Data source + - `Style ` defines the visual representation of the map such as colors and appearance. - `Layer` controls how data should be presented to the user - `Data source` holds actual data and provides layers with it @@ -21,6 +23,7 @@ It would be meaningless if we don't have any data to show, so we need know how t Firstly, we need to understand how to store data and pass it into a data source; therefore, we will discuss JSON in the next session. ### 2. JSON + JSON stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. It is popular because it is human readable and easy to parse into objects. The system treats JSON content as a string, making it easy to transmit data across clients, and saves it as a .json extension @@ -42,6 +45,7 @@ A sample JSON file: With its straightforward syntax, we can benefit from it by describing our geospatial data inside JSON ### 3. GeoJSON + [`GeoJSON`]("https://geojson.org/") is a JSON file for encoding various geographical data structures. It defines several JSON objects to represent geospatial information. We use the`.geojson` extension for GeoJSON files. We define the most fundamental objects: @@ -117,6 +121,7 @@ A typical GeoJSON file might look like: So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications ### 4. GeoJsonSource + As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJSON`. We will focus exclusively on `GeoJsonSource` and will not address other sources. `GeoJsonSource` is a type of source that has a unique `String` ID and GeoJSON data. @@ -306,6 +311,7 @@ Therefore, we can either map JSON objects to regular Java/Kotlin objects or buil ``` ### 5. Updating data at runtime + The key feature of GeoJsonSources is that once we add one, we can set another set of data. We achieve this using `setGeoJson()` method. For instance, we create a source variable and check if we have not assigned it, then we create a new source object and add it to style; otherwise, we set a different data source: ```kotlin @@ -344,6 +350,7 @@ We use `ValueAnimator` objects and update positions with `onAnimationUpdate()`: ``` # Summary + GeoJsonSources have their pros and cons. They are most effective when you want to add additional data to your style or provide features like animating objects on your map. However, working with large datasets can be challenging if you need to manipulate and store data within the app; in such cases, it’s better to use a remote data source. Lastly, you can refer to [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for a comprehensive guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") to learn best practises for your applications. \ No newline at end of file From 4e9d445c785ac2fbedabac3040706fc1b0b979c0 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 12:22:46 +0500 Subject: [PATCH 06/17] capitalised first letters of sentences --- docs/mdbook/src/android/geojson-guide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 96167966093..afc2f761968 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -6,11 +6,11 @@ You will start with fundamentals of how a map renders data internally and why yo # Goals After finishing this documentation you should be able to: -1. understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other -2. describe JSON files -3. explore building blocks of `GeoJSON` data -4. use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s -5. update data at runtime +1. Understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other +2. Describe JSON files +3. Explore building blocks of `GeoJSON` data +4. Use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s +5. Update data at runtime ### 1. Styles, Layers, and Data source From d2a2cbe22e8d132e2735abbff664b8b21db80efd Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 12:38:30 +0500 Subject: [PATCH 07/17] added correct dots --- docs/mdbook/src/android/geojson-guide.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index afc2f761968..4a41eaad571 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -1,22 +1,22 @@ # Introduction This guide will teach you how to use [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJSON`]("https://geojson.org/") file format. -You will start with fundamentals of how a map renders data internally and why you should prefer [JSON]("https://en.wikipedia.org/wiki/JSON") format in storing geospatial data +You will start with fundamentals of how a map renders data internally and why you should prefer [JSON]("https://en.wikipedia.org/wiki/JSON") format in storing geospatial data. # Goals After finishing this documentation you should be able to: -1. Understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other -2. Describe JSON files -3. Explore building blocks of `GeoJSON` data -4. Use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s -5. Update data at runtime +1. Understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other. +2. Describe JSON files. +3. Explore building blocks of `GeoJSON` data. +4. Use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s. +5. Update data at runtime. ### 1. Styles, Layers, and Data source - `Style ` defines the visual representation of the map such as colors and appearance. -- `Layer` controls how data should be presented to the user -- `Data source` holds actual data and provides layers with it +- `Layer` controls how data should be presented to the user. +- `Data source` holds actual data and provides layers with it. Styles consist of collections of layers and data source. Layers reference data source. Hence they require a unique source ID when you construct them. It would be meaningless if we don't have any data to show, so we need know how to supply data through a data source. @@ -26,7 +26,7 @@ Firstly, we need to understand how to store data and pass it into a data source; JSON stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. It is popular because it is human readable and easy to parse into objects. -The system treats JSON content as a string, making it easy to transmit data across clients, and saves it as a .json extension +The system treats JSON content as a string, making it easy to transmit data across clients, and saves it as a .json extension. A sample JSON file: ```json @@ -42,7 +42,7 @@ A sample JSON file: } ``` -With its straightforward syntax, we can benefit from it by describing our geospatial data inside JSON +With its straightforward syntax, we can benefit from it by describing our geospatial data inside JSON. ### 3. GeoJSON @@ -118,7 +118,7 @@ A typical GeoJSON file might look like: ] } ``` -So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications +So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. ### 4. GeoJsonSource From 5b2bcacb64ddb97629b52bd3d270c39bf4c7f1c9 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 12:54:25 +0500 Subject: [PATCH 08/17] removed json part --- docs/mdbook/src/android/geojson-guide.md | 35 ++++-------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 4a41eaad571..3091d10b697 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -7,10 +7,9 @@ You will start with fundamentals of how a map renders data internally and why yo After finishing this documentation you should be able to: 1. Understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other. -2. Describe JSON files. -3. Explore building blocks of `GeoJSON` data. -4. Use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s. -5. Update data at runtime. +2. Explore building blocks of `GeoJSON` data. +3. Use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s. +4. Update data at runtime. ### 1. Styles, Layers, and Data source @@ -22,29 +21,7 @@ Styles consist of collections of layers and data source. Layers reference data s It would be meaningless if we don't have any data to show, so we need know how to supply data through a data source. Firstly, we need to understand how to store data and pass it into a data source; therefore, we will discuss JSON in the next session. -### 2. JSON - -JSON stands for JavaScript Object Notation. It is a key-value pair text format for storing and retrieving data between client and server. -It is popular because it is human readable and easy to parse into objects. -The system treats JSON content as a string, making it easy to transmit data across clients, and saves it as a .json extension. - -A sample JSON file: -```json -{ - "name": "John Doe", - "age": 30, - "isStudent": false, - "contact": { - "email": "johndoe@example.com", - "phone": "123-456-7890" - }, - "hobbies": ["reading", "traveling", "coding"] -} - -``` -With its straightforward syntax, we can benefit from it by describing our geospatial data inside JSON. - -### 3. GeoJSON +### 2. GeoJSON [`GeoJSON`]("https://geojson.org/") is a JSON file for encoding various geographical data structures. It defines several JSON objects to represent geospatial information. We use the`.geojson` extension for GeoJSON files. @@ -120,7 +97,7 @@ A typical GeoJSON file might look like: ``` So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. -### 4. GeoJsonSource +### 3. GeoJsonSource As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJSON`. We will focus exclusively on `GeoJsonSource` and will not address other sources. @@ -310,7 +287,7 @@ Therefore, we can either map JSON objects to regular Java/Kotlin objects or buil style.addLayer(layer) ``` -### 5. Updating data at runtime +### 4. Updating data at runtime The key feature of GeoJsonSources is that once we add one, we can set another set of data. We achieve this using `setGeoJson()` method. For instance, we create a source variable and check if we have not assigned it, then we create a new source object and add it to style; otherwise, we set a different data source: From 5700ae3462e9982ceb90b0336f57a6730fcb3590 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 15:58:05 +0500 Subject: [PATCH 09/17] referenced geojsonsource sample --- docs/mdbook/src/android/geojson-guide.md | 10 +--------- .../activity/style/CollectionUpdateOnStyleChange.kt | 2 ++ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 3091d10b697..de87a0c5ca7 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -111,15 +111,7 @@ There are several ways to construct a `GeoJsonSource`: A sample GeoJsonSource: ```kotlin -val source = GeoJsonSource("source", featureCollection) -val lineLayer = LineLayer("layer", "source") - .withProperties( - PropertyFactory.lineColor(Color.RED), - PropertyFactory.lineWidth(10f) - ) - -style.addSource(source) -style.addLayer(lineLayer) +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt:geojson}} ``` Note that you can not simply show data on a map. Layers must reference them. diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt index cdabb1ffc10..b9a8f94cbac 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt @@ -56,6 +56,7 @@ class CollectionUpdateOnStyleChange : AppCompatActivity(), OnMapReadyCallback, S } private fun setupLayer(style: Style) { + /* ANCHOR: geojson */ val source = GeoJsonSource("source", featureCollection) val lineLayer = LineLayer("layer", "source") .withProperties( @@ -65,6 +66,7 @@ class CollectionUpdateOnStyleChange : AppCompatActivity(), OnMapReadyCallback, S style.addSource(source) style.addLayer(lineLayer) + /* ANCHOR_END: geojson */ } private fun setupStyleChangeView() { From 5ccce0112ddf2260a007f3cdf51f31bff253f72a Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 16:01:25 +0500 Subject: [PATCH 10/17] referenced maplibre setup sample --- docs/mdbook/src/android/geojson-guide.md | 10 +--------- .../android/testapp/activity/style/NoStyleActivity.kt | 3 ++- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index de87a0c5ca7..1cbe4abbcdf 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -121,15 +121,7 @@ Therefore, you create a layer that gives visual appearance to it. with assets folder file ```kotlin - binding.mapView.getMapAsync { map -> - map.moveCamera(CameraUpdateFactory.newLatLngZoom(cameraTarget, cameraZoom)) - map.setStyle( - Style.Builder() - .withImage(imageId, imageIcon) - .withSource(GeoJsonSource(sourceId, URI("asset://points-sf.geojson"))) - .withLayer(SymbolLayer(layerId, sourceId).withProperties(iconImage(imageId))) - ) - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt:setup}} ``` with raw folder file ```kotlin diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt index 43e16d7ffd6..8da287e129a 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt @@ -29,7 +29,7 @@ class NoStyleActivity : AppCompatActivity() { super.onCreate(savedInstanceState) binding = ActivityMapSimpleBinding.inflate(layoutInflater) setContentView(binding.root) - + /* ANCHOR: setup */ binding.mapView.getMapAsync { map -> map.moveCamera(CameraUpdateFactory.newLatLngZoom(cameraTarget, cameraZoom)) map.setStyle( @@ -39,6 +39,7 @@ class NoStyleActivity : AppCompatActivity() { .withLayer(SymbolLayer(layerId, sourceId).withProperties(iconImage(imageId))) ) } + /* ANCHOR_END: setup */ } override fun onStart() { From 7b89d7b1a789782355a8c857fab68fe3ba95459f Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 16:25:33 +0500 Subject: [PATCH 11/17] added remote service reference --- docs/mdbook/src/android/geojson-guide.md | 49 ++----------------- .../activity/style/HeatmapLayerActivity.kt | 6 ++- .../activity/style/RuntimeStyleActivity.kt | 2 + .../android/testapp/utils/ResourceUtils.kt | 2 + 4 files changed, 12 insertions(+), 47 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 1cbe4abbcdf..769ca2fb720 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -125,59 +125,18 @@ with assets folder file ``` with raw folder file ```kotlin - val source: Source = try { - GeoJsonSource("amsterdam-spots", ResourceUtils.readRawResource(this, R.raw.amsterdam)) - } catch (ioException: IOException) { - Toast.makeText( - this@RuntimeStyleActivity, - "Couldn't add source: " + ioException.message, - Toast.LENGTH_SHORT - ).show() - return - } - maplibreMap.style!!.addSource(source) - var layer: FillLayer? = FillLayer("parksLayer", "amsterdam-spots") - layer!!.setProperties( - PropertyFactory.fillColor(Color.RED), - PropertyFactory.fillOutlineColor(Color.BLUE), - PropertyFactory.fillOpacity(0.3f), - PropertyFactory.fillAntialias(true) - ) + {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt:source}} ``` parsing method: ```kotlin - fun readRawResource(context: Context?, @RawRes rawResource: Int): String { - var json = "" - if (context != null) { - val writer: Writer = StringWriter() - val buffer = CharArray(1024) - context.resources.openRawResource(rawResource).use { `is` -> - val reader: Reader = BufferedReader(InputStreamReader(`is`, "UTF-8")) - var numRead: Int - while (reader.read(buffer).also { numRead = it } != -1) { - writer.write(buffer, 0, numRead) - } - } - json = writer.toString() - } - return json - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt:read_raw}} ``` - Loading from remote services ```kotlin - private fun createEarthquakeSource(): GeoJsonSource { - return GeoJsonSource(EARTHQUAKE_SOURCE_ID, URI(EARTHQUAKE_SOURCE_URL)) - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt:create_earthquake}} ``` ```kotlin - companion object { - private const val EARTHQUAKE_SOURCE_URL = - "https://maplibre.org/maplibre-gl-js-docs/assets/earthquakes.geojson" - private const val EARTHQUAKE_SOURCE_ID = "earthquakes" - private const val HEATMAP_LAYER_ID = "earthquakes-heat" - private const val HEATMAP_LAYER_SOURCE = "earthquakes" - private const val CIRCLE_LAYER_ID = "earthquakes-circle" - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt:constants}} ``` - Parsing string with `fromJson` method of FeatureCollection ```kotlin diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt index dacb8d41cbe..9959bf19235 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt @@ -45,10 +45,11 @@ class HeatmapLayerActivity : AppCompatActivity() { } ) } - + /* ANCHOR: create_earthquake */ private fun createEarthquakeSource(): GeoJsonSource { return GeoJsonSource(EARTHQUAKE_SOURCE_ID, URI(EARTHQUAKE_SOURCE_URL)) } + /* ANCHOR_END: create_earthquake */ private fun createHeatmapLayer(): HeatmapLayer { val layer = HeatmapLayer(HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID) @@ -187,7 +188,7 @@ class HeatmapLayerActivity : AppCompatActivity() { super.onDestroy() mapView.onDestroy() } - +/* ANCHOR: constants */ companion object { private const val EARTHQUAKE_SOURCE_URL = "https://maplibre.org/maplibre-gl-js-docs/assets/earthquakes.geojson" @@ -196,4 +197,5 @@ class HeatmapLayerActivity : AppCompatActivity() { private const val HEATMAP_LAYER_SOURCE = "earthquakes" private const val CIRCLE_LAYER_ID = "earthquakes-circle" } + /* ANCHOR_END: constants */ } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt index cbd8c83f4ba..9cc8d5b72c9 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt @@ -329,6 +329,7 @@ class RuntimeStyleActivity : AppCompatActivity() { private fun addParksLayer() { // Add a source + /* ANCHOR: source */ val source: Source = try { GeoJsonSource("amsterdam-spots", ResourceUtils.readRawResource(this, R.raw.amsterdam)) } catch (ioException: IOException) { @@ -347,6 +348,7 @@ class RuntimeStyleActivity : AppCompatActivity() { PropertyFactory.fillOpacity(0.3f), PropertyFactory.fillAntialias(true) ) + /* ANCHOR_END: source */ // Only show me parks (except westerpark with stroke-width == 3) layer.setFilter( diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt index cabe0ccdceb..ed1b5648e1b 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt @@ -7,6 +7,7 @@ import java.io.* object ResourceUtils { @JvmStatic + /* ANCHOR: read_raw */ fun readRawResource(context: Context?, @RawRes rawResource: Int): String { var json = "" if (context != null) { @@ -23,6 +24,7 @@ object ResourceUtils { } return json } + /* ANCHOR_END: read_raw */ fun convertDpToPx(context: Context, dp: Float): Float { return TypedValue.applyDimension( From 8cf7ba34089b7995f2b25a56b6dd01acfcfd61ed Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 16:29:07 +0500 Subject: [PATCH 12/17] fromjson feature referenced --- docs/mdbook/src/android/geojson-guide.md | 64 +------------------ .../turf/MapSnapshotterWithinExpression.kt | 5 +- 2 files changed, 4 insertions(+), 65 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 769ca2fb720..4b07cbcd982 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -140,69 +140,7 @@ parsing method: ``` - Parsing string with `fromJson` method of FeatureCollection ```kotlin - private fun bufferLineStringGeometry(): Polygon { - // TODO replace static data by Turf#Buffer: mapbox-java/issues/987 - return FeatureCollection.fromJson( - """ - { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - -77.06867337226866, - 38.90467655551809 - ], - [ - -77.06233263015747, - 38.90479344272695 - ], - [ - -77.06234335899353, - 38.906463238984344 - ], - [ - -77.06290125846863, - 38.907206285691615 - ], - [ - -77.06364154815674, - 38.90684728656818 - ], - [ - -77.06326603889465, - 38.90637140121084 - ], - [ - -77.06321239471436, - 38.905561553883246 - ], - [ - -77.0691454410553, - 38.905436318935635 - ], - [ - -77.06912398338318, - 38.90466820642439 - ], - [ - -77.06867337226866, - 38.90467655551809 - ] - ] - ] - } - } - ] - } - """.trimIndent() - ).features()!![0].geometry() as Polygon - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt:buffer_line}} ``` - Creating Geometry, Feature, and FeatureCollections from scratch diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt index 7b5e6b4f707..e97ce732009 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt @@ -187,8 +187,8 @@ class MapSnapshotterWithinExpression : AppCompatActivity() { super.onSaveInstanceState(outState, outPersistentState) binding.mapView.onSaveInstanceState(outState) } - - private fun bufferLineStringGeometry(): Polygon { + /* ANCHOR: buffer_line */ + private fun bufferLineStringGeometry(): Polygon { // TODO replace static data by Turf#Buffer: mapbox-java/issues/987 return FeatureCollection.fromJson( """ @@ -251,6 +251,7 @@ class MapSnapshotterWithinExpression : AppCompatActivity() { """.trimIndent() ).features()!![0].geometry() as Polygon } + /* ANCHOR_END: buffer_line */ companion object { const val POINT_ID = "point" From ff7d6ec02ff4f67fd0a82ff538808b0cb8efb2fa Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 16:33:43 +0500 Subject: [PATCH 13/17] referenced jsonobject --- docs/mdbook/src/android/geojson-guide.md | 20 +------------------ .../feature/QuerySourceFeaturesActivity.kt | 2 ++ 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 4b07cbcd982..83a0af135df 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -147,25 +147,7 @@ parsing method: Note that the GeoJSON objects we discussed earlier have classes defined in the MapLibre SDK. Therefore, we can either map JSON objects to regular Java/Kotlin objects or build them directly. ```kotlin - val properties = JsonObject() - properties.addProperty("key1", "value1") - val source = GeoJsonSource( - "test-source", - FeatureCollection.fromFeatures( - arrayOf( - Feature.fromGeometry(Point.fromLngLat(17.1, 51.0), properties), - Feature.fromGeometry(Point.fromLngLat(17.2, 51.0), properties), - Feature.fromGeometry(Point.fromLngLat(17.3, 51.0), properties), - Feature.fromGeometry(Point.fromLngLat(17.4, 51.0), properties) - ) - ) - ) - style.addSource(source) - val visible = Expression.eq(Expression.get("key1"), Expression.literal("value1")) - val invisible = Expression.neq(Expression.get("key1"), Expression.literal("value1")) - val layer = CircleLayer("test-layer", source.id) - .withFilter(visible) - style.addLayer(layer) +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt:json_object}} ``` ### 4. Updating data at runtime diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt index b4113a482bf..6df7269200a 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt @@ -43,6 +43,7 @@ class QuerySourceFeaturesActivity : AppCompatActivity() { } private fun initStyle(style: Style) { + /* ANCHOR: json_object */ val properties = JsonObject() properties.addProperty("key1", "value1") val source = GeoJsonSource( @@ -62,6 +63,7 @@ class QuerySourceFeaturesActivity : AppCompatActivity() { val layer = CircleLayer("test-layer", source.id) .withFilter(visible) style.addLayer(layer) + /* ANCHOR_END: json_object */ // Add a click listener maplibreMap.addOnMapClickListener { point: LatLng? -> From 22aa9a7e2392a7ae81e506c55124415994463b66 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 13 Nov 2024 16:38:19 +0500 Subject: [PATCH 14/17] referenced update runtime feature --- docs/mdbook/src/android/geojson-guide.md | 22 ++----------------- .../style/ZoomFunctionSymbolLayerActivity.kt | 6 +++-- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index 83a0af135df..d1526a01b0a 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -155,29 +155,11 @@ Therefore, we can either map JSON objects to regular Java/Kotlin objects or buil The key feature of GeoJsonSources is that once we add one, we can set another set of data. We achieve this using `setGeoJson()` method. For instance, we create a source variable and check if we have not assigned it, then we create a new source object and add it to style; otherwise, we set a different data source: ```kotlin - private fun createFeatureCollection(): FeatureCollection { - val point = if (isInitialPosition) { - Point.fromLngLat(-74.01618140, 40.701745) - } else { - Point.fromLngLat(-73.988097, 40.749864) - } - val properties = JsonObject() - properties.addProperty(KEY_PROPERTY_SELECTED, isSelected) - val feature = Feature.fromGeometry(point, properties) - return FeatureCollection.fromFeatures(arrayOf(feature)) - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt:createFeatureCollection}} ``` ```kotlin - private fun updateSource(style: Style?) { - val featureCollection = createFeatureCollection() - if (source != null) { - source!!.setGeoJson(featureCollection) - } else { - source = GeoJsonSource(SOURCE_ID, featureCollection) - style!!.addSource(source!!) - } - } +{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt:updateSource}} ``` diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt index b7647dcdfc5..89c9eca3d33 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt @@ -60,7 +60,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { } } } - + /* ANCHOR: updateSource */ private fun updateSource(style: Style?) { val featureCollection = createFeatureCollection() if (source != null) { @@ -70,6 +70,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { style!!.addSource(source!!) } } + /* ANCHOR_END: updateSource */ private fun toggleSymbolLayerVisibility() { layer!!.setProperties( @@ -77,7 +78,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { ) isShowingSymbolLayer = !isShowingSymbolLayer } - + /* ANCHOR: createFeatureCollection */ private fun createFeatureCollection(): FeatureCollection { val point = if (isInitialPosition) { Point.fromLngLat(-74.01618140, 40.701745) @@ -89,6 +90,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { val feature = Feature.fromGeometry(point, properties) return FeatureCollection.fromFeatures(arrayOf(feature)) } + /* ANCHOR_END: createFeatureCollection */ private fun addLayer(style: Style) { layer = SymbolLayer(LAYER_ID, SOURCE_ID) From 03040e04c7b63a37a6dede5d9ea1a970175b2794 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Sat, 16 Nov 2024 09:00:36 +0500 Subject: [PATCH 15/17] geojson example updated --- docs/mdbook/src/android/geojson-guide.md | 61 ++---------------------- 1 file changed, 3 insertions(+), 58 deletions(-) diff --git a/docs/mdbook/src/android/geojson-guide.md b/docs/mdbook/src/android/geojson-guide.md index d1526a01b0a..6e4a195fd02 100644 --- a/docs/mdbook/src/android/geojson-guide.md +++ b/docs/mdbook/src/android/geojson-guide.md @@ -36,64 +36,9 @@ We define the most fundamental objects: - `Feautue` is a compound object that combines a single geometry with user-defined attributes, such as name, color. - `FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. -A typical GeoJSON file might look like: -```json - { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - -77.06867337226866, - 38.90467655551809 - ], - [ - -77.06233263015747, - 38.90479344272695 - ], - [ - -77.06234335899353, - 38.906463238984344 - ], - [ - -77.06290125846863, - 38.907206285691615 - ], - [ - -77.06364154815674, - 38.90684728656818 - ], - [ - -77.06326603889465, - 38.90637140121084 - ], - [ - -77.06321239471436, - 38.905561553883246 - ], - [ - -77.0691454410553, - 38.905436318935635 - ], - [ - -77.06912398338318, - 38.90466820642439 - ], - [ - -77.06867337226866, - 38.90467655551809 - ] - ] - ] - } - } - ] -} +A typical GeoJSON structure might look like: +```kotlin + {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt:buffer_line}} ``` So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. From 49089d7fcaf05fc13d6915eb8479934a65215390 Mon Sep 17 00:00:00 2001 From: Dilshodbek Date: Wed, 27 Nov 2024 17:27:24 +0500 Subject: [PATCH 16/17] renamed title --- platform/android/docs/geojson-guide.md | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/platform/android/docs/geojson-guide.md b/platform/android/docs/geojson-guide.md index 6e4a195fd02..125c6deeb59 100644 --- a/platform/android/docs/geojson-guide.md +++ b/platform/android/docs/geojson-guide.md @@ -1,4 +1,4 @@ -# Introduction +# Using a GeoJSON Source This guide will teach you how to use [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJSON`]("https://geojson.org/") file format. You will start with fundamentals of how a map renders data internally and why you should prefer [JSON]("https://en.wikipedia.org/wiki/JSON") format in storing geospatial data. @@ -21,18 +21,18 @@ Styles consist of collections of layers and data source. Layers reference data s It would be meaningless if we don't have any data to show, so we need know how to supply data through a data source. Firstly, we need to understand how to store data and pass it into a data source; therefore, we will discuss JSON in the next session. -### 2. GeoJSON +### 2. GeoJSON [`GeoJSON`]("https://geojson.org/") is a JSON file for encoding various geographical data structures. It defines several JSON objects to represent geospatial information. We use the`.geojson` extension for GeoJSON files. We define the most fundamental objects: - `Geometry` refers to a single geometric shape that contains one or more coordinates. These shapes are visual objects displayed on a map. A geometry can be one of the following six types: - - Point - - MultiPoint - - LineString - - MultilineString - - Polygon - - MultiPolygon + - Point + - MultiPoint + - LineString + - MultilineString + - Polygon + - MultiPolygon - `Feautue` is a compound object that combines a single geometry with user-defined attributes, such as name, color. - `FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. @@ -40,7 +40,7 @@ A typical GeoJSON structure might look like: ```kotlin {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt:buffer_line}} ``` -So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. +So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. ### 3. GeoJsonSource @@ -50,7 +50,7 @@ We will focus exclusively on `GeoJsonSource` and will not address other sources. There are several ways to construct a `GeoJsonSource`: - Locally stored files such as assets and raw folders -- Remote services +- Remote services - Raw string parsed into FeatureCollections objects - Geometry, Feature, and FeatureCollection objects that map to GeoJSON Base builders @@ -89,7 +89,7 @@ parsing method: ``` - Creating Geometry, Feature, and FeatureCollections from scratch -Note that the GeoJSON objects we discussed earlier have classes defined in the MapLibre SDK. +Note that the GeoJSON objects we discussed earlier have classes defined in the MapLibre SDK. Therefore, we can either map JSON objects to regular Java/Kotlin objects or build them directly. ```kotlin {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt:json_object}} @@ -108,8 +108,8 @@ We achieve this using `setGeoJson()` method. For instance, we create a source va ``` -Another advanced example showcases random cars and a passenger on a map updating their positions with smooth animation. -The example defines two sources for the cars and passenger objects and we assign these sources to appropriate layers. +Another advanced example showcases random cars and a passenger on a map updating their positions with smooth animation. +The example defines two sources for the cars and passenger objects and we assign these sources to appropriate layers. We use `ValueAnimator` objects and update positions with `onAnimationUpdate()`: ```kotlin @@ -118,6 +118,6 @@ We use `ValueAnimator` objects and update positions with `onAnimationUpdate()`: # Summary -GeoJsonSources have their pros and cons. They are most effective when you want to add additional data to your style or provide features like animating objects on your map. +GeoJsonSources have their pros and cons. They are most effective when you want to add additional data to your style or provide features like animating objects on your map. However, working with large datasets can be challenging if you need to manipulate and store data within the app; in such cases, it’s better to use a remote data source. Lastly, you can refer to [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for a comprehensive guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") to learn best practises for your applications. \ No newline at end of file From a23b6ec04089bb47eaab8166fdf6b84fc4c76c83 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Thu, 28 Nov 2024 14:53:24 +0100 Subject: [PATCH 17/17] Fix some problems, use new snippet syntax --- .../feature/QuerySourceFeaturesActivity.kt | 4 +- .../style/CollectionUpdateOnStyleChange.kt | 4 +- .../activity/style/HeatmapLayerActivity.kt | 9 +- .../testapp/activity/style/NoStyleActivity.kt | 4 +- .../activity/style/RuntimeStyleActivity.kt | 4 +- .../style/ZoomFunctionSymbolLayerActivity.kt | 10 +- .../turf/MapSnapshotterWithinExpression.kt | 4 +- .../android/testapp/utils/ResourceUtils.kt | 4 +- platform/android/docs/geojson-guide.md | 133 ++++++++++-------- 9 files changed, 95 insertions(+), 81 deletions(-) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt index 6df7269200a..213994f3cbc 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt @@ -43,7 +43,7 @@ class QuerySourceFeaturesActivity : AppCompatActivity() { } private fun initStyle(style: Style) { - /* ANCHOR: json_object */ + // # --8<-- [start:JsonObject] val properties = JsonObject() properties.addProperty("key1", "value1") val source = GeoJsonSource( @@ -63,7 +63,7 @@ class QuerySourceFeaturesActivity : AppCompatActivity() { val layer = CircleLayer("test-layer", source.id) .withFilter(visible) style.addLayer(layer) - /* ANCHOR_END: json_object */ + // # --8<-- [end:JsonObject] // Add a click listener maplibreMap.addOnMapClickListener { point: LatLng? -> diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt index b9a8f94cbac..589e6e623bf 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt @@ -56,7 +56,7 @@ class CollectionUpdateOnStyleChange : AppCompatActivity(), OnMapReadyCallback, S } private fun setupLayer(style: Style) { - /* ANCHOR: geojson */ + // # --8<-- [start:setupLayer] val source = GeoJsonSource("source", featureCollection) val lineLayer = LineLayer("layer", "source") .withProperties( @@ -66,7 +66,7 @@ class CollectionUpdateOnStyleChange : AppCompatActivity(), OnMapReadyCallback, S style.addSource(source) style.addLayer(lineLayer) - /* ANCHOR_END: geojson */ + // # --8<-- [end:setupLayer] } private fun setupStyleChangeView() { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt index 9959bf19235..117346e5694 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt @@ -45,11 +45,11 @@ class HeatmapLayerActivity : AppCompatActivity() { } ) } - /* ANCHOR: create_earthquake */ + // # --8<-- [start:createEarthquakeSource] private fun createEarthquakeSource(): GeoJsonSource { return GeoJsonSource(EARTHQUAKE_SOURCE_ID, URI(EARTHQUAKE_SOURCE_URL)) } - /* ANCHOR_END: create_earthquake */ + // # --8<-- [end:createEarthquakeSource] private fun createHeatmapLayer(): HeatmapLayer { val layer = HeatmapLayer(HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID) @@ -188,7 +188,8 @@ class HeatmapLayerActivity : AppCompatActivity() { super.onDestroy() mapView.onDestroy() } -/* ANCHOR: constants */ + + // # --8<-- [start:constants] companion object { private const val EARTHQUAKE_SOURCE_URL = "https://maplibre.org/maplibre-gl-js-docs/assets/earthquakes.geojson" @@ -197,5 +198,5 @@ class HeatmapLayerActivity : AppCompatActivity() { private const val HEATMAP_LAYER_SOURCE = "earthquakes" private const val CIRCLE_LAYER_ID = "earthquakes-circle" } - /* ANCHOR_END: constants */ + // # --8<-- [end:constants] } diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt index 8da287e129a..3352d2a56e4 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt @@ -29,7 +29,7 @@ class NoStyleActivity : AppCompatActivity() { super.onCreate(savedInstanceState) binding = ActivityMapSimpleBinding.inflate(layoutInflater) setContentView(binding.root) - /* ANCHOR: setup */ + // # --8<-- [start:setup] binding.mapView.getMapAsync { map -> map.moveCamera(CameraUpdateFactory.newLatLngZoom(cameraTarget, cameraZoom)) map.setStyle( @@ -39,7 +39,7 @@ class NoStyleActivity : AppCompatActivity() { .withLayer(SymbolLayer(layerId, sourceId).withProperties(iconImage(imageId))) ) } - /* ANCHOR_END: setup */ + // # --8<-- [end:setup] } override fun onStart() { diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt index 85c93690c34..71341d47405 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt @@ -329,7 +329,7 @@ class RuntimeStyleActivity : AppCompatActivity() { private fun addParksLayer() { // Add a source - /* ANCHOR: source */ + // # --8<-- [start:source] val source: Source = try { GeoJsonSource("amsterdam-spots", ResourceUtils.readRawResource(this, R.raw.amsterdam)) } catch (ioException: IOException) { @@ -348,7 +348,7 @@ class RuntimeStyleActivity : AppCompatActivity() { PropertyFactory.fillOpacity(0.3f), PropertyFactory.fillAntialias(true) ) - /* ANCHOR_END: source */ + // # --8<-- [end:source] // Only show me parks (except westerpark with stroke-width == 3) layer.setFilter( diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt index 89c9eca3d33..b2551676561 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt @@ -60,7 +60,8 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { } } } - /* ANCHOR: updateSource */ + + // # --8<-- [start:updateSource] private fun updateSource(style: Style?) { val featureCollection = createFeatureCollection() if (source != null) { @@ -70,7 +71,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { style!!.addSource(source!!) } } - /* ANCHOR_END: updateSource */ + // # --8<-- [end:updateSource] private fun toggleSymbolLayerVisibility() { layer!!.setProperties( @@ -78,7 +79,8 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { ) isShowingSymbolLayer = !isShowingSymbolLayer } - /* ANCHOR: createFeatureCollection */ + + // # --8<-- [start:createFeatureCollection] private fun createFeatureCollection(): FeatureCollection { val point = if (isInitialPosition) { Point.fromLngLat(-74.01618140, 40.701745) @@ -90,7 +92,7 @@ class ZoomFunctionSymbolLayerActivity : AppCompatActivity() { val feature = Feature.fromGeometry(point, properties) return FeatureCollection.fromFeatures(arrayOf(feature)) } - /* ANCHOR_END: createFeatureCollection */ + // # --8<-- [end:createFeatureCollection] private fun addLayer(style: Style) { layer = SymbolLayer(LAYER_ID, SOURCE_ID) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt index e97ce732009..ae7f447275f 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt @@ -187,9 +187,9 @@ class MapSnapshotterWithinExpression : AppCompatActivity() { super.onSaveInstanceState(outState, outPersistentState) binding.mapView.onSaveInstanceState(outState) } - /* ANCHOR: buffer_line */ private fun bufferLineStringGeometry(): Polygon { // TODO replace static data by Turf#Buffer: mapbox-java/issues/987 + // # --8<-- [start:fromJson] return FeatureCollection.fromJson( """ { @@ -250,8 +250,8 @@ class MapSnapshotterWithinExpression : AppCompatActivity() { } """.trimIndent() ).features()!![0].geometry() as Polygon + // # --8<-- [end:fromJson] } - /* ANCHOR_END: buffer_line */ companion object { const val POINT_ID = "point" diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt index ed1b5648e1b..5e9a28efe43 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt @@ -7,7 +7,7 @@ import java.io.* object ResourceUtils { @JvmStatic - /* ANCHOR: read_raw */ + // # --8<-- [start:readRawResource] fun readRawResource(context: Context?, @RawRes rawResource: Int): String { var json = "" if (context != null) { @@ -24,7 +24,7 @@ object ResourceUtils { } return json } - /* ANCHOR_END: read_raw */ + // # --8<-- [end:readRawResource] fun convertDpToPx(context: Context, dp: Float): Float { return TypedValue.applyDimension( diff --git a/platform/android/docs/geojson-guide.md b/platform/android/docs/geojson-guide.md index 125c6deeb59..db7c0f1a943 100644 --- a/platform/android/docs/geojson-guide.md +++ b/platform/android/docs/geojson-guide.md @@ -1,31 +1,33 @@ # Using a GeoJSON Source -This guide will teach you how to use [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html") by deep diving into [`GeoJSON`]("https://geojson.org/") file format. -You will start with fundamentals of how a map renders data internally and why you should prefer [JSON]("https://en.wikipedia.org/wiki/JSON") format in storing geospatial data. +This guide will teach you how to use [`GeoJsonSource`](https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-geo-json-source/index.html) by deep diving into [GeoJSON](https://geojson.org/) file format. -# Goals +## Goals After finishing this documentation you should be able to: -1. Understand how [`Style`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.maps/-style/index.html?query=open%20class%20Style"), [`Layer`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.layers/-layer/index.html?query=abstract%20class%20Layer"), and [`Data source`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source") interact with each other. -2. Explore building blocks of `GeoJSON` data. -3. Use `GeoJSON` files in constructing [`GeoJsonSource`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-source/index.html?query=abstract%20class%20Source")s. + +1. Understand how `Style`, `Layer`, and `Source` interact with each other. +2. Explore building blocks of GeoJSON data. +3. Use GeoJSON files in constructing `GeoJsonSource`s. 4. Update data at runtime. -### 1. Styles, Layers, and Data source +## 1. Styles, Layers, and Data source -- `Style ` defines the visual representation of the map such as colors and appearance. -- `Layer` controls how data should be presented to the user. -- `Data source` holds actual data and provides layers with it. +- A style defines the visual representation of the map such as colors and appearance. +- Layers control how data should be presented to the user. +- Data sources hold actual data and provides layers with it. -Styles consist of collections of layers and data source. Layers reference data source. Hence they require a unique source ID when you construct them. +Styles consist of collections of layers and a data source. Layers reference data sources. Hence, they require a unique source ID when you construct them. It would be meaningless if we don't have any data to show, so we need know how to supply data through a data source. -Firstly, we need to understand how to store data and pass it into a data source; therefore, we will discuss JSON in the next session. -### 2. GeoJSON +Firstly, we need to understand how to store data and pass it into a data source; therefore, we will discuss GeoJSON in the next session. + +## 2. GeoJSON -[`GeoJSON`]("https://geojson.org/") is a JSON file for encoding various geographical data structures. -It defines several JSON objects to represent geospatial information. We use the`.geojson` extension for GeoJSON files. +[GeoJSON](https://geojson.org/) is a JSON file for encoding various geographical data structures. +It defines several JSON objects to represent geospatial information. Typicalle the`.geojson` extension is used for GeoJSON files. We define the most fundamental objects: + - `Geometry` refers to a single geometric shape that contains one or more coordinates. These shapes are visual objects displayed on a map. A geometry can be one of the following six types: - Point - MultiPoint @@ -37,87 +39,96 @@ We define the most fundamental objects: - `FeatureCollection` is set of features stored in an array. It is a root object that introduces all other features. A typical GeoJSON structure might look like: -```kotlin - {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt:buffer_line}} + +```json +{ + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [125.6, 10.1] + }, + "properties": { + "name": "Dinagat Islands" + } +} ``` -So far we learned describing Geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. -### 3. GeoJsonSource +So far we learned describing geospatial data in GeoJSON files. We will start applying this knowledge into our map applications. + +## 3. GeoJsonSource -As we discussed before, map requires some sort data to be rendered. We use different sources such as [`Vector`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-vector-source/index.html?query=class%20VectorSource%20:%20Source"), [`Raster`]("https://maplibre.org/maplibre-native/android/api/-map-libre%20-native%20-android/org.maplibre.android.style.sources/-raster-source/index.html?query=class%20RasterSource%20:%20Source") and `GeoJSON`. +As we discussed before, map requires some sort data to be rendered. We use different sources such as Vector, Raster and GeoJSON. We will focus exclusively on `GeoJsonSource` and will not address other sources. + `GeoJsonSource` is a type of source that has a unique `String` ID and GeoJSON data. There are several ways to construct a `GeoJsonSource`: + - Locally stored files such as assets and raw folders - Remote services - Raw string parsed into FeatureCollections objects - Geometry, Feature, and FeatureCollection objects that map to GeoJSON Base builders -A sample GeoJsonSource: +A sample `GeoJsonSource`: + ```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt:geojson}} +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/CollectionUpdateOnStyleChange.kt:setupLayer" ``` -Note that you can not simply show data on a map. Layers must reference them. -Therefore, you create a layer that gives visual appearance to it. +Note that you can not simply show data on a map. Layers must reference them. Therefore, you create a layer that gives visual appearance to it. -- Loading from local files +### Creating GeoJSON sources -with assets folder file -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt:setup}} +There are various ways you can create a `GeoJSONSource`. Some of the options are shown below. + +```kotlin title="Loading from local files with assets folder file" +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/NoStyleActivity.kt:setup" ``` -with raw folder file -```kotlin - {{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt:source}} + +```kotlin title="Loading with raw folder file" +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/RuntimeStyleActivity.kt:source" ``` -parsing method: -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt:read_raw}} + +```kotlin title="Parsing inline JSON" +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/utils/ResourceUtils.kt:readRawResource" ``` -- Loading from remote services -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt:create_earthquake}} + +```kotlin title="Loading from remote services" +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt:createEarthquakeSource" ``` -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt:constants}} + +```kotlin +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt:constants" ``` -- Parsing string with `fromJson` method of FeatureCollection -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt:buffer_line}} + +```kotlin title="Parsing string with the fromJson method of FeatureCollection" +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/turf/MapSnapshotterWithinExpression.kt:fromJson" +``` + +```kotlin title="Creating Geometry, Feature, and FeatureCollections from scratch" +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt:JsonObject" ``` -- Creating Geometry, Feature, and FeatureCollections from scratch Note that the GeoJSON objects we discussed earlier have classes defined in the MapLibre SDK. Therefore, we can either map JSON objects to regular Java/Kotlin objects or build them directly. -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/feature/QuerySourceFeaturesActivity.kt:json_object}} -``` -### 4. Updating data at runtime +## 4. Updating data at runtime -The key feature of GeoJsonSources is that once we add one, we can set another set of data. +The key feature of `GeoJsonSource`s is that once we add one, we can set another set of data. We achieve this using `setGeoJson()` method. For instance, we create a source variable and check if we have not assigned it, then we create a new source object and add it to style; otherwise, we set a different data source: -```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt:createFeatureCollection}} -``` ```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt:updateSource}} +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt:createFeatureCollection" ``` - -Another advanced example showcases random cars and a passenger on a map updating their positions with smooth animation. -The example defines two sources for the cars and passenger objects and we assign these sources to appropriate layers. -We use `ValueAnimator` objects and update positions with `onAnimationUpdate()`: - ```kotlin -{{#include ../../../../platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/AnimatedSymbolLayerActivity.kt}} +--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/ZoomFunctionSymbolLayerActivity.kt:updateSource" ``` -# Summary +See [this guide](styling/animated-symbol-layer.md) for an advanced example that showcases random cars and a passenger on a map updating their positions with smooth animation. + +## Summary GeoJsonSources have their pros and cons. They are most effective when you want to add additional data to your style or provide features like animating objects on your map. -However, working with large datasets can be challenging if you need to manipulate and store data within the app; in such cases, it’s better to use a remote data source. -Lastly, you can refer to [`Official Maplibre Android Documentation`]("https://maplibre.org/maplibre-native/android/api/index.html") for a comprehensive guide and [`Test App`]("https://github.com/maplibre/maplibre-native/tree/main/platform/android/MapLibreAndroidTestApp") to learn best practises for your applications. \ No newline at end of file + +However, working with large datasets can be challenging if you need to manipulate and store data within the app; in such cases, it’s better to use a remote data source. \ No newline at end of file