diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5ed6a367..6a7fb247 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] # ArcGIS Maps SDK for Kotlin version -arcgisMapsKotlinVersion = "300.0.0-4757" +arcgisMapsKotlinVersion = "300.0.0-4790" ### Android versions androidGradlePlugin = "8.12.1" diff --git a/samples/display-local-scene/README.md b/samples/display-local-scene/README.md new file mode 100644 index 00000000..e794280e --- /dev/null +++ b/samples/display-local-scene/README.md @@ -0,0 +1,38 @@ +# Display local scene + +Display a local scene with a topographic surface and 3D scene layer clipped to a local area. + +![Image of display local scene](display-local-scene.png) + +## Use case + +A `LocalSceneView` is a user interface that displays 3D basemaps and layer content described in an `ArcGisScene` with a local `SceneViewingMode`. + +Unlike a global scene which is drawn on a globe using a geographic coordinate system, a local scene is drawn on a flat surface and supports projected coordinate systems. They are generally used to view local data and are often clipped to a specific area of interest. Currently, `LocalSceneView` cannot display data provided by a global scene and `SceneView` cannot display data provided by a local scene. + +The `LocalSceneView` displays the clipped area of the local scene, supports user interactions such as pan and zoom, and provides access to the underlying scene data. + +## How to use the sample + +This sample displays a local scene clipped to an extent. Pan and zoom to explore the scene. + +## How it works + +1. Create a local scene object with the `ArcGISScene(arcGISTopographic, SceneViewingMode.local)` constructor. +2. Create an `ArcGISTiledElevationSource` object and add it to the local scene's base surface. +3. Create an `ArcGISSceneLayer` and add it to the local scene's operational layers. +4. Create an `Envelope` and set it to the `scene.clippingArea`, then enable clipping by setting `scene.isClippingEnabled` to `true`. +5. Create a `LocalSceneView` object to display the scene. +6. Set the initial viewpoint for the local scene. +7. Set the local scene to the local scene view. + +## Relevant API + +* ArcGISScene +* ArcGISSceneLayer +* ArcGISTiledElevationSource +* LocalSceneView + +## Tags + +3D, basemap, elevation, scene, surface diff --git a/samples/display-local-scene/README.metadata.json b/samples/display-local-scene/README.metadata.json new file mode 100644 index 00000000..aee5be5f --- /dev/null +++ b/samples/display-local-scene/README.metadata.json @@ -0,0 +1,33 @@ +{ + "category": "Scenes", + "description": "Display a local scene with a topographic surface and 3D scene layer clipped to a local area.", + "formal_name": "DisplayLocalScene", + "ignore": false, + "images": [ + "display-local-scene.png" + ], + "keywords": [ + "3D", + "basemap", + "elevation", + "scene", + "surface", + "ArcGISScene", + "ArcGISSceneLayer", + "ArcGISTiledElevationSource", + "LocalSceneView" + ], + "language": "kotlin", + "redirect_from": "", + "relevant_apis": [ + "ArcGISScene", + "ArcGISSceneLayer", + "ArcGISTiledElevationSource", + "LocalSceneView" + ], + "snippets": [ + "src/main/java/com/esri/arcgismaps/sample/displaylocalscene/MainActivity.kt", + "src/main/java/com/esri/arcgismaps/sample/displaylocalscene/screens/DisplayLocalSceneScreen.kt" + ], + "title": "Display local scene" +} diff --git a/samples/display-local-scene/build.gradle.kts b/samples/display-local-scene/build.gradle.kts new file mode 100644 index 00000000..90665097 --- /dev/null +++ b/samples/display-local-scene/build.gradle.kts @@ -0,0 +1,22 @@ +plugins { + alias(libs.plugins.arcgismaps.android.library) + alias(libs.plugins.arcgismaps.android.library.compose) + alias(libs.plugins.arcgismaps.kotlin.sample) + alias(libs.plugins.gradle.secrets) +} + +secrets { + // this file doesn't contain secrets, it just provides defaults which can be committed into git. + defaultPropertiesFileName = "secrets.defaults.properties" +} + +android { + namespace = "com.esri.arcgismaps.sample.displaylocalscene" + buildFeatures { + buildConfig = true + } +} + +dependencies { + // Only module specific dependencies needed here +} diff --git a/samples/display-local-scene/display-local-scene.png b/samples/display-local-scene/display-local-scene.png new file mode 100644 index 00000000..1986c963 Binary files /dev/null and b/samples/display-local-scene/display-local-scene.png differ diff --git a/samples/display-local-scene/src/main/AndroidManifest.xml b/samples/display-local-scene/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c96fb500 --- /dev/null +++ b/samples/display-local-scene/src/main/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/samples/display-local-scene/src/main/java/com/esri/arcgismaps/sample/displaylocalscene/MainActivity.kt b/samples/display-local-scene/src/main/java/com/esri/arcgismaps/sample/displaylocalscene/MainActivity.kt new file mode 100644 index 00000000..f5794289 --- /dev/null +++ b/samples/display-local-scene/src/main/java/com/esri/arcgismaps/sample/displaylocalscene/MainActivity.kt @@ -0,0 +1,53 @@ +/* Copyright 2025 Esri + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.esri.arcgismaps.sample.displaylocalscene + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import com.arcgismaps.ApiKey +import com.arcgismaps.ArcGISEnvironment +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme +import com.esri.arcgismaps.sample.displaylocalscene.screens.DisplayLocalSceneScreen + +class MainActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // authentication with an API key or named user is + // required to access basemaps and other location services + ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ACCESS_TOKEN) + + setContent { + SampleAppTheme { + DisplayLocalSceneApp() + } + } + } + + @Composable + private fun DisplayLocalSceneApp() { + Surface(color = MaterialTheme.colorScheme.background) { + DisplayLocalSceneScreen( + sampleName = getString(R.string.display_local_scene_app_name) + ) + } + } +} diff --git a/samples/display-local-scene/src/main/java/com/esri/arcgismaps/sample/displaylocalscene/screens/DisplayLocalSceneScreen.kt b/samples/display-local-scene/src/main/java/com/esri/arcgismaps/sample/displaylocalscene/screens/DisplayLocalSceneScreen.kt new file mode 100644 index 00000000..7fb59530 --- /dev/null +++ b/samples/display-local-scene/src/main/java/com/esri/arcgismaps/sample/displaylocalscene/screens/DisplayLocalSceneScreen.kt @@ -0,0 +1,104 @@ +/* Copyright 2025 Esri + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.esri.arcgismaps.sample.displaylocalscene.screens + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import com.arcgismaps.geometry.Envelope +import com.arcgismaps.geometry.Point +import com.arcgismaps.geometry.SpatialReference +import com.arcgismaps.mapping.ArcGISScene +import com.arcgismaps.mapping.ArcGISTiledElevationSource +import com.arcgismaps.mapping.BasemapStyle +import com.arcgismaps.mapping.Viewpoint +import com.arcgismaps.mapping.layers.ArcGISSceneLayer +import com.arcgismaps.mapping.view.Camera +import com.arcgismaps.mapping.view.SceneViewingMode +import com.arcgismaps.toolkit.geoviewcompose.LocalSceneView +import com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBar + +/** + * Main screen layout for the sample app + */ +@Composable +fun DisplayLocalSceneScreen(sampleName: String) { + Scaffold( + topBar = { SampleTopAppBar(title = sampleName) }, + content = { + Column( + modifier = Modifier + .fillMaxSize() + .padding(it), + ) { + val sceneLayer = remember { + ArcGISSceneLayer("https://www.arcgis.com/home/item.html?id=61da8dc1a7bc4eea901c20ffb3f8b7af") + } + + val elevationSource = remember { + ArcGISTiledElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer") + } + + val arcGISScene = remember { + ArcGISScene( + BasemapStyle.ArcGISTopographic, + SceneViewingMode.Local + ).apply { + operationalLayers.add(sceneLayer) + baseSurface.elevationSources.add(elevationSource) + + initialViewpoint = Viewpoint( + center = Point( + x = 19455026.8116, + y = -5054995.7415, + spatialReference = SpatialReference.webMercator() + ), + scale = 8314.6991, + camera = Camera( + locationPoint = Point( + x = 19455578.6821, + y = -5056336.2227, + z = 1699.3366, + spatialReference = SpatialReference.webMercator()), + heading = 338.7410, + pitch = 40.3763, + roll = 0.0, + ) + ) + clippingArea = Envelope( + xMin = 19454578.8235, + yMin = -5055381.4798, + xMax = 19455518.8814, + yMax = -5054888.4150, + spatialReference = SpatialReference.webMercator() + ) + isClippingEnabled = true + } + } + + LocalSceneView( + modifier = Modifier.fillMaxSize(), + scene = arcGISScene + ) + } + } + ) +} diff --git a/samples/display-local-scene/src/main/res/values/strings.xml b/samples/display-local-scene/src/main/res/values/strings.xml new file mode 100644 index 00000000..01b566c5 --- /dev/null +++ b/samples/display-local-scene/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Display local scene +