Skip To Content

Add layers to your scene

In this topic

In general, you work with layers in a Scene the same way you work with them in a Map. All of the layer types that are supported for display in a Map can also be used in a Scene. They can be added at design time using XAML or at run time using code and are drawn in the order in which they are added.

Note:

Some layers, such as a SceneLayer, are exclusive to a Scene and cannot be added to a Map.

Layer scene properties

All layers supported for display in a (2D) map can also be added to a (3D) scene. The GraphicsLayer and GraphicsOverlay classes define a SceneProperties property to define behavior when rendering the layer in a scene. The property is set with a LayerSceneProperties object that defines the SurfacePlacement setting to control how the layer displays relative to the scene's elevation source (if one is defined).

See the Create a scene topic for more information and an example of defining an elevation source for a scene.

The LayerSceneProperties.SurfacePlacement property can be set 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.

<esri:GraphicsLayer ID="DrapedGraphics">
    <esri:GraphicsLayer.SceneProperties>
        <esri:LayerSceneProperties SurfacePlacement="Draped"/>
    </esri:GraphicsLayer.SceneProperties>
</esri:GraphicsLayer>

The following example creates the same layer using code.

var graphicsLayer = new GraphicsLayer();
graphicsLayer.ID = "DrapedGraphics";
graphicsLayer.SceneProperties.SurfacePlacement = SurfacePlacement.Draped;
MySceneView.Scene.Layers.Add(graphicsLayer);
Note:

Scene properties are ignored for graphics displayed in a Map.

Feature services may provide z-coordinate values for feature geometry, but these values are not used when displaying a feature layer in a scene. As a workaround, query the feature service (with ReturnZ = true) and add the results to a graphics layer with the appropriate surface placement. The following example queries a z-enabled feature service then displays the graphics in a scene.

// query for all graphics in the feature service, include z-coordinate values
var queryTask = new QueryTask(new Uri("http://myserver.com/arcgis/rest/services/FlightPaths/FeatureServer/0"));
var query = new Query("1=1");
query.ReturnZ = true;
var result = await queryTask.ExecuteAsync(query);

// create a graphics layer to show the graphics using absolute placement using the z values
var graphicsLayer = new GraphicsLayer();
graphicsLayer.SceneProperties.SurfacePlacement = SurfacePlacement.Absolute;

// build graphics from the results, symbolize with a red line
var lineSym = new SimpleLineSymbol { Color = Colors.Red, Style = SimpleLineStyle.Solid, Width = 5 };
graphicsLayer.GraphicsSource = from f in result.FeatureSet.Features select new Graphic(f.Geometry, lineSym);

// add the layer to the scene
MySceneView.Scene.Layers.Add(graphicsLayer);

3D layers

In addition to the familiar layers you may have used in your 2-dimensional maps, such as ArcGISTiledMapServiceLayer, GraphicsLayer, and so on, you can also add specialized 3D layers to your scene. With the 10.3 release of ArcGIS for Server, scene services are now available for delivering 3D content. These services support publishing and consuming large volumes of multipatch features, such as buildings for entire cityscapes. Scene services are created by publishing a scene using ArcGIS Pro.

These new services can be consumed in your ArcGIS Runtime SDK for .NET app. The following example uses a SceneLayer to show a scene service of buildings in Montreal, Canada.

<esri:SceneView x:Name="MySceneView" AmbientLight="Gray">     
    <esri:Scene>
        <esri:Scene.Surface>
            <esri:ServiceElevationSource ServiceUri="http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"
                                IsEnabled="True" ID="elevationLayer" />
        </esri:Scene.Surface>
        <esri:ArcGISTiledMapServiceLayer ID="AGOLayer"
                ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
        <esri:SceneLayer ID="MontrealBuildings" 
                ServiceUri="http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Montreal/SceneServer/layers/0" />
             
    </esri:Scene>
</esri:SceneView>

Buildings from a scene service displayed as a SceneLayer

KML layers

Keyhole Markup Language (KML) is an XML format for describing geographic features for visualization in two dimensional maps or three dimensional scenes. KML files use a .kml extension for plain KML text files or .kmz for compressed files. In your ArcGIS Runtime apps, you can use the KmlLayer to read and display geographic information from a .kml or .kmz file, which can be stored locally or accessed from an online source.

The following example shows XAML that defines a scene with a KML layer showing recent earthquakes.

<esri:SceneView x:Name="MySceneView">
    <esri:Scene>
        <esri:Scene.Surface>
            <esri:ServiceElevationSource 
                        ServiceUri="http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" />
        </esri:Scene.Surface>
        <esri:ArcGISTiledMapServiceLayer ID="AGOLayer"
                        ServiceUri="http://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer" />
        <esri:KmlLayer ID="QuakesKml" 
                        SourceUri="http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_week_age_link.kml">
        </esri:KmlLayer>
    </esri:Scene>
</esri:SceneView>

KML layer showing recent earthquakes

For more information, see the KML layers description in the Layer Types topic.

Layer initialization

Layers are initialized asynchronously when added to the scene. Attempting to access certain properties or operations before layers are initialized may throw an exception. For example, getting the spatial reference or camera position of the scene, or the name or extent of a layer. You can handle the LayerLoaded event on the SceneView to know if (and when) each layer loads successfully into the scene. The following example handles the LayerLoaded event and checks for a successful load of the streets layer (using its ID). Upon a successful load of the layer, the camera position is set for the scene.

private void MySceneView_LayerLoaded(object sender, LayerLoadedEventArgs e)
{
    if (e.LoadError == null && e.Layer.ID == "StreetMapLayer")
    {
        var mapPoint = new MapPoint(-122.40, 37.78, 210.0);
        MySceneView.SetViewAsync(new Esri.ArcGISRuntime.Controls.Camera(mapPoint, 340.0, 75.0), 1, true);
    }
}

You can also await the LayersLoadedAsync method to get the status of all layers after the scene view attempts to load them.

The following code example uses the LayersLoadedAsync method to await the loading of all the scene's layers. After loading is attempted for all layers, the InitializationException property populates for layers that encountered an exception while loading (otherwise, the property contains null). The following code would be called in the constructor for the page.

private async Task TryLoadLayers()
{
    var builder = new StringBuilder();
    await this.MySceneView.LayersLoadedAsync();
    foreach (var layer in MySceneView.Scene.Layers)
    {
        if (layer.InitializationException != null)
        {
            builder.AppendLine(layer.InitializationException.Message);
        }
    }

    // report layer initialization exception messages here ...
}

Related topics