ProSnippets 3D Analyst Data - Esri/arcgis-pro-sdk GitHub Wiki

Language:              C#  
Subject:               3DAnalystData  
Contributor:           ArcGIS Pro SDK Team <[email protected]>  
Organization:          esri, http://www.esri.com  
Date:                  4/17/2025  
ArcGIS Pro:            3.5  
Visual Studio:         2022  
.NET Target Framework: .Net 8  

TIN

Open a TIN Dataset

public async Task OpenTinDataset()
{
  try
  {
    await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
    {
      string path = @"d:\Data\Tin";
      var fileConnection = new FileSystemConnectionPath(new Uri(path), FileSystemDatastoreType.Tin);

      using (FileSystemDatastore dataStore = new FileSystemDatastore(fileConnection))
      {
        // TIN is in a folder at d:\Data\Tin\TinDataset

        string dsName = "TinDataset";

        using (var dataset = dataStore.OpenDataset<ArcGIS.Core.Data.Analyst3D.TinDataset>(dsName))
        {

        }
      }
    });
  }
  catch (GeodatabaseNotFoundOrOpenedException exception)
  {
    // Handle Exception.
  }
}

Get a TIN Defintion

public async Task GetTinDatasetDefinition()
{
  try
  {
    await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
    {
      string path = @"d:\Data\Tin";
      var fileConnection = new FileSystemConnectionPath(new Uri(path), FileSystemDatastoreType.Tin);

      using (FileSystemDatastore dataStore = new FileSystemDatastore(fileConnection))
      {
        // TIN is in a folder at d:\Data\Tin\TinDataset

        string dsName = "TinDataset";

        using (var def = dataStore.GetDefinition<ArcGIS.Core.Data.Analyst3D.TinDatasetDefinition>(dsName))
        {

        }
      }
    });
  }
  catch (GeodatabaseNotFoundOrOpenedException exception)
  {
    // Handle Exception.
  }
}

Get Super Node Extent

var superNodeExtent = tinDataset.GetSuperNodeExtent();

Get Data Area

var dataArea = tinDataset.GetDataArea();

Element Counts

var nodeCount = tinDataset.GetNodeCount();
var outsideNodeCount = tinDataset.GetOutsideNodeCount();
var edgeCount = tinDataset.GetEdgeCount();
var outsideEdgecount = tinDataset.GetOutsideEdgeCount();
var triCount = tinDataset.GetTriangleCount();
var outsideTriCount = tinDataset.GetOutsideTriangleCount();

Tin Properties

var isEmpty = tinDataset.GetIsEmpty();
var hasHardEdges = tinDataset.HasHardEdges();
var hasSoftEdges = tinDataset.HasSoftEdges();

var isConstrainedDelaunay = tinDataset.UsesConstrainedDelaunay();

Access TIN Elements By Index

using (ArcGIS.Core.Data.Analyst3D.TinNode node = tinDataset.GetNodeByIndex(23))
{

}

using (ArcGIS.Core.Data.Analyst3D.TinEdge edge = tinDataset.GetEdgeByIndex(45))
{

}
using (ArcGIS.Core.Data.Analyst3D.TinTriangle triangle = tinDataset.GetTriangleByIndex(22))
{

}

Search for TIN Nodes

// search all nodes that intersect the data extent
using (ArcGIS.Core.Data.Analyst3D.TinNodeCursor nodeCursor = tinDataset.SearchNodes(null))
{
  while (nodeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinNode node = nodeCursor.Current)
    {

    }
  }
}

// search within an extent
ArcGIS.Core.Data.Analyst3D.TinNodeFilter nodeFilter = new ArcGIS.Core.Data.Analyst3D.TinNodeFilter();
nodeFilter.FilterEnvelope = envelope;
using (ArcGIS.Core.Data.Analyst3D.TinNodeCursor nodeCursor = tinDataset.SearchNodes(nodeFilter))
{
  while (nodeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinNode node = nodeCursor.Current)
    {

    }
  }
}

// search all "inside" nodes
nodeFilter = new ArcGIS.Core.Data.Analyst3D.TinNodeFilter();
nodeFilter.FilterType = ArcGIS.Core.Data.Analyst3D.TinFilterType.InsideDataArea;
using (ArcGIS.Core.Data.Analyst3D.TinNodeCursor nodeCursor = tinDataset.SearchNodes(nodeFilter))
{
  while (nodeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinNode node = nodeCursor.Current)
    {

    }
  }
}

