Skip to content

ProSnippets SceneLayers

UmaHarano edited this page May 6, 2024 · 10 revisions
Language:              C#  
Subject:               SceneLayers  
Contributor:           ArcGIS Pro SDK Team <arcgisprosdk@esri.com>  
Organization:          esri, http://www.esri.com  
Date:                  4/22/2024  
ArcGIS Pro:            3.3  
Visual Studio:         2022  
.NET Target Framework: .Net 6  

Create a Scene Layer

var sceneLayerUrl = @"https://myportal.com/server/rest/services/Hosted/SceneLayerServiceName/SceneServer";
//portal items also ok as long as the portal is the current active portal...
//var sceneLayerUrl = @"https://myportal.com/home/item.html?id=123456789abcdef1234567890abcdef0";

await QueuedTask.Run(() =>
{
  //Create with initial visibility set to false. Add to current scene
  var createparams = new LayerCreationParams(new Uri(sceneLayerUrl, UriKind.Absolute))
  {
    IsVisible = false
  };

  //cast to specific type of scene layer being created - in this case FeatureSceneLayer
  var sceneLayer = LayerFactory.Instance.CreateLayer<Layer>(
           createparams, MapView.Active.Map) as FeatureSceneLayer;
  //or...specify the cast directly
  var sceneLayer2 = LayerFactory.Instance.CreateLayer<FeatureSceneLayer>(
           createparams, MapView.Active.Map);
  //ditto for BuildingSceneLayer, PointCloudSceneLayer, IntegratedMeshSceneLayer
  //...
});

Building Discipline Scene Layer

Get BuildingDisciplineSceneLayer Discipline

var bsl_discipline = MapView.Active.Map.GetLayersAsFlattenedList().OfType<BuildingDisciplineSceneLayer>().FirstOrDefault(l => l.Name == "Architectural");
var disciplineName = bsl_discipline.GetDiscipline();

Enumerate the Discipline Layers from a Building SceneLayer

public void QueryBuildingSceneLayer()
{
  var bldgLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<BuildingSceneLayer>().First();
  var disciplines = new Dictionary<string, BuildingDisciplineSceneLayer>();
  //A Building layer has two children - Overview and FullModel
  //Overview is a FeatureSceneLayer
  //Full Model is a BuildingDisciplineSceneLayer that contains the disciplines
  
  var fullModel = bldgLayer.FindLayers("Full Model").First() 
                                 as BuildingDisciplineSceneLayer;
  CollectDisciplineLayers(fullModel, disciplines);
  
}

internal void CollectDisciplineLayers(BuildingDisciplineSceneLayer disciplineLayer,
  Dictionary<string, BuildingDisciplineSceneLayer> disciplines)
{
  //collect information on the disciplines
  var name = disciplineLayer.Name;
  //At 2.x - var layerType =
  //      ((ISceneLayerInfo)disciplineLayer).SceneServiceLayerType.ToString();

  var discipline = disciplineLayer.GetDiscipline();
  //etc
  //TODO - use collected information

  disciplines.Add(discipline, disciplineLayer);

  //Discipline layers are composite layers too
  foreach (var childDiscipline in disciplineLayer.Layers
                      .OfType<BuildingDisciplineSceneLayer>())
  {
    //Discipline layers can also contain FeatureSceneLayers that render the
    //individual full model contents
    var content_names = string.Join(", ", childDiscipline.Layers
         .OfType<FeatureSceneLayer>().Select(fl => fl.Name));
    CollectDisciplineLayers(childDiscipline, disciplines);
  }
}

Building Scene Layer

Name of BuildingSceneLayer

var bsl = MapView.Active.Map.GetLayersAsFlattenedList()
                  .OfType<BuildingSceneLayer>().FirstOrDefault();
var scenelayerName = bsl.Name;

Query Building Scene Layer for available Types and Values

//Must be called on the MCT
//Retrieve the complete set of types and values for the building scene
//var bsl = ...;
//At 2.x - var dict = bsl.QueryAvailableFieldsAndValues();
var dict = bsl.GetAvailableFieldsAndValues();

//get a list of existing disciplines
var disciplines = dict.SingleOrDefault(
         kvp => kvp.Key == "Discipline").Value ?? new List<string>();

