How to zoom to selected features in globe


Summary
This topic explains how to zoom to the extent of selected features in one layer or multiple layers on a globe.


Zooming to selected features in globe

To zoom to selected features in globe, perform the following steps:
  1. Get all the layers present in the current globe document. Once you have a handle to the layers, loop through the layers and get all the features that are selected on the globe. See the following code example:
[C#]
ESRI.ArcGIS.GlobeCore.IGlobeDisplay globeDisplay = globe.GlobeDisplay;
ESRI.ArcGIS.Analyst3D.IScene scene = globeDisplay.Scene;
ESRI.ArcGIS.Carto.IEnumLayer enumLayer = scene.get_Layers(null, true);
[VB.NET]
Dim globeDisplay As ESRI.ArcGIS.GlobeCore.IGlobeDisplay = globe.GlobeDisplay
Dim scene As ESRI.ArcGIS.Analyst3D.IScene = globeDisplay.Scene
Dim enumLayer As ESRI.ArcGIS.Carto.IEnumLayer = scene.Layers(Nothing, True)
  1. Get a handle to the globe camera. The globe camera is used to zoom to the extent of the selected features on the globe. See the following code example:
[C#]
ESRI.ArcGIS.Analyst3D.ISceneViewer sceneViewer = globeDisplay.ActiveViewer;
ESRI.ArcGIS.Analyst3D.ICamera camera = sceneViewer.Camera;
ESRI.ArcGIS.GlobeCore.IGlobeCamera globeCamera = (ESRI.ArcGIS.GlobeCore.IGlobeCamera)
    camera; // Explicit cast.
[VB.NET]
Dim sceneViewer As ESRI.ArcGIS.Analyst3D.ISceneViewer = globeDisplay.ActiveViewer
Dim camera As ESRI.ArcGIS.Analyst3D.ICamera = sceneViewer.Camera
Dim globeCamera As ESRI.ArcGIS.GlobeCore.IGlobeCamera = CType(camera, ESRI.ArcGIS.GlobeCore.IGlobeCamera) ' Explicit Cast
  1. The extent of the layers is stored in an envelope and defines the area you need to zoom to. Make the envelope z-aware in cases when the features in the data have z-values or are draped on an elevation surface.
  2. Keep track of the extent of the layer where features are selected. This is important when zooming to selected point features. Getting the extent of the point features is shown in the following code example:
[C#]
ESRI.ArcGIS.Geometry.IEnvelope envelopeCls = new EnvelopeClass();
envelopeCls.SetEmpty();

ESRI.ArcGIS.Geometry.IEnvelope layersExtentCls = new EnvelopeClass();
layersExtentCls.SetEmpty();

ESRI.ArcGIS.Geometry.IZAware ZAware = (ESRI.ArcGIS.Geometry.IZAware)envelopeCls; 
    // Explicit cast.
ZAware.ZAware = (true);

ESRI.ArcGIS.Geodatabase.ISpatialFilter spatialFilterCls = new
    ESRI.ArcGIS.Geodatabase.SpatialFilterClass();
ESRI.ArcGIS.Geometry.ISpatialReference spatialReference = scene.SpatialReference;
[VB.NET]
Dim envelopeCls As ESRI.ArcGIS.Geometry.IEnvelope = New ESRI.ArcGIS.Geometry.EnvelopeClass
envelopeCls.SetEmpty()

Dim layersExtentCls As ESRI.ArcGIS.Geometry.IEnvelope = New ESRI.ArcGIS.Geometry.EnvelopeClass
layersExtentCls.SetEmpty()

Dim ZAware As ESRI.ArcGIS.Geometry.IZAware = CType(envelopeCls, ESRI.ArcGIS.Geometry.IZAware) ' Explicit Cast
ZAware.ZAware = (True)

Dim spatialFilterCls As ESRI.ArcGIS.Geodatabase.ISpatialFilter = New ESRI.ArcGIS.Geodatabase.SpatialFilterClass
Dim spatialReference As ESRI.ArcGIS.Geometry.ISpatialReference = scene.SpatialReference
  1. Before looping through all the layers, define a Boolean to keep track of any selected features in the layers and reset the counter to get the first layer stored in IEnumLayer. See the following code example:
[C#]
bool haveFeatures = false;

enumLayer.Reset();
[VB.NET]
Dim haveFeatures As System.Boolean = False

enumLayer.Reset()
  1. To loop through the layers, use the while loop. If no layers are present, break out of the code. See the following code example:
[C#]
ESRI.ArcGIS.Carto.ILayer layer;

while ((layer = enumLayer.Next()) != null)
{
    if (layer == null)
        break;
[VB.NET]
Dim layer As ESRI.ArcGIS.Carto.ILayer
layer = enumLayer.Next()
While layer IsNot Nothing
  1. Get the feature selection set for each layer as shown in the following code example. After getting the selection set, loop through individual features using the feature cursor, and store the geometry in the envelope.
The important thing to note is that you are trying to zoom to a number of selected features. If there are multiple features in the same feature class, keep updating the envelope of the extent by using the IEnvelope.Union method.
[C#]
ESRI.ArcGIS.Carto.IFeatureLayer featureLayer = (ESRI.ArcGIS.Carto.IFeatureLayer)
    layer; // Explicit cast.
ESRI.ArcGIS.Carto.IFeatureSelection featureSelection = 
    (ESRI.ArcGIS.Carto.IFeatureSelection)layer; // Explicit cast.
ESRI.ArcGIS.Geodatabase.ISelectionSet selectionSet = featureSelection.SelectionSet;
ESRI.ArcGIS.Geodatabase.IFeatureClass featureClass = featureLayer.FeatureClass;

string shapeField = featureClass.ShapeFieldName;
spatialFilterCls.GeometryField = shapeField;
spatialFilterCls.set_OutputSpatialReference(shapeField, spatialReference);

ESRI.ArcGIS.Geodatabase.ICursor cursor;
selectionSet.Search(spatialFilterCls, true, out cursor);
ESRI.ArcGIS.Geodatabase.IFeatureCursor featureCursor = 
    (ESRI.ArcGIS.Geodatabase.IFeatureCursor)cursor; // Explicit cast.

bool getLayerExtent = true;
ESRI.ArcGIS.Geodatabase.IFeature feature;

while ((feature = featureCursor.NextFeature()) != null)
{
    ESRI.ArcGIS.Geometry.IGeometry geometry = feature.Shape;
    ESRI.ArcGIS.Geometry.IEnvelope featureExtent = geometry.Envelope;
    envelopeCls.Union(featureExtent);

    haveFeatures = true;

    if (getLayerExtent)
    {
        ESRI.ArcGIS.Geodatabase.IGeoDataset geoDataset = 
            (ESRI.ArcGIS.Geodatabase.IGeoDataset)featureLayer; // Explicit cast.

        if (geoDataset != null)
        {
            ESRI.ArcGIS.Geometry.IEnvelope layerExtent = geoDataset.Extent;
            layersExtentCls.Union(layerExtent);
        }
        getLayerExtent = false;
    }
}

}
[VB.NET]
Dim featureLayer As ESRI.ArcGIS.Carto.IFeatureLayer = CType(layer, ESRI.ArcGIS.Carto.IFeatureLayer) ' Explicit Cast
Dim featureSelection As ESRI.ArcGIS.Carto.IFeatureSelection = CType(layer, ESRI.ArcGIS.Carto.IFeatureSelection) ' Explicit Cast
Dim selectionSet As ESRI.ArcGIS.Geodatabase.ISelectionSet = featureSelection.SelectionSet
Dim featureClass As ESRI.ArcGIS.Geodatabase.IFeatureClass = featureLayer.FeatureClass

Dim shapeField As System.String = featureClass.ShapeFieldName
spatialFilterCls.GeometryField = shapeField
spatialReference = spatialFilterCls.OutputSpatialReference(shapeField)

Dim cursor As ESRI.ArcGIS.Geodatabase.ICursor = Nothing
selectionSet.Search(spatialFilterCls, True, cursor)
Dim featureCursor As ESRI.ArcGIS.Geodatabase.IFeatureCursor = CType(cursor, ESRI.ArcGIS.Geodatabase.IFeatureCursor) ' Explicit Cast

Dim getLayerExtent As System.Boolean = True
Dim feature As ESRI.ArcGIS.Geodatabase.IFeature

feature = featureCursor.NextFeature

While (feature) IsNot Nothing
    Dim geometry As ESRI.ArcGIS.Geometry.IGeometry = feature.Shape
    Dim featureExtent As ESRI.ArcGIS.Geometry.IEnvelope = geometry.Envelope
    envelopeCls.Union(featureExtent)
    
    haveFeatures = True
    
    If getLayerExtent Then
        Dim geoDataset As ESRI.ArcGIS.Geodatabase.IGeoDataset = CType(featureLayer, ESRI.ArcGIS.Geodatabase.IGeoDataset) ' Explicit Cast
        If Not (geoDataset Is Nothing) Then
            Dim layerExtent As ESRI.ArcGIS.Geometry.IEnvelope = geoDataset.Extent
            layersExtentCls.Union(layerExtent)
        End If
        getLayerExtent = False
    End If
    
    feature = featureCursor.NextFeature ' Iterate through the next feature
End While
End If ' typeof
layer = enumLayer.Next() ' Iterate through the next layer
End While

Point feature datasets

In cases of point feature datasets—since the extent of a point is very small—use a special scenario so that you can zoom in closer to the point geometry. The following special scenarios are possible:

Scenario one

You can have the width and height of the envelope equal to zero. To do this, zoom to the layer extent and multiply it by a zoom factor (for example, 0.05) that reduces the extent of the zoom. Make sure that the zoom to envelope is centered at the point selected. See the following code example:
[C#]
double width = envelopeCls.Width;
double height = envelopeCls.Height;

if (width == 0.0 && height == 0.0)
{
    double dim = 1.0;
    bool bEmpty = layersExtentCls.IsEmpty;

    if (!bEmpty)
    {
        double layerWidth = layersExtentCls.Width;
        double layerHeight = layersExtentCls.Height;
        double layerDim = System.Math.Max(layerWidth, layerHeight) * 0.05;

        if (layerDim > 0.0)
            dim = System.Math.Min(1.0, layerDim);
    }

    double xMin = envelopeCls.XMin;
    double yMin = envelopeCls.YMin;

    ESRI.ArcGIS.Geometry.IPoint pointCls = new ESRI.ArcGIS.Geometry.PointClass();
    pointCls.X = xMin;
    pointCls.Y = yMin;
    envelopeCls.Width = dim;
    envelopeCls.Height = dim;
    envelopeCls.CenterAt(pointCls);
}
[VB.NET]
Dim Width As System.Double = envelopeCls.Width
Dim height As System.Double = envelopeCls.Height

If Width = 0 AndAlso height = 0 Then
    
    Dim Dim As System.Double = 1
    Dim bEmpty As System.Boolean = layersExtentCls.IsEmpty
    If Not bEmpty Then
        
        Dim layerWidth As System.Double = layersExtentCls.Width
        Dim layerHeight As System.Double = layersExtentCls.Height
        Dim layerDim As System.Double = System.Math.Max(layerWidth, layerHeight) * 0.05
        If layerDim > 0 Then
            Dim = System.Math.Min(1, layerDim)
        End If
        
    End If
    
    Dim xMin As System.Double = envelopeCls.XMin
    Dim yMin As System.Double = envelopeCls.YMin
    Dim pointCls As ESRI.ArcGIS.Geometry.IPoint = New ESRI.ArcGIS.Geometry.PointClass
    pointCls.X = xMin
    pointCls.Y = yMin
    envelopeCls.Width = Dim
    envelopeCls.Height = Dim
    envelopeCls.CenterAt(pointCls)

Scenario two

You can have the width or height of the envelope equal to zero. To do this, set the width and height of the envelope's zoom equal to the greater of the width or height of the extent of the selected point feature. See the following code example:
[C#]
else if (width == 0.0 || height == 0.0)
{
    double maxDim = System.Math.Max(width, height);
    envelopeCls.Width = maxDim;
    envelopeCls.Height = maxDim;
}
[VB.NET]
Else
    If Width = 0 OrElse height = 0 Then
        Dim maxDim As System.Double = System.Math.Max(Width, height)
        envelopeCls.Width = maxDim
        envelopeCls.Height = maxDim
    End If
End If
Once you have the extent of all the selected features, use the IGlobeCamera.SetToZoomToExtents() method. Pass the extent and the active viewer as the parameters. See the following code example:
[C#]
globeCamera.SetToZoomToExtents(envelopeCls, globe, sceneViewer);
sceneViewer.Redraw(true);
[VB.NET]
globeCamera.SetToZoomToExtents(envelopeCls, globe, sceneViewer)
sceneViewer.Redraw(True)






Development licensing Deployment licensing
Engine Developer Kit Engine: 3D Analyst
ArcGIS for Desktop Basic: 3D Analyst ArcGIS for Desktop Basic: 3D Analyst
ArcGIS for Desktop Standard: 3D Analyst ArcGIS for Desktop Standard: 3D Analyst
ArcGIS for Desktop Advanced: 3D Analyst ArcGIS for Desktop Advanced: 3D Analyst