// search for super nodes only
nodeFilter = new ArcGIS.Core.Data.Analyst3D.TinNodeFilter();
nodeFilter.FilterEnvelope = tinDataset.GetSuperNodeExtent();
nodeFilter.SuperNode = true;
using (ArcGIS.Core.Data.Analyst3D.TinNodeCursor nodeCursor = tinDataset.SearchNodes(nodeFilter))
{
  while (nodeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinNode node = nodeCursor.Current)
    {

    }
  }
}

Search for TIN Edges

// search all single edges that intersect the data extent
using (ArcGIS.Core.Data.Analyst3D.TinEdgeCursor edgeCursor = tinDataset.SearchEdges(null))
{
  while (edgeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinEdge edge = edgeCursor.Current)
    {

    }
  }
}

// search within an extent
ArcGIS.Core.Data.Analyst3D.TinEdgeFilter edgeFilter = new ArcGIS.Core.Data.Analyst3D.TinEdgeFilter();
edgeFilter.FilterEnvelope = envelope;
using (ArcGIS.Core.Data.Analyst3D.TinEdgeCursor edgeCursor = tinDataset.SearchEdges(edgeFilter))
{
  while (edgeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinEdge edge = edgeCursor.Current)
    {

    }
  }
}

// search all "inside" edges
edgeFilter = new ArcGIS.Core.Data.Analyst3D.TinEdgeFilter();
edgeFilter.FilterType = ArcGIS.Core.Data.Analyst3D.TinFilterType.InsideDataArea;
using (ArcGIS.Core.Data.Analyst3D.TinEdgeCursor edgeCursor = tinDataset.SearchEdges(edgeFilter))
{
  while (edgeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinEdge edge = edgeCursor.Current)
    {

    }
  }
}

// search for hard edges
edgeFilter = new ArcGIS.Core.Data.Analyst3D.TinEdgeFilter();
edgeFilter.FilterByEdgeType = true;
edgeFilter.EdgeType = ArcGIS.Core.Data.Analyst3D.TinEdgeType.HardEdge;
using (ArcGIS.Core.Data.Analyst3D.TinEdgeCursor edgeCursor = tinDataset.SearchEdges(edgeFilter))
{
  while (edgeCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinEdge edge = edgeCursor.Current)
    {

    }
  }
}

Search for TIN Triangles

// search all triangles that intersect the data extent
using (ArcGIS.Core.Data.Analyst3D.TinTriangleCursor triangleCursor = tinDataset.SearchTriangles(null))
{
  while (triangleCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinTriangle triangle = triangleCursor.Current)
    {

    }
  }
}

// search within an extent
ArcGIS.Core.Data.Analyst3D.TinTriangleFilter triangleFilter = new ArcGIS.Core.Data.Analyst3D.TinTriangleFilter();
triangleFilter.FilterEnvelope = envelope;
using (ArcGIS.Core.Data.Analyst3D.TinTriangleCursor triangleCursor = tinDataset.SearchTriangles(triangleFilter))
{
  while (triangleCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinTriangle triangle = triangleCursor.Current)
    {

    }
  }
}

// search all "inside" triangles
triangleFilter = new ArcGIS.Core.Data.Analyst3D.TinTriangleFilter();
triangleFilter.FilterType = ArcGIS.Core.Data.Analyst3D.TinFilterType.InsideDataArea;
using (ArcGIS.Core.Data.Analyst3D.TinTriangleCursor triangleCursor = tinDataset.SearchTriangles(triangleFilter))
{
  while (triangleCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.TinTriangle triangle = triangleCursor.Current)
    {

    }
  }
}

Access TIN Elements by MapPoint

// "identify" the closest node, edge, triangle
using (var nearestNode = tinDataset.GetNearestNode(mapPoint))
{
}

using (var nearestEdge = tinDataset.GetNearestEdge(mapPoint))
{
}
using (var triangle = tinDataset.GetTriangleByPoint(mapPoint))
{

}

// get the set of natural neighbours 
// (set of nodes that "mapPoint" would connect with to form triangles if it was added to the TIN)
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TinNode> naturalNeighbors = tinDataset.GetNaturalNeighbors(mapPoint);

