Working with the ArcIMS API  

Querying, Selecting, and Buffering

 

Querying the content of a spatial data source provides an application user with the ability to interact and utilize attributes, feature geometry, and image information in the same or a related data source.   The .NET ArcIMS API enables a developer to query both feature layers and image layers exposed in an Image or ArcMap service.   Feature layers can be queried using one of three methods:

  1. Attribute only.   An attribute query is defined using SQL (Structured Query Language) in a where clause.  The SQL statement uses fields and associated values or value ranges within the queried layer to filter returned content.
  2. Spatial only.  The intersection between user-defined feature geometry and features within a data layer determine returned content. 
  3. Attribute and Spatial.  Both attributes and feature geometry are used to query a data layer and determine returned content.   

Returned content can take the form of attribute data or a map image.  Map image content can be further defined by either displaying a subset of an existing layer or creating a new layer to display selected features.  In all cases, the query process can be enhanced by using a buffer to further refine returned content.

Querying Feature Layers

The ESRI.ArcGIS.ADF.IMS.Carto.Layer namespace contains three primary classes used to query feature layers: Filter, QueryParameters and FeatureLayer.   Filter defines both the attribute and spatial component in a query.   The attribute component is modified using the Filter.WhereExpression property. 

[C#]
Filter filter = new Filter();
filter.WhereExpression = "CITY_NAME = 'Phoenix'";

The spatial component is modified by setting the Filter.Geometry property to feature geometry created using classes in the ESRI.ArcGIS.ADF.Web.Geometry namespace: Envelope, Point, Multipoint, Polyline, and Polygon.   How a Filter is implemented determines what type of content is returned.   If a Filter is associated with QueryParameters, it will return filtered attributes, otherwise it will be used to filter features rendered in a map image.  In all cases, the Filter will be applied to a feature layer via a property or method on the FeatureLayer class. 

[C#]
Filter filter = new Filter();
Envelope envelope = new Envelope(-119, 32, -113, 35);
filter.Geometry = envelope;

 

Display a subset of features in a Map

To subset features in a feature layer and render them in a map, apply the filter to the FeatureLayer directly via the FeatureLayer.Filter property.  Note that the renderer defined for the feature layer in the map service will be used to render features in the map.

[C#]
FeatureLayer featurelayer = (FeatureLayer) layer;
Filter filter = new Filter();
filter.WhereExpression = "CITY_NAME = 'Phoenix'";
Envelope envelope = new Envelope(-119, 32, -113, 35);
filter.Geometry = envelope;
featurelayer.Filter = filter;
mapview.Draw();
 

Return attributes of a subset of features

To return the attributes associated with a subset of features in a feature layer, create a QueryParameters instance, set its QueryFilter property to a Filter, and call the FeatureLayer.Query() method.  A FeatureTable containing attributes and feature geometry is returned.  The Filter.SubFields property determines the fields in the FeatureTable.  By default, the subfields specified in the map service configuration file will dictate which fields are returned.  Note that the FeatureTable class extends from common ADO.NET System.Data.DataTable class, therefore it can be utilized any other DataTable in .NET.  For example, it can be bound to a DataGrid or GridView control via the Source property or iterated through its data values using an Enumerator retrieved via the GetEnumerator() method.

[C#]
FeatureLayer featurelayer = (FeatureLayer) layer;
Filter filter = new Filter();
filter.WhereExpression = "CITY_NAME = 'Phoenix'";
Envelope envelope = new Envelope(-119, 32, -113,35);
filter.Geometry = envelope;
QueryParameters queryparams = new QueryParameters();
queryparams.QueryFilter = filter; 
FeatureTable featuretable = featurelayer.Query(queryparams);


Return geometry associated with features

By default, an attribute query will not return feature or envelope geometry.  Enable these capabilities by working with a set of properties on a QueryParameters instance. Set the following properties to true to return the appropriate geometry when querying a feature layer:  

Property Geometry Returned
ReturnGeometries Feature geometry
ReturnEnvelope Envelope of each feature returned in the query
ReturnGlobalEnvelope Envelope of all features returned in the query

* Geometry types returned are in the ESRI.ArcGIS.ADF.IMS.Geometry namespace.

Return a feature count

To return the number of features selected, use the FeatureLayer.GetFeatureCount() method.  The method has two parameters: a filter and SelectionBuffer.  The SelectionBuffer (discussed below), can be used to define buffer properties and further refine the request for a count of features.  If a buffer does not need to be used, the second parameter can be set to null.

[C#]
SelectionBuffer selectionbuffer = new SelectionBuffer(flayer, "");
selectionbuffer.Distance = 100;
int featurecount = flayer.GetFeatureCount(filter, selectionbuffer);

 

Iterate through a subset of features

For performance reasons, it may be necessary to limit the number of queried features to a managable portion.   Note that the number of features queried, and number of fields for each feature, increases the amount of time needed by ArcIMS to process the transaction.   The maximum number of feature attributes returned via a query can be 1) set on the ArcIMS server or 2) set by the client. 

To limit the number of features requested from an ArcIMS service via the ArcIMS API (a client to ArcIMS), use the QueryParameter.FeatureLimit property and FeatureLayer.Query() method.  The FeatureLimit property will set the maximum number of feature attributes returned from querying a feature layer.  The Query() method is overridden to include a reference to the id value of the first feature to return.  ArcIMS maintains a unique id for each feature in a feature layer exposed in a service.  The unique id is determined by the physical location of a data row in the source dataset.  Note that the list of feature ids for a feature layer is one-based, thus the first row (feature) in a dataset has an id value of 1.  The order of features can only be changed in the underlying dataset, it cannot be changed via a where expression statement (for example, ORDER BY).  

[C#]

QueryParameters queryparams = new QueryParameters(filter); 
int FEATURE_LIMIT = 10;
queryparams.FeatureLimit = FEATURE_LIMIT; 
int BEGIN_RECORD = 1; 
FeatureTable featuretable; 
DataTable mergetable = new DataTable(); 
do { 
 featuretable = featurelayer.Query(queryparams, BEGIN_RECORD); 
 mergetable.Merge(featuretable);
 BEGIN_RECORD += FEATURE_LIMIT; 
} while (featuretable.HasMore);
 

Display Selected Features in a Map

To display a subset of queried features as a selection in a map, a new FeatureLayer is created to store the selected features.  The FeatureLayer.CreateSelectionLayer() method uses a filter, renderer, and layer id to create a new FeatureLayer to display selected features.  Note that a new renderer must be created for the new FeatureLayer to display the selected features.  The layer id should consist of a unique string used to identify the new FeatureLayer from other layers in the map service.

[C#]
FeatureLayer featurelayer = (FeatureLayer) layer;
Filter filter = new Filter();
filter.WhereExpression = "CITY_NAME = 'Phoenix'";
Envelope envelope = new Envelope(-119, 32, -113, 35);
filter.Geometry = envelope;
SimpleRenderer simplerenderer = new SimpleRenderer(); SimpleMarkerSymbol sms = new SimpleMarkerSymbol(); sms.Color = System.Drawing.Color.Yellow; simplerenderer.Symbol = sms;

FeatureLayer selectionlayer = featurelayer.CreateSelectionLayer(filter, simplerenderer, "myselectionid"); mapview.Layers.Add(selectionlayer); mapview.Draw();
 

Buffering

A buffer is defined as the area within a specified distance around a feature.  The query process implemented by the AXL Object API can be enhanced by using buffers on selected features or feature geometry.  Buffers are generated to:

  1. Display a buffer in a map.
  2. Return buffer geometry. 
  3. Display features selected by the buffer in a map. 
  4. Return attributes of features selected by a buffer. 
The ESRI.ArcGIS.ADF.IMS.Carto.Layer namespace contains two classes used to generate buffers: DisplayBuffer and SelectionBuffer.  In general, DisplayBuffer is used to display the buffer within a map.  SelectionBuffer is used to either display features selected by a buffer in a map, or return attributes of features selected by a buffer.   Both require setting their Distance property to a valid value in map units.  By default, map units are set within a map service, however they can be modified by setting the Units property. 

Display a buffer within a map

The FeatureLayer.CreateBufferLayer() method is used to generate a FeatureLayer containing buffer geometry.  The buffer is generated on the feature layer that calls the CreateBufferLayer() method.  The method requires four parameters: a Filter, DisplayBuffer, Renderer and string.  The Filter defines the attribute and/or spatial component used to select features on which a buffer will be created.  DisplayBuffer stores the buffer specific information such as distance and map units.  The Renderer defines how the buffer will be rendered in the map.  The string defines a unique layer id for the new FeatureLayer.  Once the new FeatureLayer is created, it must be added to the map to be visible.

[C#]
FeatureLayer featurelayer = (FeatureLayer) layer;
Filter filter = new Filter();
filter.WhereExpression = "CITY_NAME = 'Phoenix'";
Envelope envelope = new Envelope(-119, 32, -113, 35);
filter.Geometry = envelope;

DisplayBuffer displaybuffer = new DisplayBuffer();
displaybuffer.Distance = 200;
displaybuffer.Units = BufferUnits.Miles;

SimpleRenderer bufferrenderer = new SimpleRenderer();
SimpleFillSymbol sfs = new SimpleFillSymbol();
sfs.Color = System.Drawing.Color.Yellow; 
sfs.Transparency = 50.0;
bufferrenderer.Symbol = sfs;

FeatureLayer bufferlayer = featurelayer.CreateBufferLayer(filter, displaybuffer, bufferrenderer, "mybuffer");
mapview.Layers.Add(bufferlayer);
mapview.Draw();
 

Return buffer geometry

To return the geometry of a buffer, use a SelectionBuffer without a target layer.  Create a QueryParameters instance, set its QueryFilter property to a Filter which selects the features on which to construct a buffer.  Set the QueryParameter.SelectionBuffer property to the SelectionBuffer instance without the target layer defined and call the FeatureLayer.Query() method.   The FeatureTable returned contains the buffer geometry in a single column named "#SHAPE#".   If only one buffer is created, the FeatureTable will contain only one row. 

[C#]
FeatureLayer featurelayer = (FeatureLayer) layer;
Filter filter = new Filter();
filter.WhereExpression = "CITY_NAME = 'Phoenix'";

SelectionBuffer selectionbuffer = new SelectionBuffer();
selectionbuffer.Distance = 200;
selectionbuffer.Units = BufferUnits.Miles;

QueryParameters queryparams = new QueryParameters();
queryparams.QueryFilter = filter;
queryparams.SelectionBuffer = selectionbuffer;
queryparams.ReturnGeometries = true;

FeatureTable featuretable = featurelayer.Query(queryparams);

 

Display features selected by the buffer in a map

The FeatureLayer.CreateBufferSelectionLayer() method is used to generate a FeatureLayer containing features selected by a buffer.  The buffer is generated on the feature layer  that calls the CreateBufferSelectionLayer() method and can select features in the same layer or a different feature layer.  The feature layer in which the selection occurs is called the target layer.  The CreateBufferSelectionLayer() method requires four parameters: a Filter, SelectionBuffer, Renderer, and string.  The Filter defines the attribute and/or spatial component used to select features on which a buffer will be created.   The SelectionBuffer defines the target layer and an optional target layer where clause, in addition to buffer distance and units.  The target layer where clause can be used to further refine to query on the target layer.  The Renderer defines how the selected features will be displayed, so its symbol type must be appropriate for the selected feature type.  For example, a marker symbol can be used to render point features, while a fill symbol cannot.  The string defines a unique layer id for the new FeatureLayer.   Once the new FeatureLayer is created, it must be added to the map to be visible.  

Note that when the buffer distance is set to 0, the inherent feature geometry of a feature layer can be used to evaluate spatial relationships in the same or another feature layer.

[C#]

FeatureLayer featurelayer = (FeatureLayer) layer; Filter filter = new Filter(); Filter.WhereExpression = "CITY_NAME = 'Phoenix'"; Envelope envelope = new Envelope(-119, 32, -113, 35); filter.Geometry = envelope;

FeatureLayer targetlayer = (FeatureLayer) layercollection.FindByName("States"); string targetwhere = "";

SelectionBuffer selectionbuffer = new SelectionBuffer(targetlayer, targetwhere); selectionbuffer.Distance = 200; selectionbuffer.Units = BufferUnits.Miles;

SimpleRenderer targetrenderer = new SimpleRenderer(); SimpleFillSymbol sfs = new SimpleFillSymbol(); sfs.Color = System.Drawing.Color.Yellow;  targetrenderer.Symbol = sfs;

FeatureLayer selectionlayer = featurelayer.CreateBufferSelectionLayer(filter, selectionbuffer, targetrenderer, "mybufferselection"); mapview.Layers.Add(selectionlayer); mapview.Draw();

 

Return attributes of features selected by a buffer

To return attributes associated with features selected using a buffer, create a QueryParameters instance, set its QueryFilter property to a Filter, set its SelectionBuffer property to a BufferSelection, and call the FeatureLayer.Query() method.   A FeatureTable containing attributes and feature geometry is returned.  By default, subfields specified for the target layer in the map service configuration file will dictate which fields are returned.   The SelectionBuffer defines the target layer and an optional target layer where clause, in addition to buffer distance and units.  The target layer where clause can be used to further refine to query on the target layer. 

[C#]

FeatureLayer featurelayer = (FeatureLayer) layer; Filter filter = new Filter(); Filter.WhereExpression = "CITY_NAME = 'Phoenix'"; Envelope envelope = new Envelope(-119, 32, -113, 35); filter.Geometry = envelope;

FeatureLayer targetlayer = (FeatureLayer) layercollection.FindByName("States"); string targetwhere = "";

SelectionBuffer selectionbuffer = new SelectionBuffer(targetlayer, targetwhere); selectionbuffer.Distance = 200; selectionbuffer.Units = BufferUnits.Miles;

 

QueryParameters queryparams = new QueryParameters();

queryparams.QueryFilter = filter;

queryparams.SelectionBuffer = selectionbuffer;

FeatureTable featuretable = featurelayer.Query(queryparams)

 

Selection Tolerance

Often when querying features in a map using geometry (such as an extent box or a point via a mouse click) the application developer must account for user error.  For example, an application user uses the mouse to click on a map and select features in a layer.  However, due to imprecision in the usability of the application (such as converting pixel to map coordinates or lack of user visibility) the features are not selected.  Another scenario involves using graphic or user-defined geometry to select features in a feature layer.  For example, a user may want to locate all of the features within a distance from a geocoded point, represented as a graphic point within a map. 

The Filter class defines two properties to account for these situation: Tolerance and ToleranceUnits.   If the Filter.Geometry property has been set to a valid Geometry object, the Tolerance property will define the distance around the geometry in map units defined by the Units property.  In essence, this constructs a buffer around the Filter's geometry object.   The Filter can be used to subset and select features as well as return selected attributes (see sections above). 

 

Limitations

The filter for a target layer can only define a where clause via the SelectionBuffer.WhereExpression property.  Additional filter properties, such as Subfields and Geometry cannot be defined on a target layer. 

 

Querying Image (Raster) Layers

The ArcIMS API can be used to query image layers in an ArcIMS service.  The ImageLayer.Identify() method is used to return a collection of multibands within an image.  Each multiband can itself contain a set of bands.  Each band contains a single pixel value for a given coordinate location.

[C#]
Layer layer = layercollection.FindByName("sanfran.tif");
ImageLayer imagelayer = (ImageLayer) layer; 
Point point = new Point(-122.475, 37.648); 
MultibandCollection multicollection = imagelayer.Identify(point); 
IEnumerator iecollection = multicollection.GetEnumerator(); 
while (iecollection.MoveNext()) 
{ 
 Multiband multiband = (Multiband) iecollection.Current; 
 IEnumerator ieband = multiband.GetEnumerator(); 
 while (ieband.MoveNext()) 
 { 
  double bandvalue = (double) ieband.Current;
 } 
}