How to implement custom feature renderers


Summary
Use custom feature renderers to control the way features are drawn in a feature layer. This topic briefly explains the essential steps and concepts to develop a custom feature renderer (that is, creating a Java class, annotating the class, implementing the methods, and deploying to ArcGIS).

In this topic


About implementing custom feature renderers

A feature renderer allows you to visualize a feature layer on a map by symbolizing the features in a layer. Standard feature renderers, such as SimpleRenderer, UniqueValueRenderer, BiUniqueValueRenderer, and so on, allow you to symbolize the features based on specific rules applied to the attributes of the feature layer. If none of the standard ArcGIS renderers meet your visualization requirements, and if you want to implement logic and control the way features are symbolized, you can implement custom feature renderers. This topic explains the major steps and concepts behind implementing a custom feature renderer. For a step by step walkthrough on implementing a custom feature renderer, see Building Custom Feature Renderer in Eclipse IDE.

Developing custom feature renderers

The custom feature renderers can be developed by creating simple Java class that implements IFeatureRenderer. The Java class must be annotated with @ArcGISExtension annotation and must override the methods of the IFeatureRenderer to suit your custom drawing. See the following code snippet.
[Java]
//Step 2: Annotate the class with @ArcGISExtension. 
@ArcGISExtension 
//Step 1: Create Java class that implements IFeatureRenderer.
public class FirstCustomRenderer implements IFeatureRenderer{
    //Step 3: Implement methods.
}
IFeatureRenderer is the minimum interface required to create a custom feature renderer. However, you can implement optional interfaces, particularly java.io.Externalizable, to persist the feature renderer in your map documents, IDocumentVersionSupportGEN to support version compatibility, and ILegendInfo to ensure the table of contents (TOC) and legends  appropriately. For more information, see Getting started with a custom feature renderer. The following section explains the methods that must be overridden in detail.

IFeatureRenderer methods

The following illustration shows the methods for IFeatureRenderer. You must override these methods to customize your feature renderer implementation:
The following illustration shows the sequence in which the IFeatureRenderer methods are invoked by the framework when rendering the feature layer.
 

canRender

The canRender method is the first method invoked by the ArcGIS framework. If the method did not return a value of true, the feature renderer will not be applied to the feature layer. The ArcGIS framework provides the feature class and the display references to which the feature renderer will be applied as arguments of the method. 
[Java]
public boolean canRender(IFeatureClass fc, IDisplay display)throws IOException,
    AutomationException{
    if (fc.getShapeType() == esriGeometryType.esriGeometryPoint)
        return true;
    else
        return false;
}

isRenderPhase

If all the conditions specified by the canRender method returned true, the ArcGIS framework invokes the isRenderPhase() method. The isRenderPhase() method lets you specify the draw phase in which the features must be rendered. The framework provides the draw phase as the method argument to determine whether to render the feature layer in the specified draw phase. If the method implementation did not return a value of true for the particular draw phase provided by the framework, it will not render the layer for that draw phase.
[Java]
public boolean isRenderPhase(int drawPhase){
    if (drawPhase == esriDrawPhase.esriDPGeography)
        return true;
    else
        return false;
}

setExclusionSetByRef

If the isRenderPhase() method returns a value of true for the particular draw phase, the ArcGIS framework invokes the setExclusionSetByRef method. The framework provides a IFeatureIDSet reference, which provides a list of features that need to be excluded from rendering.
Another recommended alternative to prevent features from drawing and from appearing in tables and query results, is to set a layer definition query using IFeatureLayerDefinition.

prepareFilter

The ArcGIS framework invokes the prepareFilter method after setExclusionSetByRef() method.  By default, the framework prepares a QueryFilter that queries the feature class for the feature ID and its shape fields only. The fields returned by the QueryFilter are used by the draw() method for rendering. However, your custom rendering and symbolization may be based on other fields of the feature class. In such a scenario, you must add those fields to the QueryFilter reference provided in the prepareFilter method.
The following code example shows how you can add all the fields for the feature class to the query filter:
[Java]
public void prepareFilter(IFeatureClass fc, IQueryFilter qFilter)throws IOException,
    AutomationException{

    //Get fields from the feature class.
    IFields fields = fc.getFields();

    //Add all fields to the query filter.
    for (int i = 0; i < fields.getFieldCount(); i++)
        qFilter.addField(fields.getField(i).getName());

    //If an exclusion set is specified by the setExclusionSetByRef() method, 
    //make sure the ObjectID field is present.

    if (exclusionSet != null){
        if (exclusionSet.getCount() > 0){
            qFilter.addField(fc.getOIDFieldName());
        }
    }
}