// get the set of triangles whose circumscribed circle contains "mapPoint" 
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TinTriangle> triangles = tinDataset.GetTriangleNeighborhood(mapPoint);

TIN Nodes

// node coordinates
var coord3D = node.Coordinate3D;
var mapPoint = node.ToMapPoint();
// is the node "inside"
var isInsideNode = node.IsInsideDataArea;

// get all other nodes connected to "node" 
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TinNode> adjNodes = node.GetAdjacentNodes();

// get all edges that share "node" as a from node. 
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TinEdge> edges = node.GetIncidentEdges();

// get all triangles that share "node"
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TinTriangle> triangles = node.GetIncidentTriangles();

TIN Edges

// nodes of the edge
var nodes = edge.Nodes;

// edge geometry
var polyline = edge.ToPolyline();
// edge length
var length = edge.Length;
// is the edge "inside"
var isInsideEdge = edge.IsInsideDataArea;
// edge type - regular/hard/soft
var edgeType = edge.EdgeType;

// get next (clockwise) edge in the triangle
var nextEdge = edge.GetNextEdgeInTriangle();
// get previous (anti-clockwise) edge in the triangle
var prevEdge = edge.GetPreviousEdgeInTriangle();

// get opposite edge
var oppEdge = edge.GetNeighbor();

// get left triangle
var leftTriangle = edge.LeftTriangle;
// get right triangle
var rightTriangle = edge.RightTriangle;

TIN Triangles

// nodes, edges of the triangle
var triNnodes = triangle.Nodes;
var triEdges = triangle.Edges;

// triangle geometry
var polygon = triangle.ToPolygon();
// triangle length
var triLength = triangle.Length;
// triangle area 
var triArea = triangle.Area;
// is the triangle "inside"
var isInsideTriangle = triangle.IsInsideDataArea;

// triangle aspect and slope  (radians)
var aspect = triangle.Aspect;
var slope = triangle.Slope;

// get centroid
var centroid = triangle.GetCentroid();

// get normal
var normal = triangle.GetNormal();

// get adjacent triangles
var adjTriangles = triangle.GetAdjacentTriangles();

// get area of triangle that falls between the z values
double minZ = 1.0;
double maxZ = 3.0;
IReadOnlyList<Coordinate3D> coords = triangle.GetPointsBetweenZs(minZ, maxZ);

Create TinEditor from envelope

tinEditor = new TinEditor(envelope);
bool isInEditMode = tinEditor.IsInEditMode;  // isInEditMode = true

Create TinEditor from TinDataset

tinEditor = new TinEditor(tinDataset);
isInEditMode = tinEditor.IsInEditMode;  // isInEditMode = true

Create TinEditor from feature class

var fields = featureClass.GetDefinition().GetFields();

// Use the z-values from the geometries as the height field
Field heightField = fields.First(f => f.FieldType == FieldType.Geometry);

// Set the vertices from the geometries as TIN nodes
tinEditor = TinEditor.CreateFromFeatureClass(featureClass, null, heightField, null, TinSurfaceType.MassPoint);
isInEditMode = tinEditor.IsInEditMode;  // isInEditMode = true

// Use the object ids as tag values
Field tagField = fields.First(f => f.FieldType == FieldType.OID);

// Set the lines from the geometries as TIN edges
tinEditor = TinEditor.CreateFromFeatureClass(featureClass, null, heightField, tagField, TinSurfaceType.HardLine);
isInEditMode = tinEditor.IsInEditMode;  // isInEditMode = true

// Only use certain geometries in the TIN
QueryFilter filter = new QueryFilter()
{
  ObjectIDs = new List<long> { 2, 6, 7, 8, 9, 10, 14, 17, 21, 22 }
};
tinEditor = TinEditor.CreateFromFeatureClass(featureClass, filter, heightField, tagField, TinSurfaceType.HardLine);
isInEditMode = tinEditor.IsInEditMode;  // isInEditMode = true

Add geometries from feature class

var fields = featureClass.GetDefinition().GetFields();

// Use the z-values from the geometries as the height field
Field heightField = fields.First(f => f.FieldType == FieldType.Geometry);

