arcgissamples\cartography\ColorBivariateRend.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Bivariate renderers
arcgissamples\cartography\ColorBivariateRend.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.IOException;

import com.esri.arcgis.carto.ClassBreaksRenderer;
import com.esri.arcgis.carto.IBivariateRenderer;
import com.esri.arcgis.carto.IClassBreaksRenderer;
import com.esri.arcgis.carto.IFeatureIDSet;
import com.esri.arcgis.carto.IFeatureRenderer;
import com.esri.arcgis.carto.ILegendGroup;
import com.esri.arcgis.carto.ILegendInfo;
import com.esri.arcgis.carto.ILegendItem;
import com.esri.arcgis.carto.LegendClass;
import com.esri.arcgis.carto.LegendGroup;
import com.esri.arcgis.display.AlgorithmicColorRamp;
import com.esri.arcgis.display.IDisplay;
import com.esri.arcgis.display.IFillSymbol;
import com.esri.arcgis.display.ISymbol;
import com.esri.arcgis.display.esriColorRampAlgorithm;
import com.esri.arcgis.geodatabase.IFeature;
import com.esri.arcgis.geodatabase.IFeatureClass;
import com.esri.arcgis.geodatabase.IFeatureCursor;
import com.esri.arcgis.geodatabase.IFeatureDraw;
import com.esri.arcgis.geodatabase.IQueryFilter;
import com.esri.arcgis.geodatabase.esriDrawStyle;
import com.esri.arcgis.geometry.esriGeometryType;
import com.esri.arcgis.system.IClone;
import com.esri.arcgis.system.ITrackCancel;
import com.esri.arcgis.system.esriDrawPhase;
import com.esri.arcgis.interop.AutomationException;

/**
 * Class definition for ColorBivariateRend.
 * In general, bivariate renderer is useful for representing the relationship
 * between two data distributions. Two variables are classified independently,
 * and their combination is represented using some combination of symbol colors.
 */
