Select to view content in your preferred language

SDK equivalent to Changing Layer's Elevation Properties "Features are" setting (At an Absolute Height, On the Ground, or Relative to the Ground)

419
2
11-06-2023 08:17 AM
ShaunHustad
New Contributor II

Pro 3.1.3 on Windows 11

I am able to convert a 2D Map into a 3D Local Scene using MapFactory.Instance.ConvertMap()

I then get the Ground Surface Layer, set the default Elevation Source Layer to visibility(false), add a raster layer as a new Elevation Source Layer to the Ground Surface.

Only a couple steps seem to be left:

  1. For each Layer in the Scene, Set the Elevation Properties setting (as it shows in Pro) "Features are" to "on the Ground", the default appears to be "at an Absolute Height"  I have spent way too many hours trying to find a workflow that accomplishes this.  I'm stumped.
  2. Change the Scene camera angle to an initial angle that shows the terrain relief (haven't attempted this yet, but if someone has a solution along with a solution for #1, that's great)
await QueuedTask.Run(() =>
{
    if (MapFactory.Instance.CanConvertMap(newMap, MapConversionType.SceneLocal))
    {
        newScene = MapFactory.Instance.ConvertMap(newMap, MapConversionType.SceneLocal, true);
        newScene.SetSpatialReference(SpatialReferences.WGS84);
        var groundSurfaceLayer = newScene.GetGroundElevationSurfaceLayer();
        groundSurfaceLayer.SetVerticalExaggeration(2.00);
        groundSurfaceLayer.SetCIMColor(CIMColor.NoColor());
        groundSurfaceLayer.Layers.FirstOrDefault().SetVisibility(false);
        var elevationLayerCreationParams = new ElevationLayerCreationParams(new Uri(System.IO.Path.Combine(CommonVariables.geoDatabasePath, CommonVariables.krigLayerName)));
        var eleSourceLayer = LayerFactory.Instance.CreateLayer<Layer>(elevationLayerCreationParams, groundSurfaceLayer);
        List<Layer> layerList = newScene.GetLayersAsFlattenedList().OfType<Layer>().ToList();
        foreach (Layer lyr  in layerList)
        {
            lyrName = lyr.Name;
        }
    }
});

 I did find the ArcGIS.Core.CIM.AltitudeMode Enum with the 3 possible values I'm looking for, and that is referenced by ArcGIS.Core.CIM.CIMAltitudeParams Class Mode Property... but I'm not seeing anywhere that CIMAltitudeParams is referenced.

0 Kudos
2 Replies
ShaunHustad
New Contributor II

UPDATE:

I found a way to set each Layer's Elevation Properties to "Relative to the Ground".  Still not sure how to set a Layer's Elevation Properties to "On the Ground"

await QueuedTask.Run(() =>
{
    if (MapFactory.Instance.CanConvertMap(newMap, MapConversionType.SceneLocal))
    {
        newScene = MapFactory.Instance.ConvertMap(newMap, MapConversionType.SceneLocal, true);
        newScene.SetSpatialReference(SpatialReferences.WGS84);
        var groundSurfaceLayer = newScene.GetGroundElevationSurfaceLayer();
        groundSurfaceLayer.SetVerticalExaggeration(2.00);
        groundSurfaceLayer.SetCIMColor(CIMColor.NoColor());
        groundSurfaceLayer.Layers.FirstOrDefault().SetVisibility(false);
        var elevationLayerCreationParams = new ElevationLayerCreationParams(new Uri(System.IO.Path.Combine(CommonVariables.geoDatabasePath, CommonVariables.krigLayerName)));
        var eleSourceLayer = LayerFactory.Instance.CreateLayer<Layer>(elevationLayerCreationParams, groundSurfaceLayer);
        var layerElevationSurface = new CIMLayerElevationSurface
        {
            ElevationSurfaceLayerURI = groundSurfaceLayer.URI,
        };
        List<Layer> layerList = newScene.GetLayersAsFlattenedList().OfType<Layer>().ToList();
        foreach (Layer lyr  in layerList)
        {
            if (lyr is FeatureLayer fl)
            {
                var cimLyr = fl.GetDefinition() as CIMFeatureLayer;
                cimLyr.LayerElevation = layerElevationSurface;
                fl.SetDefinition(cimLyr);
            }
            lyrName = lyr.Name;
        }
    }
});
0 Kudos
UmaHarano
Esri Regular Contributor

Hi,

If you pick the On the Ground option, the CIM definition of the layer looks like this:

 

  <LayerElevation xsi:type="typens:CIMLayerElevationSurface">
    <OffsetZ>0</OffsetZ>
    <ElevationSurfaceLayerURI>CIMPATH=Map/dc9328b7a8a849d78652499f3fa0ca9e.json</ElevationSurfaceLayerURI>
    <IsRelativeToScene>false</IsRelativeToScene>
  </LayerElevation>

 

In code, you can set these CIM values like this:

 

var layer = MapView.Active?.Map?.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
var surface = MapView.Active.Map.GetGroundElevationSurfaceLayer();
if (layer == null || surface == null)
return;
await QueuedTask.Run(() =>
{
//Get the layer's CIM Definition
var layerDefn = layer.GetDefinition() as CIMFeatureLayer;
//Set the LayerElevation properties
layerDefn.LayerElevation.ElevationSurfaceLayerURI = surface.URI;
layerDefn.LayerElevation.OffsetZ = 0;
layerDefn.LayerElevation.IsRelativeToScene = false;
//This is important - set the FeatureElevationExpression to an empty string
layerDefn.FeatureElevationExpression = string.Empty;
layer.SetDefinition(layerDefn);
});

 

 

If you pick the Relative to the Ground option, there is an additional attribute on the CIM that specifies the attribute to use for feature elevation.

 

<FeatureElevationExpression>Shape.Z</FeatureElevationExpression>

 

In code, you set this CIM value like this - (in addition to setting the LayerElevation mentioned above).

 

layerDefn.FeatureElevationExpression = "Shape.Z";

 

0 Kudos