// Set the vertices from the geometries as TIN nodes
tinEditor.AddFromFeatureClass(featureClass, null, heightField, null, TinSurfaceType.MassPoint);

// Use the object ids as tag values
Field tagField = fields.First(f => f.FieldType == FieldType.OID);

// Set the lines from the geometries as TIN edges
tinEditor.AddFromFeatureClass(featureClass, null, heightField, tagField, TinSurfaceType.HardLine);

// Only use certain geometries in the TIN
QueryFilter filter = new QueryFilter()
{
  ObjectIDs = new List<long> { 2, 6, 7, 8, 9, 10, 14, 17, 21, 22 }
};
tinEditor.AddFromFeatureClass(featureClass, filter, heightField, tagField, TinSurfaceType.HardLine);

Add a geometry

// Add a point as a node with no tag value at height = 10. Points and multipoints can only be added as mass points.
tinEditor.AddGeometry(point, TinSurfaceType.MassPoint, 0, 10);

// Add a z-aware multipoint as a nodes with tag value = 12 at height equal to the z-values of the points. Points and multipoints can only be added as mass points.
tinEditor.AddGeometryZ(multipointZ, TinSurfaceType.MassPoint, 12);

// Add a polyline as hard lines with tag value = 42 and height = 17.
tinEditor.AddGeometry(polyline, TinSurfaceType.HardLine, 42, 17);

// Add a z-aware polygon as an erase polygon with no tag value and height equal to the z-values of the vertices.
tinEditor.AddGeometryZ(polygonZ, TinSurfaceType.HardErase, 0);

Add mass points

// Add points with no tag value and height = 17.
// The points have the same spatial reference as the tin editor, so there is no need to provide it. 
tinEditor.AddMassPoints(points, 0, 17);

// Add coordinates as nodes with tag value = 42. The height will come from the z-values of the coordinates.
tinEditor.AddMassPointsZ(coordinate3Ds, 42);

// Add z-aware points with tag value = 21. The height will come from the z-values of the points.
// The points are in a different spatial reference than the tin editor, so we provide the spatial 
// reference of the points. The points will be projected to the spatial reference of the tin editor.
tinEditor.AddMassPointsZ(pointsZ, 21, SpatialReferenceBuilder.CreateSpatialReference(54004));

Add z-aware point

// Add a z-aware point with tag value = 56
tinEditor.AddPointZ(pointZ, 56);

Add polygons

// Add polygons with tagValue = 42 and height = 12. 
// The polygons are in a different spatial reference than the tin editor, so we provide the spatial 
// reference of the polygons. The polygons will be projected to the spatial reference of the tin editor.
tinEditor.AddPolygons(polygons, TinSurfaceType.ZLessSoftLine, 42, 12, SpatialReferenceBuilder.CreateSpatialReference(54004));

// Add z-aware polygons with no tag value. The height comes from the z-values of the vertices. 
// The polygons are in the same spatial reference as the tin editor, so there is no need to provide it.
tinEditor.AddPolygonsZ(polygonsZ, TinSurfaceType.HardLine, 0);

Add polylines

// Add polylines with tagValue = 42 and height = 12. 
// The polylines are in a different spatial reference than the tin editor, so we provide the spatial 
// reference of the polylines. The polylines will be projected to the spatial reference of the tin editor.
tinEditor.AddPolylines(polylines, TinSurfaceType.ZLessSoftLine, 42, 12, SpatialReferenceBuilder.CreateSpatialReference(54004));

// Add z-aware polylines with no tag value. The height comes from the z-values of the vertices. 
// The polylines are in the same spatial reference as the tin editor, so there is no need to provide it.
tinEditor.AddPolylinesZ(polylinesZ, TinSurfaceType.HardLine, 0);

Delete tag values

// Delete all edge tags
tinEditor.DeleteEdgeTagValues();

// Delete all node tags
tinEditor.DeleteNodeTagValues();

// Delete all triangle tags
tinEditor.DeleteTriangleTagValues();

Set tag values

// Set the tag value for edge #6
tinEditor.SetEdgeTagValue(6, 42);

// Set the tag value for node #8
tinEditor.SetNodeTagValue(8, 93);

// Set the tag value for triangle #9
tinEditor.SetTriangleTagValue(9, 17);

Delete node