//get a list of existing categories
var categories = dict.SingleOrDefault(
         kvp => kvp.Key == "Category").Value ?? new List<string>();

//get a list of existing floors or "levels"
var floors = dict.SingleOrDefault(
         kvp => kvp.Key == "BldgLevel").Value ?? new List<string>();

Create a Default Filter and Get Filter Count

//Must be called on the MCT
//Creates a default filter on the building scene
//var bsl = ...;
var filter1 = bsl.CreateDefaultFilter();
var values = filter1.FilterBlockDefinitions[0].SelectedValues;
//values will be a single value for the type
//"CreatedPhase", value "New Construction"

//There will be at least one filter after "CreateDefaultFilter()" call
var filtersCount = bsl.GetFilters().Count;

Get all the Filters that Contain WireFrame Blocks

//var bsl = ...;
//Note: wire_frame_filters can be null in this example
var wire_frame_filters = bsl.GetFilters().Where(
  f => f.FilterBlockDefinitions.Any(
    fb => fb.FilterBlockMode == Object3DRenderingMode.Wireframe));
//substitute Object3DRenderingMode.None to get blocks with a solid mode (default)
//and...
//fb.FilterBlockMode == Object3DRenderingMode.Wireframe &&
//fb.FilterBlockMode == Object3DRenderingMode.None
//for blocks with both

Set and Clear Active Filter for BuildingSceneLayer

//Must be called on the MCT
//Note: Use HasFilter to check if a given filter id exists in the layer
//var bsl = ...;
if (bsl.HasFilter(filter1.ID))
  bsl.SetActiveFilter(filter1.ID);
var activeFilter = bsl.GetActiveFilter();

//Clear the active filter
bsl.ClearActiveFilter();

Get BuildingSceneLayer Filter ID and Filter

string filterID1 = filter1.ID;
var filter = bsl.GetFilter(filterID1);
//or via Linq
//var filter = bsl.GetFilters().FirstOrDefault(f => f.ID == filterID1);

Modify BuildingSceneLayer Filter Name and Description

//Must be called on the MCT
//var bsl = ...;
//var filter1 = bsl.GetFilter(filterID1);

filter1.Name = "Updated Filter Name";
filter1.Description = "Updated Filter description";
//At 2.x - bsl.SetFilter(filter1);
bsl.UpdateFilter(filter);

Create a Filter using Building Level and Category

//Must be called on the MCT

//refer to "Query Building Scene Layer for available Types and Values"
//...
//var bsl = ...;
//At 2.x
//var dict = bsl.QueryAvailableFieldsAndValues();

//var dict = bsl.GetAvailableFieldsAndValues();
//var categories = dict.SingleOrDefault(kvp => kvp.Key == "Category").Value;
//var floors = dict.SingleOrDefault(kvp => kvp.Key == "BldgLevel").Value;

//Make a new filter definition
var fd = new FilterDefinition()
{
  Name = "Floor and Category Filter",
  Description = "Example filter",
};
//Set up the values for the filter
var filtervals = new Dictionary<string, List<string>>();
filtervals.Add("BldgLevel", new List<string>() { floors[0] });
var category_vals = categories.Where(v => v == "Walls" || v == "Stairs").ToList() ?? new List<string>();
if (category_vals.Count() > 0)
{
  filtervals.Add("Category", category_vals);
}
//Create a solid block (other option is "Wireframe")
var fdef = new FilterBlockDefinition()
{
  FilterBlockMode = Object3DRenderingMode.None,
  Title = "Solid Filter",
  SelectedValues = filtervals//Floor and Category
};
//Apply the block
fd.FilterBlockDefinitions = new List<FilterBlockDefinition>() { fdef };
//Add the filter definition to the layer
//At 2.x - bsl.SetFilter(fd);
bsl.UpdateFilter(fd);
//Set it active. The ID is auto-generated
bsl.SetActiveFilter(fd.ID);

Modify BuildingSceneLayer Filter Block

//Must be called on the MCT
//Assuming retrieve filter ok
//var bsl = ...;
//var filter1 = bsl.GetFilter(...);

var filterBlock = new FilterBlockDefinition();
filterBlock.FilterBlockMode = Object3DRenderingMode.Wireframe;