draw

The ArcGIS framework invokes IFeatureRenderer.draw() to draw features on the display after invoking the prepareFilter method. The framework provides the featureCursor, drawPhase, display, and trackCancel references as method arguments. The featureCursor reference is the result of the query filter made by the prepareFilter method. It includes the feature ID, shape fields by default. If you have specified additional fields in the prepareFilter method, the featurecursor would have fetched those fields too.  The draw() method of a renderer will be called for each phase specified in isRenderPhase() and for the selection phase by default.
The drawPhase method argument indicates the phase in which the draw() method is invoked. The trackCancel method argument allows you to track whether the Esc key was pressed to cancel the drawing during rendering the features. Tracking ESC key is important, since the renderer can slow down in situations with large datasets. It is a good practice to track the Esc key in the draw() method.
[Java]
//draw method of IFeatureRenderer that draws the feature.
public void draw(IFeatureCursor featureCursor, int drawPhase, IDisplay display,
    ITrackCancel trackCancel)throws IOException, AutomationException{

    //declare local variable to to track cancel
    boolean bContinue = false;
    // Do not draw features if there is no display or incorrect drawPhase.
    if (display == null || drawPhase != esriDrawPhase.esriDPGeography)
        return ;

    //Create and set the display symbol to represent the features.
    //Set the display symbol. 
    CharacterMarkerSymbol markerSym = new CharacterMarkerSymbol();
    markerSym.setCharacterIndex(72);
    markerSym.setSize(12.0);
    IColor redColor = new RgbColor();
    redColor.setRGB(0xFF0000);
    markerSym.setColor(redColor);
    display.setSymbol(markerSym);

    //Verify Track Cancel
    if (trackCancel != null)
        bContinue = trackCancel.esri_continue();

    //Loop through the features and draw them using the display symbol.
    IFeature feature = featureCursor.nextFeature();
    while ((feature != null) && (bcontinue == true)){
        IFeatureDraw featureDraw = (IFeatureDraw)feature;
        featureDraw.draw(drawPhase, display, markerSym, false, null,
            esriDrawStyle.esriDSNormal);
        feature = featureCursor.nextFeature();
        bContinue = trackCancel.esri_continue();
    }
}

getSymbolByFeature

The getSymbolByFeature() method returns the appropriate symbol to a feature. You must invoke the getSymbolByFeature() method within the draw() method explicitly.

What's Next

When the custom feature renderer is created, compile them and bundle the class files as a Java Archive (JAR) file. The custom feature renderer is then deployed to ArcGIS by placing the JAR file in the ArcGIS extension folder (<ArcGIS Install Dir>/java/lib/ext). An ArcGIS application (ArcGIS Engine, ArcMap, ArcCatalog, ArcGIS Server) recognizes and registers the  custom feature renderer when started, by the extension annotation. If the ArcGIS application is running, restart it after deploying the custom feature renderer. If there are code modifications in the custom feature renderer Java classes in the bundled JAR file, recreate and redeploy the JAR file, then restart the ArcGIS application after redeployment.
When deployed to ArcGIS, the custom feature renderer can be consumed in ArcGIS Engine and ArcGIS Server applications like other ArcGIS feature renderers. For more information about consuming custom feature renderers, see Consuming custom feature renderers. To consume the custom renderer in ArcGIS Desktop, create an associated property page for the custom feature renderer and deploy to ArcGIS. For more information about creating custom property pages for custom feature renderers, see How to implement custom property pages for custom feature renderers.


See Also:

Getting started with a custom feature renderer
Building custom feature renderers in Eclipse IDE
How to implement property pages for custom feature renderers
Implementing persistence and version compatibility
How to implement TOC legends for custom feature renderers




Development licensingDeployment licensing
Engine Developer KitEngine
ServerServer
ArcGIS for Desktop BasicArcGIS for Desktop Basic
ArcGIS for Desktop StandardArcGIS for Desktop Standard
ArcGIS for Desktop AdvancedArcGIS for Desktop Advanced