// Delete node by index 
tinEditor.DeleteNode(7);

// Node indices start at 1.
try
{
  tinEditor.DeleteNode(0);
}
catch (ArgumentException)
{
  // Handle the exception
}

// Can't delete a super node (indices 1 - 4)
try
{
  tinEditor.DeleteNode(2);
}
catch (TinException)
{
  // Handle the exception
}

Delete nodes outside of data area

// Delete all data nodes that are outside the data area. Does not delete super nodes.
tinEditor.DeleteNodesOutsideDataArea();

Set edge type

// Set the type of edge #8
tinEditor.SetEdgeType(8, TinEdgeType.SoftEdge);

Set z-value of a node

// Set the z-value of node #10
tinEditor.SetNodeZ(10, 12.5);

Set the spatial reference

// Set the spatial reference
tinEditor.SetSpatialReference(SpatialReferenceBuilder.CreateSpatialReference(54004));

Set to constrained Delaunay

// Set the triangulation method to constrained Delaunay from this point forward
tinEditor.SetToConstrainedDelaunay();

Set triangle in/out of data area

// Set triangle #7 to be inside the data area
tinEditor.SetTriangleInsideDataArea(7);

// Set triangle #9 to be outside the data area
tinEditor.SetTriangleInsideDataArea(9);

Create a new TIN and save edits

// Create a new TIN 
tinEditor = new TinEditor(envelope);
tinEditor.AddMassPoints(points, 42, 13.7);

// Since the TIN doesn't exist on disk, you can't call SaveEdits.
// You must call SaveAs first.
try
{
  tinEditor.SaveEdits();
}
catch (TinException)
{
  // Handle the exception
}

// Since the TIN doesn't exist on disk, you can't call StopEditing(true).
// You must call SaveAs first.
try
{
  tinEditor.StopEditing(true);
}
catch (TinException)
{
  // Handle the exception
}

// Now save the newly created TIN to disk
tinEditor.SaveAs("C:\\Tin1", false);

// Delete a node
tinEditor.DeleteNode(7);

// Since the TIN now exists on disk you can call SaveEdits
tinEditor.SaveEdits();

// Delete another node
tinEditor.DeleteNode(11);

// Since the TIN now exists on disk, you can call StopEditing(true).
// The edits will be saved and the tin editor will be taken out of edit mode.
tinEditor.StopEditing(true);
bool isInEditMode = tinEditor.IsInEditMode; // isInEditMode = false

// Now if you try to make an edit, an exception is thrown because the editor is not in edit mode.
try
{
  tinEditor.AddPointZ(pointZ, 0);
}
catch (TinException)
{
  // Handle the exception
}

// Put the editor into edit mode.
tinEditor.StartEditing();
isInEditMode = tinEditor.IsInEditMode; // isInEditMode = true

// Now you can add the point
tinEditor.AddPointZ(pointZ, 0);

// Oops, you didn't really want to add the point. You want to stop editing and discard the unsaved edits
// since the last time the editor was put into edit mode. All previous saved edits remain.
tinEditor.StopEditing(false);

Edit an existing TIN

// Create an instance of TinEditor from an existing TinDataset
tinEditor = new TinEditor(tinDataset);
int numNodes = tinDataset.GetNodeCount();  // numNodes = 10
tinEditor.AddPointZ(pointZ, 7);

// Calling SaveEdits modifies the existing TIN
tinEditor.SaveEdits();
numNodes = tinDataset.GetNodeCount();  // numNodes = 11

// Adding twenty points
tinEditor.AddMassPoints(points, 10, 112.5);

// Calling SaveAs creates a new TIN on disk, and 
// the tin editor points to the new TIN.
string tinPath2 = "C:\\Tin2";
tinEditor.SaveAs(tinPath2, true);

tinEditor.StopEditing(true);
TinDataset tinDataset2 = OpenTin(tinPath2); // See https://github.com/esri/arcgis-pro-sdk/wiki/ProConcepts-3D-Analyst-Data#working-with-tin-data
numNodes = tinDataset2.GetNodeCount(); // numNodes = 31

// The edits still show up in the original TIN while it is in memory, but if you open it
// again you will see that it only has the edits that were saved before SaveAs was called.
numNodes = tinDataset.GetNodeCount(); // numNodes = 31