var selectedValues = new Dictionary<string, List<string>>();
//We assume QueryAvailableFieldsAndValues() contains "Walls" and "Doors"
//For 'Category'
selectedValues["Category"] = new List<string>() { "Walls", "Doors" };
filterBlock.SelectedValues = selectedValues;

//Overwrite
filter1.FilterBlockDefinitions = new List<FilterBlockDefinition>() { filterBlock };
//At 2.x - bsl.SetFilter(filter1);
bsl.UpdateFilter(filter1);

Remove BuildingSceneLayer Filter

//var bsl = ...;
//Note: Use HasFilter to check if a given filter id exists in the layer
//Must be called on the MCT
if (bsl.HasFilter(filter1.ID))
  bsl.RemoveFilter(filter1.ID);
//Or remove all filters
bsl.RemoveAllFilters();

FeatureSceneLayer Editing

Determine if a FeatureSceneLayer supports editing

var featSceneLayer = MapView.Active.Map.GetLayersAsFlattenedList()
                   .OfType<FeatureSceneLayer>().FirstOrDefault();
if (!featSceneLayer.HasAssociatedFeatureService || 
    !featSceneLayer.IsEditable)
  return;//not supported

//TODO continue editing here...

Create a new Point feature in FeatureSceneLayer

//must support editing!
//var featSceneLayer = ... ;
if (!featSceneLayer.HasAssociatedFeatureService || 
    !featSceneLayer.IsEditable)
  return;
//Check geometry type...must be point in this example
if (featSceneLayer.ShapeType != esriGeometryType.esriGeometryPoint)
  return;

var editOp = new EditOperation()
{
  Name = "Create new 3d point feature",
  SelectNewFeatures = true
};

var attributes = new Dictionary<string, object>();
//mapPoint contains the new 3d point location
attributes.Add("SHAPE", mapPoint);
attributes.Add("TreeID", "1");
editOp.Create(featSceneLayer, attributes);
editOp.ExecuteAsync();//fyi, no await

Delete all the selected features in FeatureSceneLayer

//must support editing!
//var featSceneLayer = .... ;
if (!featSceneLayer.HasAssociatedFeatureService || 
    !featSceneLayer.IsEditable)
  return;

var delOp = new EditOperation()
{
  Name = "Delete selected features"
};
//Assuming we have a selection on the layer...
delOp.Delete(featSceneLayer, featSceneLayer.GetSelection().GetObjectIDs());
await delOp.ExecuteAsync();//await if needed but not required

Edit the attributes of a FeatureSceneLayer

//must support editing!
var featSceneLayer = MapView.Active.Map.GetLayersAsFlattenedList()
                   .OfType<FeatureSceneLayer>().FirstOrDefault();
if (!featSceneLayer.HasAssociatedFeatureService || 
    !featSceneLayer.IsEditable)
  return;

var ok = await QueuedTask.Run(() =>
{
  var editOp = new EditOperation()
  {
    Name = "Edit FeatureSceneLayer Attributes",
    SelectModifiedFeatures = true
  };
  //make an inspector
  var inspector = new Inspector();
  //get the attributes for the specified oid
  inspector.Load(featSceneLayer, oid);
  inspector["PermitNotes"] = "test";//modify
  editOp.Modify(inspector);
  return editOp.Execute();//synchronous flavor
});

FeatureSceneLayer

Name of FeatureSceneLayer

var featSceneLayer = MapView.Active.Map.GetLayersAsFlattenedList()
                 .OfType<FeatureSceneLayer>().FirstOrDefault();
var scenelayerName = featSceneLayer?.Name;

Get the Data Source type

//Must be called on the MCT
var dataSourceType = featSceneLayer?.GetDataSourceType() ?? 
                           SceneLayerDataSourceType.Unknown;
if (dataSourceType == SceneLayerDataSourceType.SLPK)
{
  //Uses SLPK - only cached attributes
}
else if (dataSourceType == SceneLayerDataSourceType.Service)
{
  //Hosted service - can have live attributes - check HasAssociatedFeatureService
}

Get the Associated Feature class

//var featSceneLayer = ....;
if (featSceneLayer.HasAssociatedFeatureService)
{
  //Must be called on the MCT
  using (var fc = featSceneLayer.GetFeatureClass())
  {
    //TODO query underlying feature class
  }
}

