ArcEngine+C# TIN相关三维功能模块介绍(三)
——TreeView控件控制TIN颜色
本篇介绍如何写一个带复选框及颜色指示图标的TreeView控件,该控件与TIN模型分级设色方案中的各级颜色相关联。通过该TreeView控件复选框的勾选状态决定TIN模型对应颜色层的显示与隐藏,再结合颜色选择下拉框控件,双击TreeView中的颜色图标,弹出颜色选择对话框,选择颜色后即可实时改变TIN模型中对应分级的颜色,效果图如下。注意观察TreeView中复选框为空的颜色层对应TIN的样式,此外,那个蓝色和紫色的层是经过修改过后的结果:
颜色选择对话框
运行效果界面截图
编写TIN颜色关联TreeView控件过程同上篇的编写颜色控件类似,先在项目下添加一个新的UserControl控件,再拖一个TreeView控件到UserControl上,将TreeView的Dock属性设为Fill,,最后加入代码。
TIN模型颜色可以通过ITinRenderer渲染器接口设置,ITinColorRampRenderer接口控制渲染器中的色带,通过遍历获取或设置ITinColorRampRenderer中的颜色值,再将改变后的ITinRenderer重新赋给TIN模型就行了。隐藏效果只是将对应层的颜色值设为NullColor即可。
再稍微解释一下TreeView中颜色图标的实时联动更新。我是先生成一个动态的Image图片对象,该Image的颜色就是从TIN模型或颜色对话框中获得的颜色值,再依次将这些颜色图片存入一个ImageList对象中,再将该ImageList对象赋给TreeView,通过ImageList中图片的索引与TreeView中的节点(Node)相关联,这样就达到实时更新显示的效果。
下面是该控件的完整代码,具体的解释见代码注释:
using System;
using System.Drawing;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Analyst3D;
namespace CaseAnalyse
{
/// <summary>
/// 模仿ArcGIS的TOCControl控件,对TIN模型分级渲染颜色进行关联,
/// 并通过复选框的勾选状态控制对应色带的显隐,
/// 同时可双击颜色图标,实时修改对应层的颜色
/// </summary>
public partial class ColorControlView : UserControl
{
/// <summary>
/// 颜色图标清单
/// </summary>
private ImageList pImageList;
/// <summary>
/// 激活的节点
/// </summary>
private TreeNode pTreeNode;
/// <summary>
/// 含有TIN的三维控件
/// </summary>
static private AxSceneControl _pSceneControl;
//构造函数
public ColorControlView()
{
InitializeComponent();
treeView1.CheckBoxes = true;
}
/// <summary>
/// 初始化,关联TIN图层颜色列表与TreeView控件
/// </summary>
/// <param name="pSceneControl">含TIN图层的AxSceneControl控件</param>
public void IniColorTree(AxSceneControl pSceneControl)
{
_pSceneControl = pSceneControl;
ITinLayer pTinLayer = getTinLayer(_pSceneControl);
if (pTinLayer == null)
return;
treeView1.Nodes.Clear();
//给TreeView绑定一个图片列表控件,该控件记录着所有的颜色图片
pImageList = new ImageList();
pImageList.ImageSize = new Size(16, 15);
treeView1.ImageList = pImageList;
//获得TIN模型的渲染器,这里假设只有一个渲染层
ITinRenderer pRenderNew = pTinLayer.GetRenderer(0);
ITinColorRampRenderer pElevRenderer = pRenderNew as ITinColorRampRenderer;
if (pElevRenderer == null)
return;
ISimpleFillSymbol pSymbol = null;
Color pColor = new Color();
string lable = "";
//遍历渲染层的分级颜色,并用生成动态临时图标,将其加入ImageList中,以备TreeView调用
for (int i = 0; i < pElevRenderer.BreakCount; i++)
{
lable = pElevRenderer.get_Label(i);
pSymbol = pElevRenderer.get_Symbol(i) as ISimpleFillSymbol;
pColor = ColorTranslator.FromOle(pSymbol.Color.RGB);
Image pImage = getImage(pColor);
pImageList.Images.Add(pImage);
TreeNode pTN = new TreeNode();
pTN.Text = lable;
pTN.Checked = true;
pTN.ImageIndex = pImageList.Images.Count - 1;
pTN.Tag = pColor;
treeView1.Nodes.Add(pTN);
}
}
/// <summary>
/// 关联图标
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
treeView1.SelectedImageIndex = treeView1.SelectedNode.ImageIndex;
}
/// <summary>
/// 复选框勾选事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
//调用颜色显隐方法
ShowOrHideColor();
treeView1.SelectedNode = e.Node;
}
/// <summary>
/// 双击节点事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView1_DoubleClick(object sender, EventArgs e)
{
if (treeView1.SelectedNode == null)
return;
pTreeNode = treeView1.SelectedNode;
//调用改变颜色方法
ChangeColor();
//刷新颜色图标
treeView1.SelectedNode = treeView1.Nodes[0];
treeView1.SelectedNode = pTreeNode;
}
/// <summary>
/// 获得颜色图标
/// </summary>
/// <param name="clr">图标颜色</param>
/// <returns></returns>
private static Image getImage(Color clr)
{
Panel pPanel = new Panel();
pPanel.Visible = false;
pPanel.Width = 16;
pPanel.Height = 14;
Bitmap pBitmap = new Bitmap(16, 14);
Rectangle rc = new Rectangle(0, 0, 16, 14);
pPanel.BackColor = clr;
pPanel.DrawToBitmap(pBitmap, rc);
Image pImage = (Image)pBitmap;
return pImage;
}
/// <summary>
/// 切换点选色带对应TIN中区域的显示/消隐状态
/// 既通过给TIN一个新的渲染器来实现
/// </summary>
private void ShowOrHideColor()
{
ITinLayer pTinLayer = getTinLayer(_pSceneControl);
if (pTinLayer == null)
return;
ITinRenderer pRenderNew = pTinLayer.GetRenderer(0);
ITinColorRampRenderer pElevRenderer = pRenderNew as ITinColorRampRenderer;
ISimpleFillSymbol pSymbol = null;
int ClassCount = treeView1.Nodes.Count;
//遍历TreeView节点,并依次设置渲染器样式
for (int i = 0; i < ClassCount; i++)
{
pSymbol = pElevRenderer.get_Symbol(i) as ISimpleFillSymbol;
IRgbColor rgb = new RgbColorClass();
rgb.Red = ((Color)treeView1.Nodes[i].Tag).R;
rgb.Green = ((Color)treeView1.Nodes[i].Tag).G;
rgb.Blue = ((Color)treeView1.Nodes[i].Tag).B;
IColor pC = rgb as IColor;
if (!treeView1.Nodes[i].Checked)
{
pC.NullColor = true;
pC.Transparency = 0;
}
pSymbol = new SimpleFillSymbolClass();
pSymbol.Color = pC;
//设置渲染器样式
pElevRenderer.set_Symbol(i, pSymbol as ISymbol);
}
//创建TinEdgeRendererClass 类型的Renderer
pTinLayer.ClearRenderers();
//插入一个渲染模型
pTinLayer.InsertRenderer(pRenderNew, 0);
//刷新渲染
_pSceneControl.Scene.SceneGraph.Invalidate(pTinLayer, true, false);
_pSceneControl.SceneViewer.Redraw(true);
_pSceneControl.Scene.SceneGraph.RefreshViewers();
}
/// <summary>
/// 改变点选色带对应TIN区域的颜色
/// </summary>
private void ChangeColor()
{
FrmChosePColor fChoseColor = new FrmChosePColor();
if (fChoseColor.ShowDialog() == DialogResult.OK)
{
Color color = fChoseColor.pureColorComboBox1.SelectedColor;
IRgbColor rgb = new RgbColorClass();
rgb.Red = color.R;
rgb.Green = color.G;
rgb.Blue = color.B;
IColor pC = rgb as IColor;
Image pImage = getImage(color);
pImageList.Images.Add(pImage);
pTreeNode.ImageIndex = pImageList.Images.Count - 1;
pTreeNode.Tag = color;
treeView1.Refresh();
ITinLayer pTinLayer = getTinLayer(_pSceneControl);
if (pTinLayer == null)
return;
ITinRenderer pRenderNew = pTinLayer.GetRenderer(0);
ITinColorRampRenderer pElevRenderer = pRenderNew as ITinColorRampRenderer;
ISimpleFillSymbol pSymbol = null;
int ClassCount = treeView1.Nodes.Count;
for (int i = 0; i < ClassCount; i++)
{
if (i != pTreeNode.Index)
continue;
pSymbol = new SimpleFillSymbolClass();
if (!treeView1.Nodes[i].Checked)
{
pC.NullColor = true;
pC.Transparency = 0;
}
pSymbol.Color = pC;
pElevRenderer.set_Symbol(i, pSymbol as ISymbol);
}
//创建TinEdgeRendererClass 类型的Renderer
pTinLayer.ClearRenderers();
pTinLayer.InsertRenderer(pRenderNew, 0);//插入一个渲染模型
//渲染的刷新方法.
_pSceneControl.Scene.SceneGraph.Invalidate(pTinLayer, true, false);
_pSceneControl.SceneViewer.Redraw(true);
_pSceneControl.Scene.SceneGraph.RefreshViewers();
}
}
/// <summary>
/// 获得三维控件中的TIN图层
/// </summary>
/// <param name="pSceneControl">含TIN图层的AxSceneControl控件</param>
/// <returns></returns>
private static ITinLayer getTinLayer(AxSceneControl pSceneControl)
{
IScene pScene = pSceneControl.Scene;
ITinLayer pTinLayer = null;
for (int i = 0; i < pScene.LayerCount; i++)
{
ILayer lyr = pScene.get_Layer(i);
if (lyr is ITinLayer)
{
pTinLayer = lyr as ITinLayer;
break;
}
}
return pTinLayer;
}
}
}
最后,只需要将该控件拖入相应的窗体中,调用控件的IniColorTree()方法,传入参数AxSceneControl即可,如下:
private void button1_Click(object sender, EventArgs e)
{
//关联色板
this.colorControlView1.IniColorTree(this.axSceneControl1);
}
下一篇打算介绍如何从DEM栅格数据中提取等值线以及如何由DEM栅格数据生成TIN三维模型。最后把这个系列所设计的功能整合到一个程序中,以供感兴趣的朋友参考。