Skip to content

Commit 5da2313

Browse files
authored
Include 200.6 samples changes (#249)
1 parent 869aec6 commit 5da2313

File tree

33 files changed

+1579
-7
lines changed

33 files changed

+1579
-7
lines changed

gradle/libs.versions.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[versions]
22

33
# ArcGIS Maps SDK for Kotlin version
4-
arcgisMapsKotlinVersion = "200.6.0-4331"
4+
arcgisMapsKotlinVersion = "200.6.0-4398"
55

66
### Android versions
77
androidGradlePlugin = "8.5.1"
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Add ENC exchange set
2+
3+
Display nautical charts per the ENC specification.
4+
5+
![Image showing the add ENC exchange set app](add-enc-exchange-set.png)
6+
7+
## Use case
8+
9+
The [ENC specification](https://docs.iho.int/iho_pubs/standard/S-57Ed3.1/20ApB1.pdf) describes how hydrographic data should be displayed digitally.
10+
11+
An ENC exchange set is a catalog of data files which can be loaded as cells. The cells contain information on how symbols should be displayed in relation to one another, so as to represent information such as depth and obstacles accurately.
12+
13+
## How to use the sample
14+
15+
Run the sample and view the ENC data. Pan and zoom around the map. Take note of the high level of detail in the data and the smooth rendering of the layer.
16+
17+
## How it works
18+
19+
1. Specify the path to a local CATALOG.031 file to create an `EncExchangeSet`.
20+
2. After loading the exchange set, get the `EncDataset` objects in the exchange set with `EncExchangeSet.datasets`.
21+
3. Create an `EncCell` for each dataset. Then create an `EncLayer` for each cell.
22+
4. Add the ENC layer to a map's operational layers collection to display it.
23+
24+
## Relevant API
25+
26+
* EncCell
27+
* EncDataset
28+
* EncExchangeSet
29+
* EncLayer
30+
31+
## Offline data
32+
33+
This sample downloads the [ENC Exchange Set without updates](https://www.arcgis.com/home/item.html?id=9d2987a825c646468b3ce7512fb76e2d) and [Hydrography dataset resources](https://www.arcgis.com/home/item.html?id=5028bf3513ff4c38b28822d010a4937c) from ArcGIS Online.
34+
35+
## Additional information
36+
37+
This sample uses the GeoViewCompose Toolkit module to be able to implement a Composable SceneView.
38+
39+
## Tags
40+
41+
data, ENC, geoviewcompose, hydrographic, layers, maritime, nautical chart
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"category": "Layers",
3+
"description": "Display nautical charts per the ENC specification.",
4+
"formal_name": "AddEncExchangeSet",
5+
"ignore": false,
6+
"images": [
7+
"add-enc-exchange-set.png"
8+
],
9+
"keywords": [
10+
"ENC",
11+
"data",
12+
"geoviewcompose",
13+
"hydrographic",
14+
"layers",
15+
"maritime",
16+
"nautical chart",
17+
"EncCell",
18+
"EncDataset",
19+
"EncExchangeSet",
20+
"EncLayer"
21+
],
22+
"language": "kotlin",
23+
"provision_from": [
24+
"https://www.arcgis.com/home/item.html?id=9d2987a825c646468b3ce7512fb76e2d",
25+
"https://www.arcgis.com/home/item.html?id=5028bf3513ff4c38b28822d010a4937c"
26+
],
27+
"provision_to": [],
28+
"redirect_from": "",
29+
"relevant_apis": [
30+
"EncCell",
31+
"EncDataset",
32+
"EncExchangeSet",
33+
"EncLayer"
34+
],
35+
"snippets": [
36+
"src/main/java/com/esri/arcgismaps/sample/addencexchangeset/MainActivity.kt",
37+
"src/main/java/com/esri/arcgismaps/sample/addencexchangeset/DownloadActivity.kt",
38+
"src/main/java/com/esri/arcgismaps/sample/addencexchangeset/components/MapViewModel.kt",
39+
"src/main/java/com/esri/arcgismaps/sample/addencexchangeset/screens/MainScreen.kt"
40+
],
41+
"title": "Add ENC exchange set"
42+
}
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
plugins {
2+
alias(libs.plugins.arcgismaps.android.library)
3+
alias(libs.plugins.arcgismaps.android.library.compose)
4+
alias(libs.plugins.arcgismaps.kotlin.sample)
5+
alias(libs.plugins.gradle.secrets)
6+
}
7+
8+
secrets {
9+
// this file doesn't contain secrets, it just provides defaults which can be committed into git.
10+
defaultPropertiesFileName = "secrets.defaults.properties"
11+
}
12+
13+
android {
14+
namespace = "com.esri.arcgismaps.sample.addencexchangeset"
15+
// For view based samples
16+
buildFeatures {
17+
buildConfig = true
18+
}
19+
}
20+
21+
dependencies {
22+
// Only module specific dependencies needed here
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<uses-permission android:name="android.permission.INTERNET" />
5+
6+
<application><activity
7+
android:name=".DownloadActivity"
8+
android:exported="true"
9+
android:label="@string/add_enc_exchange_set_app_name">
10+
11+
</activity>
12+
<activity
13+
android:name=".MainActivity"
14+
android:exported="true"
15+
android:label="@string/add_enc_exchange_set_app_name">
16+
<intent-filter>
17+
<action android:name="android.intent.action.MAIN" />
18+
</intent-filter>
19+
</activity>
20+
</application>
21+
22+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* Copyright 2024 Esri
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
package com.esri.arcgismaps.sample.addencexchangeset
18+
19+
import android.content.Intent
20+
import android.os.Bundle
21+
import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity
22+
23+
class DownloadActivity : DownloaderActivity() {
24+
override fun onCreate(savedInstanceState: Bundle?) {
25+
super.onCreate(savedInstanceState)
26+
downloadAndStartSample(
27+
Intent(this, MainActivity::class.java),
28+
// get the app name of the sample
29+
getString(R.string.add_enc_exchange_set_app_name),
30+
listOf(
31+
// ArcGIS Portal item containing ENC hydrography resources
32+
"https://www.arcgis.com/home/item.html?id=5028bf3513ff4c38b28822d010a4937c",
33+
// ArcGIS Portal item containing the ENC dataset
34+
"https://www.arcgis.com/home/item.html?id=9d2987a825c646468b3ce7512fb76e2d"
35+
)
36+
)
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* Copyright 2024 Esri
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
package com.esri.arcgismaps.sample.addencexchangeset
18+
19+
import android.os.Bundle
20+
import androidx.activity.ComponentActivity
21+
import androidx.activity.compose.setContent
22+
import androidx.compose.material3.MaterialTheme
23+
import androidx.compose.material3.Surface
24+
import androidx.compose.runtime.Composable
25+
import com.arcgismaps.ApiKey
26+
import com.arcgismaps.ArcGISEnvironment
27+
import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme
28+
import com.esri.arcgismaps.sample.addencexchangeset.screens.MainScreen
29+
30+
class MainActivity : ComponentActivity() {
31+
32+
override fun onCreate(savedInstanceState: Bundle?) {
33+
super.onCreate(savedInstanceState)
34+
// authentication with an API key or named user is
35+
// required to access basemaps and other location services
36+
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN)
37+
38+
setContent {
39+
SampleAppTheme {
40+
SampleApp()
41+
}
42+
}
43+
}
44+
45+
@Composable
46+
private fun SampleApp() {
47+
Surface(
48+
color = MaterialTheme.colorScheme.background
49+
) {
50+
MainScreen(
51+
sampleName = getString(R.string.add_enc_exchange_set_app_name)
52+
)
53+
}
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* Copyright 2024 Esri
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
package com.esri.arcgismaps.sample.addencexchangeset.components
18+
19+
import android.app.Application
20+
import androidx.compose.runtime.getValue
21+
import androidx.compose.runtime.mutableStateOf
22+
import androidx.compose.runtime.setValue
23+
import androidx.lifecycle.AndroidViewModel
24+
import androidx.lifecycle.viewModelScope
25+
import com.arcgismaps.geometry.Envelope
26+
import com.arcgismaps.geometry.GeometryEngine
27+
import com.arcgismaps.hydrography.EncCell
28+
import com.arcgismaps.hydrography.EncEnvironmentSettings
29+
import com.arcgismaps.hydrography.EncExchangeSet
30+
import com.arcgismaps.mapping.ArcGISMap
31+
import com.arcgismaps.mapping.BasemapStyle
32+
import com.arcgismaps.mapping.Viewpoint
33+
import com.arcgismaps.mapping.layers.EncLayer
34+
import com.esri.arcgismaps.sample.addencexchangeset.R
35+
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel
36+
import kotlinx.coroutines.launch
37+
import java.io.File
38+
39+
class MapViewModel(application: Application) : AndroidViewModel(application) {
40+
private val provisionPath: String by lazy {
41+
application.getExternalFilesDir(null)?.path.toString() +
42+
File.separator +
43+
application.getString(R.string.add_enc_exchange_set_app_name)
44+
}
45+
46+
// Paths to ENC data and hydrology resources
47+
private val encResourcesPath = provisionPath + application.getString(R.string.enc_res_dir)
48+
private val encDataPath = provisionPath + application.getString(R.string.enc_data_dir)
49+
50+
// Create an ENC exchange set from the local ENC data
51+
private val encExchangeSet = EncExchangeSet(listOf(encDataPath))
52+
private val encEnvironmentSettings: EncEnvironmentSettings = EncEnvironmentSettings
53+
54+
// Create an empty map, to be updated once ENC data is loaded
55+
var arcGISMap by mutableStateOf(ArcGISMap())
56+
57+
// Create a message dialog view model for handling error messages
58+
val messageDialogVM = MessageDialogViewModel()
59+
60+
init {
61+
// Provide ENC environment with location of ENC resources and configure SENC caching location
62+
encEnvironmentSettings.resourcePath = encResourcesPath
63+
encEnvironmentSettings.sencDataPath = application.externalCacheDir?.path
64+
65+
viewModelScope.launch {
66+
encExchangeSet.load().onSuccess {
67+
68+
// Calculate the combined extent of all datasets in the exchange set
69+
val exchangeSetExtent: Envelope? = encExchangeSet.extentOrNull()
70+
71+
// Set the map to the oceans basemap style, and viewpoint to the exchange set extent
72+
arcGISMap = ArcGISMap(BasemapStyle.ArcGISOceans).apply {
73+
exchangeSetExtent?.let {
74+
initialViewpoint = Viewpoint(exchangeSetExtent)
75+
}
76+
}
77+
78+
encExchangeSet.datasets.forEach { encDataset ->
79+
// Create a layer for each ENC dataset and add it to the map
80+
val encCell = EncCell(encDataset)
81+
val encLayer = EncLayer(encCell)
82+
arcGISMap.operationalLayers.add(encLayer)
83+
84+
encLayer.load().onFailure { err ->
85+
messageDialogVM.showMessageDialog(
86+
"Error loading ENC layer",
87+
err.message.toString()
88+
)
89+
}
90+
}
91+
}.onFailure { err ->
92+
messageDialogVM.showMessageDialog(
93+
"Error loading ENC exchange set",
94+
err.message.toString()
95+
)
96+
}
97+
}
98+
}
99+
}
100+
101+
/**
102+
* Get the combined extent of every dataset in the exchange set.
103+
*/
104+
private fun EncExchangeSet.extentOrNull(): Envelope? {
105+
var extent: Envelope? = null
106+
107+
datasets.forEach { dataset ->
108+
if (extent == null) {
109+
extent = dataset.extent
110+
}
111+
112+
if (extent != null && dataset.extent != null) {
113+
// Update the combined extent of the exchange set if geometry engine returns non-null
114+
extent = GeometryEngine.combineExtentsOrNull(extent!!, dataset.extent!!) ?: extent
115+
}
116+
}
117+
return extent
118+
}

0 commit comments

Comments
 (0)