Get Field Definitions

//var featSceneLayer = ....;
await QueuedTask.Run(() =>
{
  //Get only the readonly fields
  var readOnlyFields = featSceneLayer.GetFieldDescriptions()
                              .Where(fdesc => fdesc.IsReadOnly);
  //etc
  
});

Set a Definition Query

//Must be called on the MCT
//var featSceneLayer = ...;
featSceneLayer.SetDefinitionQuery("Name = 'Ponderosa Pine'");

Select features via the MapView

//assume the geometry used in SelectFeaturesEx() is coming from a 
//map tool...
//
//SketchType = SketchGeometryType.Rectangle;
//SketchOutputMode = SketchOutputMode.Screen;

await QueuedTask.Run(() =>
{
  var result = MapView.Active.SelectFeaturesEx(geometry);
  //Get scene layers with selections
  //At 2.x - var scene_layers = result.Where(kvp => kvp.Key is FeatureSceneLayer);
  var scene_layers = result.ToDictionary<FeatureSceneLayer>();
  foreach (var kvp in scene_layers)
  {
    var scene_layer = kvp.Key as FeatureSceneLayer;
    var sel_oids = kvp.Value;
    //If there are attributes then get them
    if (scene_layer.HasAssociatedFeatureService)
    {
      var insp = new Inspector();
      foreach (var oid in sel_oids)
      {
        insp.Load(scene_layer, oid);
        //TODO something with retrieved attributes
      } 
    }
  }
});
 

Has Associated FeatureService

var featSceneLayer = MapView.Active.Map.GetLayersAsFlattenedList()
                     .OfType<FeatureSceneLayer>().First();
if (featSceneLayer.HasAssociatedFeatureService)
{
  //Can Select and Search...possibly edit

}

Search Rows on the FeatureSceneLayer

//var featSceneLayer = ...;
if (!featSceneLayer.HasAssociatedFeatureService)
  return;//Search and Select not supported

//Multipatch (Object3D) or point?
//var is3dObject = ((ISceneLayerInfo)featSceneLayer).SceneServiceLayerType 
//                                  == esriSceneServiceLayerType.Object3D;
var is3dObject = featSceneLayer.FeatureSceneLayerType == FeatureSceneLayerType.Object3D;
await QueuedTask.Run(() =>
{
  var queryFilter = new QueryFilter
  {
    WhereClause = "Name = 'Ponderosa Pine'",
    SubFields = "*"
  };

  int rowCount = 0;
  //or select... var select = featSceneLayer.Select(queryFilter)
  using (RowCursor rowCursor = featSceneLayer.Search(queryFilter))
  {
    while (rowCursor.MoveNext())
    {
      using (var feature = rowCursor.Current as Feature)
      {
        var oid = feature.GetObjectID();
        var shape = feature.GetShape();
        var attrib = feature["Name"];
        if (is3dObject)
        {
          //shape is a multipatch
        }
        else
        {
          //shape is a point
        }
        rowCount += 1;
      }

    }
  }

});

Hide Selected features and Show Hidden features

//var featSceneLayer = ...;
if (featSceneLayer.HasAssociatedFeatureService)
  return;//Search and Select not supported

await QueuedTask.Run(() =>
{
  QueryFilter qf = new QueryFilter()
  {
    ObjectIDs = new List<long>() { 6069, 6070, 6071 },
    SubFields = "*"
  };
  featSceneLayer.Select(qf, SelectionCombinationMethod.New);

  featSceneLayer.HideSelectedFeatures();
  var selectionCount = featSceneLayer.SelectionCount;

  featSceneLayer.ShowHiddenFeatures();
  selectionCount = featSceneLayer.SelectionCount;

});

Use MapView Selection SelectFeaturesEx or GetFeaturesEx

//var featSceneLayer = ...;
var sname = featSceneLayer.Name;

