In ArcGIS, a three-dimensional map is known as a Scene. Introduced in ArcGIS Runtime SDK for .NET at version 10.2.6, scenes allow you to experience a more realistic view of the world by adding the third dimension to your data. Viewing data in 3D gives you new perspectives and can provide insights that would not be readily apparent from a 2D map of the same data.
Define a scene
ArcGIS Runtime SDK for .NET provides the SceneView and Scene controls for visualizing your data in three dimensions. These controls are very similar to the MapView and Map controls used for displaying two dimensional maps. Just as a map view contains a single map, a scene view contains a single scene. Like a map, a scene contains a collection of layers to display. In addition to layers that are unique for 3D mapping, a scene can contain the same types of layers you add to a map.
A scene view can contain only one scene at a time, however, multiple scene objects can be created and swapped out dynamically in the scene view as the application is running.
Define a scene with XAML
The following example shows XAML that defines a MapView and Map to display the World Street Map layer from ArcGIS Online. As you will see shortly, it only takes a couple minor alterations to this XAML to display the same map as a 3D scene.
<esri:MapView x:Name="MyMapView"> <esri:Map> <layers:ArcGISTiledMapServiceLayer ID="AGOLayer" ServiceUri="http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer" /> </esri:Map> </esri:MapView>
The following XAML displays the same layer in three dimensions using a SceneView and Scene.
<esri:SceneView x:Name="MySceneView"> <esri:Scene> <layers:ArcGISTiledMapServiceLayer ID="AGOLayer" ServiceUri="http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer" /> </esri:Scene> </esri:SceneView>
In this basic example, all you have to do to view the layer in three dimensions is change the Map element to Scene and the MapView element to SceneView in your XAML.
Define a scene with code
Instead of defining your scene and the layers it contains at design time using XAML, you can create it programmatically. Even if you create your initial scene using XAML, you can access it at run time to modify its characteristics or contents.
The following code example assumes that a container element (such as a Grid control) has been added to the page at design time and has been given the name MyGrid. This code creates a SceneView that contains a Scene with a single layer. The Scenewill be assigned to the Scene property of the SceneView, added to the Grid control and displayed in the application.
// create a new SceneView
var mySceneView = new Esri.ArcGISRuntime.Controls.SceneView();
// create a new Scene
var myScene = new Esri.ArcGISRuntime.Controls.Scene();
// create a new layer (give the layer an ID so it can be found later)
var uri = new Uri("http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer");
var baseLayer = new Esri.ArcGISRuntime.Layers.ArcGISTiledMapServiceLayer(uri);
baseLayer.ID = "BaseMap";
// add the layer to the Scene
// add the Scene to the SceneView
mySceneView.Scene = myScene;
// add the SceneView to the grid
Provide a surface for a scene
When you create a basic scene like those described in the previous examples, you will notice that although they are drawn in three dimensions, there is no topography (elevation) applied to the layers. The scene displays on a flat spherical surface without relief, so features like mountains and valleys appear as they would on a two-dimensional map. To apply topography (z-values) for layers displayed in your scene, you must define a set of datasets to act as a surface.
The abstract ElevationSource class represents a dataset containing elevation values that define a scene's surface, either from an online or local source. The ServiceElevationSource class is used to define an online source by pointing the ServiceUri property to a service containing elevation values, such as an ArcGIS Image Service. Elevation sources stored locally on the client are defined with the FileElevationSource class, that holds a collection of file paths to supported elevation source files.
The following formats are supported for a FileElevationSource:
- CIB1, 5, 10
- DTED0, 1, 2
- JPEG 2000
- SRTM1, 2
You can define your scene's surface using any combination of local and online elevation sources. The following example defines a surface by creating an ElevationSourceCollection consisting of both online and local sources.
<esri:SceneView x:Name="MySceneView"> <esri:Scene> <esri:Scene.Surface> <esri:ElevationSourceCollection> <esri:FileElevationSource x:Name="MyLocalElevationSource"> <esri:FilenameCollection> <x:String>D:\data\DTED\HI_Hawaii\DTED\DTED2\w155\n19.dt2</x:String> <x:String>D:\data\DTED\HI_Hawaii\DTED\DTED2\w156\n18.dt2</x:String> <x:String>D:\data\DTED\HI_Hawaii\DTED\DTED2\w156\n19.dt2</x:String> <x:String>D:\data\DTED\HI_Hawaii\DTED\DTED2\w156\n20.dt2</x:String> </esri:FilenameCollection> </esri:FileElevationSource> <esri:ServiceElevationSource ServiceUri="http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"/> </esri:ElevationSourceCollection> </esri:Scene.Surface> <layers:ArcGISTiledMapServiceLayer ID="AGOLayer" ServiceUri="http://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer" /> </esri:Scene> </esri:SceneView>
An individual ElevationSource can be enabled or disabled by setting its IsEnabled property. This gives you the ability to change the current surface used by your scene when your app is running.
Once a surface is in place, graphics layers and overlays can define how the surface is used to draw grapics. A GraphicsLayer or GraphicsOverlay can set the SurfacePlacement property of its associated LayerSceneProperties to one of the following values:
- Draped—Graphics draw directly on the surface, like laying a sheet over the topography defined by the surface. The resulting z-values on the draped layer are equal to the z-values of the underlying surface. Drawing streets that follow the underlying terrain is an example of draped placement.
- Absolute—Graphics draw using z-values defined for the layer. The z-values are independent of values provided by the surface. Drawing aircraft at their current altitude above sea level is an example of an absolute placement.
- Relative—Graphics draw using z-values defined for the layer using the surface z-value as the baseline. In other words, the z-values for the graphics are added to the z-values defined for the surface. Displaying the height of a power line network above the terrain is an example of using relative placement.
The following example shows XAML that sets the SurfacePlacement property of a graphics layer to Draped.
<layers:GraphicsLayer ID="DrapedGraphics"> <layers:GraphicsLayer.SceneProperties> <layers:LayerSceneProperties SurfacePlacement="Draped"/> </layers:GraphicsLayer.SceneProperties> </layers:GraphicsLayer>
Scene properties are ignored for graphics displayed in a map.
Query elevation in a scene
Scene locations, from a hit test or tapped event handler for example, provide elevation values as the z-coordinate of the returned MapPoint. It's important to remember that such results are only as good as the level of detail currently rendered in the scene, which can be quite coarse. The ability to query the most accurate elevation at a location is only supported for file elevation sources using the FileElevationSource.GetElevationAsync method.
The following example handles the SceneViewTapped event to get an elevation value from the local elevation source using GetElevationAsync. If a value is not available (the location is outside the extent of the local elevation source, for example), the elevation is read from the tap location z-coordinate (derived from the online elevation source).
private async void MySceneView_SceneViewTapped(object sender, MapViewInputEventArgs e)
var elevation = await MyLocalElevationSource.GetElevationAsync(e.Location);
elevation = e.Location.Z;
// ... do something with the elevation value here ...
Define display of the scene
The display of a Scene is determined by the position and properties of an observer, represented by the Camera class. The following characteristics of the camera are taken into account when displaying a three-dimensional scene.
- Location (target) on the surface (x,y coordinates)
- Heading from the camera location (on the surface) to the target
- Elevation (z-coordinate)
- Pitch (tilt) relative to the surface
See the Scene navigationtopic for information about mouse, touch, and keyboard navigation functionality that is built into the scene view control. Set camera position programmatically in the same topic has information and examples for defining the scene display with code and for synchronizing the display between a map and scene view in your app.
Additional SceneView properties and methods
The SceneView provides methods and properties to control things like the lighting of the scene, the available navigation operations, and the conversion of points between screen and geographic coordinate systems.
- IsShadowsEnabled—Whether or not shadows appear on the scene.
- ElevationExaggeration—The factor by which elevation values are exaggerated.
Elevation exaggeration is not applied only to the surface, but to the scene as a whole. Graphics draped on the scene surface will follow the new exaggerated surface, while graphics displayed in relative or absolute modes will be positioned by multiplying their z-values by the exaggeration factor.
- LightPoint—The position of the light source (sun, in other words) for the scene (x, y, z). For a realistic sun position based on the time, use the SetSunTime method. Use the LightPoint property to set the light position to a specific location (which may or may not reflect a realistic position for the sun).
- AmbientLight—The color of ambient light in the scene when shadows are enabled.
- SetSunTime—Sets the location of the sun in the sky (and resulting shadows on the scene, if enabled) using a DateTime object.
- LocationToScreen—Converts a point in geographic coordinates to screen coordinates (measured from the upper left corner of the scene). Optionally, you can return a ScreenPointVisibility value to describe the point's visibility (Visible, HiddenByEarth, HiddenByElevation, NotOnScreen).
- ScreenToLocation—Converts a point in display coordinates to geographic coordinates.
Share data between scene views
Sharing the same scene instance simultaneously among two or more scene views, or a layer instance simultaneously between scenes, is not supported and is likely to cause stability or performance issues. Working with graphics overlays or distinct feature layer instances that share the same feature service (ServiceFeatureTable) can cause the same issues and is also not supported in multiple scene views at the same time.
If you need to reuse a Scene in another SceneView, you should ensure that it is first removed from the previous control. The same technique can be used for reusing a layer instance between scenes.
The following example moves a layer from one scene to another.
var layer = MySceneView1.Scene.Layers["MyFeatureLayer"] as FeatureLayer;
MySceneView2.Scene.Layers.Add(layer); // add the layer to a new scene
MySceneView1.Scene.Layers.Remove(layer); // remove the layer from its original scene