public class ColorBivariateRend implements IFeatureRenderer,       // generic renderer interface
                       IBivariateRenderer,     // ESRI's bivariate renderer interface
                       ILegendInfo {           // support TOC and legend
  private static final long serialVersionUID = 1L;
  // data members
  IClassBreaksRenderer mainColorRend;
  IClassBreaksRenderer variationColorRend;
  ILegendGroup[] legendGroups;
  AlgorithmicColorRamp algorithmicColorRamp;
  boolean[] ok;

  /**
   * Default constructor.
   */
  public ColorBivariateRend() {
    try {
      this.ok = new boolean[1];
      this.algorithmicColorRamp = new AlgorithmicColorRamp();
      this.algorithmicColorRamp.setAlgorithm(esriColorRampAlgorithm.esriLabLChAlgorithm);
      this.algorithmicColorRamp.setSize(3);
    } catch (java.io.IOException e) {
      // never happens
    }
  }

  // IFeatureRenderer interface
  /**
   * @see IFeatureRenderer#canRender
   * @param featureClass IFeatureClass
   * @param display IDisplay
   * @throws IOException
   * @throws AutomationException
   * @return boolean
   */
  public boolean canRender(IFeatureClass featureClass, IDisplay display) throws IOException, AutomationException {
    return (featureClass.getShapeType() == esriGeometryType.esriGeometryPolygon);
  }

  /**
   * Implements IFeatureRenderer interface
   * @see IFeatureRenderer#prepareFilter
   * @param featureClass
   * @param queryFilter
   * @throws IOException
   * @throws AutomationException
   */
  public void prepareFilter(IFeatureClass featureClass, IQueryFilter queryFilter) throws IOException, AutomationException {
    queryFilter.addField(featureClass.getOIDFieldName());
    IFeatureRenderer rend = (IFeatureRenderer)this.variationColorRend;
    rend.prepareFilter(featureClass, queryFilter);
    rend = (IFeatureRenderer)this.mainColorRend;
    rend.prepareFilter(featureClass, queryFilter);
  }

  /**
   * Implements IFeatureRenderer interface
   * @see IFeatureRenderer#draw
   */
  public void draw(IFeatureCursor featureCursor, int drawPhase, IDisplay display, ITrackCancel trackCancel) throws IOException, AutomationException {
    if (display == null)
      return;
    if (drawPhase != esriDrawPhase.esriDPGeography)
      return;
    IFeature feat = featureCursor.nextFeature();
    boolean bContinue = true;
    // while there are still more features and drawing has not been canceled
    IFeatureRenderer featRend = (IFeatureRenderer)this.mainColorRend;
    IFeatureRenderer featRend2 = (IFeatureRenderer)this.variationColorRend;
    while (feat != null && bContinue == true) {
      ISymbol mainSym = featRend.getSymbolByFeature(feat);
      ISymbol variationSym = featRend2.getSymbolByFeature(feat);
      ISymbol sym = mergedSymbol(mainSym, variationSym); // merge symbols
      display.setSymbol(sym);
      IFeatureDraw featDraw = (IFeatureDraw)feat;
      featDraw.draw(drawPhase, display, sym, true, null, esriDrawStyle.esriDSNormal); // draw the feature
      feat = featureCursor.nextFeature();
      if (trackCancel != null)
        bContinue = trackCancel.esri_continue();
    }
  }

  /**
   * Implements IFeatureRenderer interface
   * @see IFeatureRenderer#getSymbolByFeature
   * @param feature
   * @throws IOException
   * @throws AutomationException
   * @return ISymbol
   */
  public ISymbol getSymbolByFeature(IFeature feature) throws IOException, AutomationException {
    IFeatureRenderer featureRendererMain = (IFeatureRenderer)this.mainColorRend;
    ISymbol colorSymbol = featureRendererMain.getSymbolByFeature(feature);
    IFeatureRenderer featureRendererVariation = (IFeatureRenderer)this.variationColorRend;
    ISymbol sizeSymbol = featureRendererVariation.getSymbolByFeature(feature);
    return mergedSymbol(colorSymbol, sizeSymbol);
  }

  /**
   * Implements IFeatureRenderer interface
   * @see IFeatureRenderer#isRenderPhase
   * @param drawPhase
   * @return boolean
   */
  public boolean isRenderPhase(int drawPhase) {
    return (drawPhase == esriDrawPhase.esriDPGeography);
  }

  /**
   * Implements IFeatureRenderer interface
   * @see IFeatureRenderer#setExclusionSetByRef
   * @param featureIDSet IFeatureIDSet
   */
  public void setExclusionSetByRef(IFeatureIDSet featureIDSet) {
    // nothing implemented
  }

  // IBivariateRenderer interface

  /**
   * Implements IBivariateRenderer interface.
   * Creates the TOC entry for the renderer.
   * Call after setting all other properties.
   * @see IBivariateRenderer#createLegend
   * @throws IOException
   * @throws AutomationException
   */
  public void createLegend() throws IOException, AutomationException {
    ILegendInfo variationLegendInfo = (ILegendInfo)this.variationColorRend;
    ILegendInfo mainLegendInfo = (ILegendInfo)this.mainColorRend;
    this.legendGroups = new ILegendGroup[mainLegendInfo.getLegendGroup(0).getClassCount()];
    // first LegendGroup (0) contains only a heading
    this.legendGroups[0] = new LegendGroup();
    this.legendGroups[0].setHeading(variationLegendInfo.getLegendGroup(0).getHeading());
    // all other LegendGroups (1 thru MainLegendInfo.LegendGroup(0).ClassCount)
    //   contain symbology
    for (int i = 0; i < mainLegendInfo.getLegendGroup(0).getClassCount(); i++) {
      // build new legend group
      this.legendGroups[i] = new LegendGroup();
      String strTemp = mainLegendInfo.getLegendGroup(0).getHeading() + ":" + mainLegendInfo.getLegendGroup(0).esri_getClass(i).getLabel();
      this.legendGroups[i].setHeading(strTemp);
      this.legendGroups[i].setEditable(false); // TOC NOT editable
      for (int j = 0; j < variationLegendInfo.getLegendGroup(0).getClassCount(); j++) {
        // build new legend class
        LegendClass legendClass = new LegendClass();
        legendClass.setLabel(variationLegendInfo.getLegendGroup(0).esri_getClass(j).getLabel());
        // clone the main symbol before merging
        IClone cloneSource = (IClone)mainLegendInfo.getLegendGroup(0).esri_getClass(i).getSymbol();
        IClone cloneTarget = cloneSource.esri_clone();
        ISymbol symbol = (ISymbol)cloneTarget;
        legendClass.setSymbolByRef(mergedSymbol(symbol, variationLegendInfo.getLegendGroup(0).esri_getClass(j).getSymbol()));
        // add legend class to legend group
        this.legendGroups[i].addClass(legendClass);
      }
    }
  }

  /**
   * Implements IBivariateRenderer interface.
   * @see IBivariateRenderer#setMainRendererByRef
   * @param featureRenderer
   * @throws IOException
   * @throws AutomationException
   */
  public void setMainRendererByRef(IFeatureRenderer featureRenderer) throws IOException, AutomationException {
    this.mainColorRend = (ClassBreaksRenderer)featureRenderer;
  }

  /**
   * Implements IBivariateRenderer interface.
   * @see IBivariateRenderer#getMainRenderer
   * @throws IOException
   * @throws AutomationException
   * @return IFeatureRenderer
   */
  public IFeatureRenderer getMainRenderer() throws IOException, AutomationException {
    return (IFeatureRenderer)this.mainColorRend;
  }

  /**
   * Implements IBivariateRenderer interface.
   * @see IBivariateRenderer#setVariationRendererByRef
   * @param featureRenderer
   * @throws IOException
   * @throws AutomationException
   */
  public void setVariationRendererByRef(IFeatureRenderer featureRenderer) throws IOException, AutomationException {
    this.variationColorRend = (IClassBreaksRenderer)featureRenderer;
  }

  /**
   * Implements IBivariateRenderer interface.
   * @see IBivariateRenderer#getVariationRenderer
   * @throws IOException
   * @throws AutomationException
   * @return IFeatureRenderer
   */
  public IFeatureRenderer getVariationRenderer() throws IOException, AutomationException {
    return (IFeatureRenderer)this.variationColorRend;
  }

  // ILegendInfo interface

  /**
   * Implements ILegendInfo interface.
   * @see ILegendInfo#getLegendGroupCount
   * @return int
   */
  public int getLegendGroupCount() {
    return this.legendGroups.length;
  }

  /**
   * Implements ILegendInfo interface.
   * @see ILegendInfo#getLegendGroup
   * @param index
   * @return ILegendGroup
   */
  public ILegendGroup getLegendGroup(int index) {
    if (index >= 0 && index < this.legendGroups.length)
      return this.legendGroups[index];
    return null;
  }

  /**
   * Implements ILegendInfo interface.
   * @see ILegendInfo#getLegendItem
   * @return ILegendItem
   */
  public ILegendItem getLegendItem() {
    return null;
  }

  /**
   * Implements ILegendInfo interface.
   * @see ILegendInfo#isSymbolsAreGraduated
   * @return boolean
   */
  public boolean isSymbolsAreGraduated() {
    return false;
  }

  /**
   * Implements ILegendInfo interface
   * @see ILegendInfo#setSymbolsAreGraduated
   * @param b boolean
   */
  public void setSymbolsAreGraduated(boolean b) {
    // nothing implemented
  }

  // private own methods

  /**
   * Auxiliary private method merges two symbols in one.
   * @param mainSym ISymbol
   * @param variationSym ISymbol
   * @throws IOException
   * @throws AutomationException
   * @return ISymbol
   */
  private ISymbol mergedSymbol(ISymbol mainSym, ISymbol variationSym) throws IOException, AutomationException {
    IFillSymbol colorMain = (IFillSymbol)mainSym;
    IFillSymbol colorVariation = (IFillSymbol)variationSym;
    this.algorithmicColorRamp.setFromColor(colorMain.getColor());
    this.algorithmicColorRamp.setToColor(colorVariation.getColor());
    this.algorithmicColorRamp.createRamp(this.ok);
    colorMain.setColor(this.algorithmicColorRamp.getColor(1));
    return (ISymbol)colorMain;
  }

}