arcgissamples\cartography\SimpleDispersalRenderer.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Simple dispersal renderer
arcgissamples\cartography\SimpleDispersalRenderer.java
/* Copyright 2015 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at <your ArcGIS install location>/DeveloperKit10.4/userestrictions.txt.
* 
*/
package arcgissamples.cartography;

import java.io.Externalizable;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.IOException;
import com.esri.arcgis.carto.IFeatureIDSet;
import com.esri.arcgis.carto.IFeatureRenderer;
import com.esri.arcgis.carto.SimpleRenderer;
import com.esri.arcgis.display.CharacterMarkerSymbol;
import com.esri.arcgis.display.IColor;
import com.esri.arcgis.display.IDisplay;
import com.esri.arcgis.display.IDisplayTransformation;
import com.esri.arcgis.display.ISymbol;
import com.esri.arcgis.display.RgbColor;
import com.esri.arcgis.display.SimpleMarkerSymbol;
import com.esri.arcgis.display.esriSimpleMarkerStyle;
import com.esri.arcgis.geodatabase.IFeature;
import com.esri.arcgis.geodatabase.IFeatureClass;
import com.esri.arcgis.geodatabase.IFeatureCursor;
import com.esri.arcgis.geodatabase.IQueryFilter;
import com.esri.arcgis.geometry.GeometryBag;
import com.esri.arcgis.geometry.IGeometryCollection;
import com.esri.arcgis.geometry.IPoint;
import com.esri.arcgis.geometry.IPolygon;
import com.esri.arcgis.geometry.IRelationalOperator;
import com.esri.arcgis.geometry.Point;
import com.esri.arcgis.geometry.Polygon;
import com.esri.arcgis.geometry.esriGeometryType;
import com.esri.arcgis.interop.AutomationException;
import com.esri.arcgis.system.ITrackCancel;
import com.esri.arcgis.system.esriArcGISVersion;
import com.esri.arcgis.system.esriDrawPhase;
import com.esri.arcgis.interop.extn.ArcGISExtension;
import com.esri.arcgis.system.IDocumentVersionSupportGEN;

@ArcGISExtension
public class SimpleDispersalRenderer implements IFeatureRenderer, Externalizable, IDocumentVersionSupportGEN {
  
  private double dispersalRatio;


  public SimpleDispersalRenderer() {
  
  }

  /**
   * canRender. Indicates if the specified feature class can be rendered on the given display.
   *
   * @param    featClass An reference to a com.esri.arcgis.geodatabase.IFeatureClass (in)
   * @param    display An reference to a com.esri.arcgis.display.IDisplay (in)
   * @return    The result
   * @exception java.io.IOException If there are interop problems.
   * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
   */
  public boolean canRender(IFeatureClass fc, IDisplay display) throws IOException, AutomationException {
    if (fc.getShapeType() == esriGeometryType.esriGeometryPoint)
      return true;
      else
      return false;
  }

  /**
   * prepareFilter. Prepares the query filter for the rendering process.Before an IFeatureRenderer::Draw occurs, you are given an opportunity with PrepareFilter to modify the query filter that produces the feature 
   * cursor.You must add into the filter any fields you need for your renderer.  
   *
   * @param     fc An reference to a com.esri.arcgis.geodatabase.IFeatureClass (in)
   * @param     queryFilter An reference to a com.esri.arcgis.geodatabase.IQueryFilter (in)
   * @exception java.io.IOException If there are interop problems.
   * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
   */
  public void prepareFilter(IFeatureClass fc, IQueryFilter qFilter)throws IOException, AutomationException {
  
  }

  /**
   * draw. Draws features from the specified cursor on the given display.This is the main method which will be called by ArcGIS framework.It is the job of your renderer to draw the feature layer in any way you  
   *  specify inside this method implementation. 
   *
   * @param     cursor An reference to a com.esri.arcgis.geodatabase.IFeatureCursor (in)
   * @param     drawPhase A com.esri.arcgis.system.esriDrawPhase constant (in)
   * @param     display An reference to a com.esri.arcgis.display.IDisplay (in)
   * @param     trackCancel An reference to a com.esri.arcgis.system.ITrackCancel (in)
   * @exception java.io.IOException If there are interop problems.
   * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
   */
  public void draw(IFeatureCursor featureCursor, int drawPhase, IDisplay display, ITrackCancel trackCancel) throws IOException,AutomationException {
    // do not draw features if display is null 
    if (display == null) {
    System.exit(0);
    } 

    //Step 1: 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);

    // Step 2: loop through the features and draw them using the display symbol

    //calculate the dispersal distance from the dispersal ratio
    //
    //The dispersal distance defines the minimum distance between two points
    IDisplayTransformation displayTrans = display.getDisplayTransformation();
    double dispersalDist = displayTrans.fromPoints(markerSym.getSize())* this.dispersalRatio;


    // build a GeometryBag to collect the already drawn locations.
    IGeometryCollection geomColl = new GeometryBag();
    IFeature feature = featureCursor.nextFeature();
    boolean bContinue = false;
    if (trackCancel != null)
    bContinue = trackCancel.esri_continue(); 
    do {
    IPoint featureLocation = (IPoint) feature.getShape();
    IPoint disperseLocation=new Point();
    IPolygon symPoly = new Polygon();

    //a. Find a disperse location that does not overlap on already drawn points

    //Note: placeFeature method is a utility method described below
    placeFeature(featureLocation, 0, geomColl, display, markerSym,
    disperseLocation, symPoly, dispersalDist); 

    //b. Draw the Symbol in the new disperse location
    display.drawPoint(disperseLocation);

    //c. Add the dispersed location's envelope to geometry bag
    geomColl.addGeometry(symPoly.getEnvelope(), null, null); 

    //d. Move on to next feature
    feature = featureCursor.nextFeature();
    if (trackCancel != null)
    bContinue = trackCancel.esri_continue();

    } while ((feature != null) && (bContinue == true));//end of loop
  }

