protected override void UpdateVertexColors(Rhino.DocObjects.RhinoObject obj, Mesh[] meshes)
    {
        // A "mapping tag" is used to determine if the colors need to be set
        Rhino.Render.MappingTag mt = GetMappingTag(obj.RuntimeSerialNumber);

        for (int mi = 0; mi < meshes.Length; mi++)
        {
            var mesh = meshes[mi];
            if (mesh.VertexColors.Tag.Id != this.Id)
            {
                // The mesh's mapping tag is different from ours. Either the mesh has
                // no false colors, has false colors set by another analysis mode, has
                // false colors set using different m_z_range[]/m_hue_range[] values, or
                // the mesh has been moved.  In any case, we need to set the false
                // colors to the ones we want.
                System.Drawing.Color[] colors = new System.Drawing.Color[mesh.Vertices.Count];
                for (int i = 0; i < mesh.Vertices.Count; i++)
                {
                    double z = mesh.Vertices[i].Z;
                    colors[i] = FalseColor(z);
                }
                mesh.VertexColors.SetColors(colors);
                // set the mesh's color tag
                mesh.VertexColors.Tag = mt;
            }
        }
    }
    /// <summary>
    /// Returns a mapping tag that is used to detect when a mesh's colors need to
    /// be set.
    /// </summary>
    /// <returns></returns>
    Rhino.Render.MappingTag GetMappingTag(uint serialNumber)
    {
        Rhino.Render.MappingTag mt = new Rhino.Render.MappingTag();
        mt.Id = this.Id;

        // Since the false colors that are shown will change if the mesh is
        // transformed, we have to initialize the transformation.
        mt.MeshTransform = Transform.Identity;

        // This is a 32 bit CRC or the information used to set the false colors.
        // For this example, the m_z_range and m_hue_range intervals control the
        // colors, so we calculate their crc.
        uint crc = RhinoMath.CRC32(serialNumber, m_z_range.T0);

        crc           = RhinoMath.CRC32(crc, m_z_range.T1);
        crc           = RhinoMath.CRC32(crc, m_hue_range.T0);
        crc           = RhinoMath.CRC32(crc, m_hue_range.T1);
        mt.MappingCRC = crc;
        return(mt);
    }
  /// <summary>
  /// Returns a mapping tag that is used to detect when a mesh's colors need to
  /// be set.
  /// </summary>
  /// <returns></returns>
  Rhino.Render.MappingTag GetMappingTag(uint serialNumber)
  {
    Rhino.Render.MappingTag mt = new Rhino.Render.MappingTag();
    mt.Id = this.Id;

    // Since the false colors that are shown will change if the mesh is
    // transformed, we have to initialize the transformation.
    mt.MeshTransform = Transform.Identity;

    // This is a 32 bit CRC or the information used to set the false colors.
    // For this example, the m_z_range and m_hue_range intervals control the
    // colors, so we calculate their crc.
    uint crc = RhinoMath.CRC32(serialNumber, m_z_range.T0);
    crc = RhinoMath.CRC32(crc, m_z_range.T1);
    crc = RhinoMath.CRC32(crc, m_hue_range.T0);
    crc = RhinoMath.CRC32(crc, m_hue_range.T1);
    mt.MappingCRC = crc;
    return mt;
  }