tinDataset = OpenTin(tinPath);
numNodes = tinDataset.GetNodeCount(); // numNodes = 11

Terrain

Open a Terrain

public async Task OpenTerrain()
{
  try
  {
    await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
    {
      string path = @"d:\Data\Terrain\filegdb_Containing_A_Terrain.gdb";
      var fileConnection = new FileGeodatabaseConnectionPath(new Uri(path));

      using (Geodatabase dataStore = new Geodatabase(fileConnection))
      {
        string dsName = "nameOfTerrain";

        using (var dataset = dataStore.OpenDataset<ArcGIS.Core.Data.Analyst3D.Terrain>(dsName))
        {
        }
      }
    });
  }
  catch (GeodatabaseNotFoundOrOpenedException exception)
  {
    // Handle Exception.
  }
}

Get a Terrain Definition

public async Task GetTerrainDefinition()
{
  try
  {
    await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
    {
      string path = @"d:\Data\Terrain\filegdb_Containing_A_Terrain.gdb";
      var fileConnection = new FileGeodatabaseConnectionPath(new Uri(path));

      using (Geodatabase dataStore = new Geodatabase(fileConnection))
      {
        string dsName = "nameOfTerrain";

        using (var terrainDef = dataStore.GetDefinition<ArcGIS.Core.Data.Analyst3D.TerrainDefinition>(dsName))
        {
          // get the feature class names that are used in the terrain
          var fcNames = terrainDef.GetFeatureClassNames();
        }
      }
    });
  }
  catch (GeodatabaseNotFoundOrOpenedException exception)
  {
    // Handle Exception.
  }
}

Get datasources from a Terrain

var dsCount = terrain.GetDataSourceCount();
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TerrainDataSource> dataSources = terrain.GetDataSources();
foreach (var ds in dataSources)
{
  var dsName = ds.DataSourceName;
  var surfaceType = ds.SurfaceType;
  var maxResolution = ds.MaximumResolution;
  var minResolution = ds.MinimumResolution;
}

Get Pyramid Level Information from a Terrain

var levelCount = terrain.GetPyramidLevelCount();
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.TerrainPyramidLevel> pyramidLevels = terrain.GetPyramidLevels();
foreach (var pyramidLevel in pyramidLevels)
{
  var resolution = pyramidLevel.Resolution;
  var maxScale = pyramidLevel.MaximumScale;
}

Get Tile Information from a Terrain

var tileInfo = terrain.GetTileProperties();
var colCount = tileInfo.ColumnCount;
var rowCount = tileInfo.RowCount;
var tileSize = tileInfo.TileSize;
var tileCount = tileInfo.TileCount;

Get Pyramid Information from a TerrainDefinition

var pyramidType = terrainDef.GetPyramidType();
var pyramidProps = terrainDef.GetPyramidWindowSizeProperties();

var method = pyramidProps.Method;
var threshold = pyramidProps.ZThreshold;
var strategy = pyramidProps.ZThresholdStrategy;

LAS Dataset

Open a LAS Dataset

public async Task OpenLasDataset()
{
  try
  {
    await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
    {
      string path = @"d:\Data\LASDataset";
      var fileConnection = new FileSystemConnectionPath(new Uri(path), FileSystemDatastoreType.LasDataset);

      using (FileSystemDatastore dataStore = new FileSystemDatastore(fileConnection))
      {
        string name = "utrecht_tile.lasd";      // can specify with or without the .lasd extension

        using (var dataset = dataStore.OpenDataset<ArcGIS.Core.Data.Analyst3D.LasDataset>(name))
        {

        }
      }
    });
  }
  catch (GeodatabaseNotFoundOrOpenedException exception)
  {
    // Handle Exception.
  }
}

Get a LAS Dataset Defintion

public async Task GetLasDatasetDefinition()
{
  try
  {
    await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
    {
      string path = @"d:\Data\LASDataset";
      var fileConnection = new FileSystemConnectionPath(new Uri(path), FileSystemDatastoreType.LasDataset);

      using (FileSystemDatastore dataStore = new FileSystemDatastore(fileConnection))
      {
        string name = "utrecht_tile.lasd";      // can specify with or without the .lasd extension

        using (var dataset = dataStore.GetDefinition<ArcGIS.Core.Data.Analyst3D.LasDatasetDefinition>(name))
        {

        }
      }
    });
  }
  catch (GeodatabaseNotFoundOrOpenedException exception)
  {
    // Handle Exception.
  }
}