  /**
   * getSymbolByFeature. Symbol used to draw the specified feature.
   *
   * @param    feature An reference to a com.esri.arcgis.geodatabase.IFeature (in)
   * @return    An reference to a com.esri.arcgis.display.ISymbol
   * @exception java.io.IOException If there are interop problems.
   * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
   */
  public ISymbol getSymbolByFeature(IFeature arg0) throws IOException,AutomationException {
    return null;
  }

  /**
   * isRenderPhase. Indicates if renderer uses the specified draw phase..We have 3 draw phases 1.esriDPAnnotation,2.esriDPGeography and 3.esriDPSelection.Generally its under esriDPGeography. 
   *
   * @param    drawPhase A com.esri.arcgis.system.esriDrawPhase constant (in)
   * @return    The result
   * @exception java.io.IOException If there are interop problems.
   * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
   */
  public boolean isRenderPhase(int drawPhase) throws IOException,AutomationException {
    //Need to render only in geography phase
    if (drawPhase == esriDrawPhase.esriDPGeography)
    return true;
    else
    return false;

  }

  /**
   * setExclusionSetByRef. An object reference to a temporary drawing exclusion set.
   *
   * @param     featureIDSet An reference to a com.esri.arcgis.carto.IFeatureIDSet (in)
   * @exception java.io.IOException If there are interop problems.
   * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
   */
  public void setExclusionSetByRef(IFeatureIDSet featureIDSet)throws IOException, AutomationException {
  
  }

  /**
   * Persist the properties that you want to store with your custom renderer in the write external method 
   *
   * @param  out The stream to write the object to 
   * @exception java.io.IOException If there are interop problems.
   */
  public void writeExternal(ObjectOutput out) throws IOException {
    out.writeDouble(this.dispersalRatio);

  }

  /**
   * Read the properties inside this method that you stored in the write external method for the custom renderer 
   *
   * @param  in The stream to read data from in order to restore the object 
   * @exception java.io.IOException If there are interop problems.
   */
  public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
     this.dispersalRatio = in.readDouble();    
  }

  /**
  * convertToSupportedObject. For every esriArcGISVersion for which you return false from 
  * isSupportedAtVersion, you should implement a suitable alternative in 
  * convertToSupportedObject. 
  * If you do not do this, you prevent users from saving a copy of a document to that version,
  * and the user may not receive any information about why their attempt to save 
  * a copy failed. Do not return a null reference either, as ArcGIS may attempt to 
  * apply this null reference to a property, which may cause the saved document to 
  * become corrupted.
  
  * @param docVersion An reference to a com.esri.arcgis.system.esriArcGISVersion(in)
  * @return An Object which is compatable to the version specified
  * @exception java.io.IOException If there are interop problems.
  * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
  */
  public Object convertToSupportedObject(int docVersion) throws IOException,AutomationException {
    SimpleRenderer simpleRend = new SimpleRenderer();
    SimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbol();
    simpleMarkerSymbol.setSize(8);
    simpleMarkerSymbol.setStyle(esriSimpleMarkerStyle.esriSMSDiamond);
    simpleRend.setSymbolByRef(simpleMarkerSymbol);
    return simpleRend;

  }

  /**
  * isSupportedAtVersion. This method is where you determine to which ArcGIS document versions 
  * your component can be persisted. Return true or false from this method depending on the 
  * document version indicated by the parameter passed in to this method. The parameter is an
  * esriArcGISVersion enumeration value.
  
  * @param docVersion An reference to a com.esri.arcgis.system.esriArcGISVersion(in)
  * @return The result
  * @exception java.io.IOException If there are interop problems.
  * @exception com.esri.arcgis.interop.AutomationException If the ArcObject component throws an exception.
  */
  public boolean isSupportedAtVersion(int docVersion) throws IOException,AutomationException {
    //Support all versions above or equal 9.3.
    if (docVersion >= esriArcGISVersion.esriArcGISVersion93)
    return true;
    else
    //convertToSupportedObject() method will be invoked if isSupportedAtVersion() method returns false
    return false;

  }
  public void placeFeature(IPoint point, int lTried,IGeometryCollection geomColl, IDisplay display, ISymbol symbol, IPoint disperseLocation, IPolygon symPoly, double dDispersalDist){
    try {
    // Calculate the place to try the feature
    if (lTried == 0) {
    disperseLocation.putCoords(point.getX(), point.getY());
    } else {
    double dDist = ((lTried - 1) / 4) * dDispersalDist;
    switch (lTried % 4) {
    case 0:
    disperseLocation.putCoords(point.getX() - dDist, point.getY());
    case 1:
    disperseLocation.putCoords(point.getX(), point.getY() + dDist);
    break;
    case 2:
    disperseLocation.putCoords(point.getX() + dDist, point.getY());
    break;
    case 3:
    disperseLocation.putCoords(point.getX(), point.getY() - dDist);
    break;
    }
    }
    // see if it intersects already drawn features
    IRelationalOperator relOp = (IRelationalOperator) geomColl;
    symbol.queryBoundary(display.getHDC(), display.getDisplayTransformation(), disperseLocation, symPoly);
    if (!relOp.disjoint(symPoly.getEnvelope()))

    // Try a new disperse Location
    placeFeature(point, lTried + 1, geomColl, display, symbol, disperseLocation, symPoly, dDispersalDist);
    else
    return;
    } catch (AutomationException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

  public double getDispersalRatio() {
    return dispersalRatio;
  }

  public void setDispersalRatio(double dispersalRatio) {
    this.dispersalRatio = dispersalRatio;
  }
}