await QueuedTask.Run(() =>
{
  //Select all features within the current map view
  var sz = MapView.Active.GetViewSize();

  var c_ll = new Coordinate2D(0, 0);
  var c_ur = new Coordinate2D(sz.Width, sz.Height);
  //Use screen coordinates for 3D selection on MapView
  var env = EnvelopeBuilderEx.CreateEnvelope(c_ll, c_ur);

  //HasAssociatedFeatureService does not matter for SelectFeaturesEx
  //or GetFeaturesEx
  var result = MapView.Active.SelectFeaturesEx(env);
  //var result = MapView.Active.GetFeaturesEx(env);

  //The list of object ids from SelectFeaturesEx
  //At 2.x - var oids1 = result.Where(kvp => kvp.Key.Name == sname).First().Value;
  var oids1 = result.ToDictionary().Where(kvp => kvp.Key.Name == sname).First().Value;
  //TODO - use the object ids

  MapView.Active.Map.ClearSelection();
});

Use Select or Search with a Spatial Query

//var featSceneLayer = ...;
//var sname = featSceneLayer.Name;
await QueuedTask.Run(() =>
{
  if (!featSceneLayer.HasAssociatedFeatureService)
    return;//no search or select

  //Select all features within the current map view
  var sz = MapView.Active.GetViewSize();
  var map_pt1 = MapView.Active.ClientToMap(new System.Windows.Point(0, sz.Height));
  var map_pt2 = MapView.Active.ClientToMap(new System.Windows.Point(sz.Width, 0));

  //Convert to an envelope
  var temp_env = EnvelopeBuilderEx.CreateEnvelope(map_pt1, map_pt2, MapView.Active.Map.SpatialReference);

  //Project if needed to the layer spatial ref
  SpatialReference sr = null;
  using (var fc = featSceneLayer.GetFeatureClass())
  using (var fdef = fc.GetDefinition())
    sr = fdef.GetSpatialReference();

  var env = GeometryEngine.Instance.Project(temp_env, sr) as Envelope;

  //Set up a query filter
  var sf = new SpatialQueryFilter()
  {
    FilterGeometry = env,
    SpatialRelationship = SpatialRelationship.Intersects,
    SubFields = "*"
  };

  //Select against the feature service
  var select = featSceneLayer.Select(sf);
  if (select.GetCount() > 0)
  {
    //enumerate over the selected features
    using (var rc = select.Search())
    {
      while (rc.MoveNext())
      {
        using (var feature = rc.Current as Feature)
        {
          var oid = feature.GetObjectID();
          //etc.
        }
      }
    }
  }

  MapView.Active.Map.ClearSelection();

});

PointCloudSceneLayer

Name of PointCloudSceneLayer

var pcsl = MapView.Active.Map.GetLayersAsFlattenedList()
               .OfType<PointCloudSceneLayer>().FirstOrDefault();
var scenelayerName = pcsl?.Name;

Get Data Source type for PointCloudSceneLayer

//var pcsl = ...;
//At 2.x - ISceneLayerInfo slInfo = pcsl as ISceneLayerInfo;
//         SceneLayerDataSourceType dataSourceType = slInfo.GetDataSourceType();

SceneLayerDataSourceType dataSourceType = pcsl.GetDataSourceType();
if (dataSourceType == SceneLayerDataSourceType.Service)
{
  //TODO...
}
else if (dataSourceType == SceneLayerDataSourceType.SLPK)
{

}

Query all class codes and lables in the PointCloudSceneLayer

//Must be called on the MCT
//var pcsl = ...;
//At 2.x - Dictionary<int, string> classCodesAndLabels =
//                    pcsl.QueryAvailableClassCodesAndLabels();

Dictionary<int, string> classCodesAndLabels = 
                pcsl.GetAvailableClassCodesAndLabels();

Set a Filter for PointCloudSceneLayer

//Must be called on the MCT
//var pcsl = ...;
//Retrieve the available classification codes
//At 2.x - var dict = pcsl.QueryAvailableClassCodesAndLabels();
var dict = pcsl.GetAvailableClassCodesAndLabels();

//Filter out low noise and unclassified (7 and 1 respectively)
//consult https://pro.arcgis.com/en/pro-app/help/data/las-dataset/storing-lidar-data.htm
var filterDef = new PointCloudFilterDefinition()
{
  ClassCodes = dict.Keys.Where(c => c != 7 && c != 1).ToList(),
  ReturnValues = new List<PointCloudReturnType> { 
                         PointCloudReturnType.FirstOfMany }
};
//apply the filter
pcsl.SetFilters(filterDef.ToCIM());