Get Individual File Information from a LAS Dataset

var (lasFileCount, zLasFileCount) = lasDataset.GetFileCounts();
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.LasFile> fileInfo = lasDataset.GetFiles();
foreach (var file in fileInfo)
{
  var path = file.FilePath;
  var name = file.FileName;
  var ptCount = file.PointCount;
  var zMin = file.ZMin;
  var zMax = file.ZMax;
}

Get Surface Constraint information from a LAS Dataset

var constraintCount = lasDataset.GetSurfaceConstraintCount();
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.SurfaceConstraint> constraints = lasDataset.GetSurfaceConstraints();
foreach (var constraint in constraints)
{
  var dsName = constraint.DataSourceName;
  var wksPath = constraint.WorkspacePath;
  var heightField = constraint.HeightField;
  var surfaceType = constraint.SurfaceType;
}

Get classification codes / Returns from a LAS Dataset

var classCodes = lasDataset.GetUniqueClassCodes();
var returns = lasDataset.GetUniqueReturns();

Access LAS Points by ID

// access by ID
IReadOnlyList<ArcGIS.Core.Data.Analyst3D.LasPoint> pts = lasDataset.GetPointByID(123456);

pts = lasDataset.GetPointByID(123456, envelope);
ArcGIS.Core.Data.Analyst3D.LasPoint pt = pts.FirstOrDefault();

var coords = pt.Coordinate3D;
var mapPoint = pt.ToMapPoint();

Search LAS Points

// search all points
using (ArcGIS.Core.Data.Analyst3D.LasPointCursor ptCursor = lasDataset.SearchPoints(null))
{
  while (ptCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.LasPoint point = ptCursor.Current)
    {

    }
  }
}

// search within an extent
ArcGIS.Core.Data.Analyst3D.LasPointFilter pointFilter = new ArcGIS.Core.Data.Analyst3D.LasPointFilter();
pointFilter.FilterGeometry = envelope;
using (ArcGIS.Core.Data.Analyst3D.LasPointCursor ptCursor = lasDataset.SearchPoints(pointFilter))
{
  while (ptCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.LasPoint point = ptCursor.Current)
    {

    }
  }
}

// search within an extent and limited to specific classification codes
pointFilter = new ArcGIS.Core.Data.Analyst3D.LasPointFilter();
pointFilter.FilterGeometry = envelope;
pointFilter.ClassCodes = new List<int> { 4, 5 };
using (ArcGIS.Core.Data.Analyst3D.LasPointCursor ptCursor = lasDataset.SearchPoints(pointFilter))
{
  while (ptCursor.MoveNext())
  {
    using (ArcGIS.Core.Data.Analyst3D.LasPoint point = ptCursor.Current)
    {

    }
  }
}

Search using pre initialized arrays

// search all points
using (ArcGIS.Core.Data.Analyst3D.LasPointCursor ptCursor = lasDataset.SearchPoints(null))
{
  int count;
  Coordinate3D[] lasPointsRetrieved = new Coordinate3D[10000];
  while (ptCursor.MoveNextArray(lasPointsRetrieved, null, null, null, out count))
  {
    var points = lasPointsRetrieved.ToList();
  
    // ...
  }
}

// search within an extent
// use MoveNextArray retrieving coordinates, fileIndex and pointIds
ArcGIS.Core.Data.Analyst3D.LasPointFilter filter = new ArcGIS.Core.Data.Analyst3D.LasPointFilter();
filter.FilterGeometry = envelope;
using (ArcGIS.Core.Data.Analyst3D.LasPointCursor ptCursor = lasDataset.SearchPoints(filter))
{
  int count;
  Coordinate3D[] lasPointsRetrieved = new Coordinate3D[50000];
  int[] fileIndexes = new int[50000];
  double[] pointIds = new double[50000];
  while (ptCursor.MoveNextArray(lasPointsRetrieved, null, fileIndexes, pointIds, out count))
  {
    var points = lasPointsRetrieved.ToList();

  }
}
⚠️ **GitHub.com Fallback** ⚠️