Common Custom renderers
Common_CustomRenderers_CSharp\App_Code\GraduatedColorRenderer.cs
// Copyright 2010 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.
// 

namespace ESRI.ADF.Samples.Renderers
{
  /// <summary>
  /// Renderer that colors a layer based on an attribute
  /// </summary>
    [System.Serializable]
    public class GraduatedColorRenderer : ESRI.ADF.Samples.Renderers.RendererBase
  {
    #region Public Properties

    private System.Drawing.Color startColor = System.Drawing.Color.Red;

        /// <summary>
        /// Beginning color of the renderer's gradient
        /// </summary>
    public System.Drawing.Color StartColor
    {
      get { return startColor; }
      set { startColor = value; }
    }

    private System.Drawing.Color endColor = System.Drawing.Color.Yellow;

        /// <summary>
        /// Ending color of the renderer's gradient
        /// </summary>
    public System.Drawing.Color EndColor
    {
      get { return endColor; }
      set { endColor = value; }
    }

    private double minValue = 0;

        /// <summary>
        /// The value to apply StartColor to.  Values less than MinValue will also
        /// be rendered using StartColor.
        /// </summary>
    public double MinValue
    {
      get { return minValue; }
      set { minValue = value; }
    }

    private double maxValue = 100;

        /// <summary>
        /// The value to apply EndColor to.  Values greater than MaxValue will also
        /// be rendered using EndColor.
        /// </summary>
    public double MaxValue
    {
      get { return maxValue; }
      set { maxValue = value; }
    }

    private string colorColumnName;

        /// <summary>
        /// The name of the column to use in determining a feature's color
        /// </summary>
    public string ColorColumnName
    {
      get { return colorColumnName; }
      set { colorColumnName = value; }
    }

    #endregion

    #region IRenderer Members

        /// <summary>
        /// Main part of the IRenderer interface, within which a feature encapsulating the specified DataRow is to be 
        /// rendered on the specified graphics surface. The geometry instance has already been transformed to screen 
        /// coordinate, so we don't have to worry about that here.
        /// </summary>
        /// <param name="row">row containing the feature's data</param>
        /// <param name="graphics">GDI+ surface on which to render the feature</param>
        /// <param name="geometryColumn">column containing the feature's geometry</param>
        public override void Render(System.Data.DataRow row, System.Drawing.Graphics graphics, 
            System.Data.DataColumn geometryColumn)
    {
            // Validate input
      if (row == null || graphics == null || geometryColumn == null)
        return;

            // Get the feature geometry
      ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfGeometry = 
                row[geometryColumn] as ESRI.ArcGIS.ADF.Web.Geometry.Geometry;

            // Validate the geometry.  Points are not handled by this renderer.
      if (adfGeometry == null || adfGeometry is ESRI.ArcGIS.ADF.Web.Geometry.Point) 
        return;

      // Make sure the feature has the column specified for use in determining the feature's color
      if (!string.IsNullOrEmpty(this.ColorColumnName) && 
                row.Table.Columns.Contains(this.ColorColumnName))
      {
                // Make sure the color value can be cast to a double
        double value = 0;
        if (double.TryParse(row[ColorColumnName].ToString(), out value))
        {
                    // Calculate what color the value corresponds to
          System.Drawing.Color color = interpolateColor(value);

                    // Render the geometry with the renderers utility
          if (adfGeometry is ESRI.ArcGIS.ADF.Web.Geometry.Polygon)
          {
            ESRI.ADF.Samples.Renderers.Utility.FillPolygon(graphics, 
                            adfGeometry as ESRI.ArcGIS.ADF.Web.Geometry.Polygon, color, 0, 0, 0);
          }
          else if (adfGeometry is ESRI.ArcGIS.ADF.Web.Geometry.Polyline)
          {
            ESRI.ADF.Samples.Renderers.Utility.DrawPolyline(graphics, 
                            adfGeometry as ESRI.ArcGIS.ADF.Web.Geometry.Polyline, color, 2);
          }
        }
      }
    }

    /// <summary>
    /// Creates swatches used for the Table of Contents / Legend.
    /// This is automatically called by IMapTocFunctionality when generating the TOC.
    /// </summary>
    /// <param name="swatchInfo"></param>
    /// <param name="fileName"></param>
    /// <param name="minScale"></param>
    /// <param name="maxScale"></param>
    /// <returns></returns>
    public override ESRI.ArcGIS.ADF.Web.Display.Swatch.SwatchCollection GenerateSwatches(
            ESRI.ArcGIS.ADF.Web.Display.Swatch.SwatchInfo swatchInfo, string fileName, string minScale, string maxScale)
    {
      ESRI.ArcGIS.ADF.Web.Display.Swatch.SwatchCollection swatches = 
                base.GenerateSwatches(swatchInfo, fileName, minScale, maxScale);
      ESRI.ArcGIS.ADF.Web.Display.Swatch.SwatchUtility swatchUtility = 
                new ESRI.ArcGIS.ADF.Web.Display.Swatch.SwatchUtility(swatchInfo);

            int swatchCount = 5; // The number of swatches created is this number plus one

            // Create the swatches
      for (int i = 0; i <= swatchCount; i++)
      {
        // Use the renderer's man and max values to interpolate the value at step 'i'
        double value = minValue + (maxValue - minValue) / swatchCount * i;

                // Get the color at this value
        System.Drawing.Color color = interpolateColor(value);

                // Create the swatch image
        ESRI.ArcGIS.ADF.Web.CartoImage swatchImage = swatchUtility.DrawNewSwatch(
                    new ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleFillSymbol(color, System.Drawing.Color.Empty, 
                        ESRI.ArcGIS.ADF.Web.Display.Symbol.PolygonFillType.Solid), fileName);

        // Create the swatch and add it to the collection
        swatches.Add(new ESRI.ArcGIS.ADF.Web.Display.Swatch.Swatch(swatchImage, value.ToString(), null, null));
      }
      return swatches;
    }

    #endregion

    /// <summary>
    /// Returns the color for a given value based on the renderer's min and max values and start and end colors.
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private System.Drawing.Color interpolateColor(double value)
    {
            // Return the start or end color if the value is at or outside the renderer's value bounds
      if (value <= minValue) return startColor;
      if (value >= maxValue) return endColor;

            // Calculate how far along the gradient the passed-in value is
      double distanceAlongGradient = (value - minValue) / (maxValue - minValue);

            // Interpolate the red, green, blue, and alpha values based on the distance along the gradient,
            // the renderer's start color, and the renderer's end color
      int red = (int)System.Math.Round(startColor.R * (1 - distanceAlongGradient) + 
                endColor.R * (distanceAlongGradient));
            int green = (int)System.Math.Round(startColor.G * (1 - distanceAlongGradient) + 
                endColor.G * (distanceAlongGradient));
            int blue = (int)System.Math.Round(startColor.B * (1 - distanceAlongGradient) + 
                endColor.B * (distanceAlongGradient));
            int alpha = (int)System.Math.Round(startColor.A * (1 - distanceAlongGradient) + 
                endColor.A * (distanceAlongGradient));

      return System.Drawing.Color.FromArgb(alpha, red, green, blue);
    }
  }
}