Update the ClassFlags for PointCloudSceneLayer

//Must be called on the MCT
//var pcsl = ...;
var filters = pcsl.GetFilters();
PointCloudFilterDefinition fdef = null;
if (filters.Count() == 0)
{
  fdef = new PointCloudFilterDefinition()
  {
    //7 is "edge of flight line" - exclude
    ClassFlags = new List<ClassFlag> { 
       new ClassFlag(7, ClassFlagOption.Exclude) }
  };
}
else
{
  fdef = PointCloudFilterDefinition.FromCIM(filters);
  //keep any include or ignore class flags
  var keep = fdef.ClassFlags.Where(
         cf => cf.ClassFlagOption != ClassFlagOption.Exclude).ToList();
  //7 is "edge of flight line" - exclude
  keep.Add(new ClassFlag(7, ClassFlagOption.Exclude));
  fdef.ClassFlags = keep;
}
//apply
pcsl.SetFilters(fdef.ToCIM());

Get the filters for PointCloudSceneLayer

//Must be called on the MCT
//var pcsl = ...;
IReadOnlyList<CIMPointCloudFilter> updatedFilter = pcsl.GetFilters();
foreach (var filter in updatedFilter)
{
  //There is either 0 or 1 of each
  if (filter is CIMPointCloudReturnFilter returnFilter)
  {
    PointCloudFilterDefinition pcfl = PointCloudFilterDefinition.FromCIM(updatedFilter);
    List<PointCloudReturnType> updatedReturnValues = pcfl.ReturnValues;

  }
  if (filter is CIMPointCloudValueFilter classCodesFilter)
  {
    // do something
  }

  if (filter is CIMPointCloudBitFieldFilter classFlagsFilter)
  {
    // do something
  }
}

Clear filters in PointCloudSceneLayer

//Must be called on the MCT
//var pcsl = ...;
pcsl.ClearFilters();

Get PointCloudSceneLayer Renderer and RendererType

//Must be called on the MCT
//var pcsl = ...;
CIMPointCloudRenderer cimGetPCLRenderer = pcsl.GetRenderer();
//Can be one of Unknown, Stretch, ClassBreaks, UniqueValue, RGB
PointCloudRendererType pclRendererType = pcsl.RendererType;

Query PointCloudSceneLayer Renderer fields

//Must be called on the MCT
//var pcsl = ...;
//At 2.x - IReadOnlyList<string> flds = pcsl.QueryAvailablePointCloudRendererFields(
//                                     PointCloudRendererType.UniqueValueRenderer);
IReadOnlyList<string> flds = pcsl.GetAvailablePointCloudRendererFields(
                             PointCloudRendererType.UniqueValueRenderer);
var fldCount = flds.Count;

Create and Set a Stretch Renderer

//Must be called on the MCT
//var pcsl = ...;

//At 2.x - var fields = pcsl.QueryAvailablePointCloudRendererFields(
//                           PointCloudRendererType.StretchRenderer);

var fields = pcsl.GetAvailablePointCloudRendererFields(
                         PointCloudRendererType.StretchRenderer);
var stretchDef = new PointCloudRendererDefinition(
                          PointCloudRendererType.StretchRenderer)
{
  //Will be either ELEVATION or INTENSITY
  Field = fields[0]
};
//Create the CIM Renderer
var stretchRenderer = pcsl.CreateRenderer(stretchDef) 
                                   as CIMPointCloudStretchRenderer;
//Apply a color ramp
var style = Project.Current.GetItems<StyleProjectItem>()
                                .First(s => s.Name == "ArcGIS Colors");
var colorRamp = style.SearchColorRamps("").First();
stretchRenderer.ColorRamp = colorRamp.ColorRamp;
//Apply modulation
stretchRenderer.ColorModulation = new CIMColorModulationInfo()
{
  MinValue = 0,
  MaxValue = 100
};
//apply the renderer
pcsl.SetRenderer(stretchRenderer);

Create and Set a ClassBreaks Renderer

//Must be called on the MCT
//var pcsl = ...;

//At 2.x - var fields = pcsl.QueryAvailablePointCloudRendererFields(
//                          PointCloudRendererType.ClassBreaksRenderer);

var fields = pcsl.GetAvailablePointCloudRendererFields(
                     PointCloudRendererType.ClassBreaksRenderer);
var classBreakDef = new PointCloudRendererDefinition(
                          PointCloudRendererType.ClassBreaksRenderer)
{
  //ELEVATION or INTENSITY
  Field = fields[0]
};
//create the renderer
var cbr = pcsl.CreateRenderer(classBreakDef) 
                          as CIMPointCloudClassBreaksRenderer;
//Set up a color scheme to use
var style = Project.Current.GetItems<StyleProjectItem>()
                           .First(s => s.Name == "ArcGIS Colors");
var rampStyle = style.LookupItem(
  StyleItemType.ColorRamp, "Spectrum By Wavelength-Full Bright_Multi-hue_2")
                                                            as ColorRampStyleItem;
var colorScheme = rampStyle.ColorRamp;
//Set up 6 manual class breaks
var breaks = 6;
var colors = ColorFactory.Instance.GenerateColorsFromColorRamp(
                                            colorScheme, breaks);
var classBreaks = new List<CIMColorClassBreak>();
var min = cbr.Breaks[0].UpperBound;
var max = cbr.Breaks[cbr.Breaks.Count() - 1].UpperBound;
var step = (max - min) / (double)breaks;

//add in the class breaks
double upper = min;
for (int b = 1; b <= breaks; b++)
{
  double lower = upper;
  upper = b == breaks ? max : min + (b * step);
  var cb = new CIMColorClassBreak()
  {
    UpperBound = upper,
    Label = string.Format("{0:#0.0#} - {1:#0.0#}", lower, upper),
    Color = colors[b - 1]
  };
  classBreaks.Add(cb);
}
cbr.Breaks = classBreaks.ToArray();
pcsl.SetRenderer(cbr);

PointCloudSceneLayer Extended Properties

Edit Color Modulation

//Must be called on the MCT
//var pcsl = ...;
var def = pcsl.GetDefinition() as CIMPointCloudLayer;
//Get the ColorModulation off the renderer
var modulation = def.Renderer.ColorModulation;
if (modulation == null)
  modulation = new CIMColorModulationInfo();
//Set the minimum and maximum intensity as needed
modulation.MinValue = 0;
modulation.MaxValue = 100.0;
//apply back
def.Renderer.ColorModulation = modulation;
//Commit changes back to the CIM
pcsl.SetDefinition(def);

Edit The Renderer to use Fixed Size

//Must be called on the MCT
//var pcsl = ...;
var def = pcsl.GetDefinition() as CIMPointCloudLayer;

//Set the point shape and sizing on the renderer
def.Renderer.PointShape = PointCloudShapeType.DiskShaded;
var pointSize = new CIMPointCloudFixedSizeAlgorithm()
{
  UseRealWorldSymbolSizes = false,
  Size = 8
};
def.Renderer.PointSizeAlgorithm = pointSize;
//Commit changes back to the CIM
pcsl.SetDefinition(def);

Edit the Renderer to Scale Size

//Must be called on the MCT
//var pcsl = ...;
var def = pcsl.GetDefinition() as CIMPointCloudLayer;

//Set the point shape and sizing on the renderer
def.Renderer.PointShape = PointCloudShapeType.DiskFlat;//default
var scaleSize = new CIMPointCloudSplatAlgorithm()
{
  MinSize = 8,
  ScaleFactor = 1.0 //100%
};
def.Renderer.PointSizeAlgorithm = scaleSize;
//Commit changes back to the CIM
pcsl.SetDefinition(def);

Edit Density settings

//Must be called on the MCT
//var pcsl = ...;
var def = pcsl.GetDefinition() as CIMPointCloudLayer;
//PointsBudget - corresponds to Display Limit on the UI
// - the absolute maximum # of points to display
def.PointsBudget = 1000000;

//PointsPerInch - corresponds to Density Min --- Max on the UI
// - the max number of points per display inch to renderer
def.PointsPerInch = 15;
//Commit changes back to the CIM
pcsl.SetDefinition(def);

Home

ProSnippets: SceneLayers

Clone this wiki locally