ArcEngine+C# TIN 相关三维功能模块介绍 ( 三 ) TreeView 控件控制 TIN 颜色 作者 : 刘志远 Email:592418843@qq.com
1. 简介 本篇介绍如何写一个带复选框及颜色指示图标的 TreeView 控件, 该控件与 TIN 模型分级设色方案中的各级颜色相关联 通过该 TreeView 控件复选框的勾选状态决定 TIN 模型对应颜色层的显示与隐藏, 再结合颜色选择下拉框控件, 双击 TreeView 中的颜色图标, 弹出颜色选择对话框, 选择颜色后即可实时改变 TIN 模型中对应分级的颜色, 效果图如下 注意观察 TreeView 中复选框为空的颜色层对应 TIN 的样式, 此外, 那个蓝色和紫色的层是经过修改过后的结果 : 颜色选择对话框 运行效果界面截图
2. 思路分析 编写 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) 相关联, 这样就达到实时更新显示的效果 3. 完整代码 下面是该控件的完整代码, 具体的解释见代码注释 : 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 /// 模仿 ArcGIS 的 TOCControl 控件, 对 TIN 模型分级渲染颜色进行关联, /// 并通过复选框的勾选状态控制对应色带的显隐, /// 同时可双击颜色图标, 实时修改对应层的颜色 public partial class ColorControlView : UserControl /// 颜色图标清单 private ImageList pimagelist; /// 激活的节点
private TreeNode ptreenode; /// 含有 TIN 的三维控件 static private AxSceneControl _pscenecontrol; // 构造函数 public ColorControlView() InitializeComponent(); treeview1.checkboxes = true; /// 初始化, 关联 TIN 图层颜色列表与 TreeView 控件 /// <param name="pscenecontrol"> 含 TIN 图层的 AxSceneControl 控件 </param> public void IniColorTree(AxSceneControl pscenecontrol) _pscenecontrol = pscenecontrol; ITinLayer ptinlayer = gettinlayer(_pscenecontrol); if (ptinlayer == null) 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) 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); /// 关联图标 /// <param name="sender"></param> /// <param name="e"></param> private void treeview1_afterselect(object sender, TreeViewEventArgs e) treeview1.selectedimageindex = treeview1.selectednode.imageindex; /// 复选框勾选事件 /// <param name="sender"></param> /// <param name="e"></param> private void treeview1_aftercheck(object sender, TreeViewEventArgs e) // 调用颜色显隐方法 ShowOrHideColor(); treeview1.selectednode = e.node; /// 双击节点事件 /// <param name="sender"></param> /// <param name="e"></param>
private void treeview1_doubleclick(object sender, EventArgs e) if (treeview1.selectednode == null) ptreenode = treeview1.selectednode; // 调用改变颜色方法 ChangeColor(); // 刷新颜色图标 treeview1.selectednode = treeview1.nodes[0]; treeview1.selectednode = ptreenode; /// 获得颜色图标 /// <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; /// 切换点选色带对应 TIN 中区域的显示 / 消隐状态 /// 既通过给 TIN 一个新的渲染器来实现 private void ShowOrHideColor() ITinLayer ptinlayer = gettinlayer(_pscenecontrol); if (ptinlayer == null)
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(); /// 改变点选色带对应 TIN 区域的颜色 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) 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(); /// 获得三维控件中的 TIN 图层 /// <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); 4. 下一篇简介 下一篇打算介绍如何从 DEM 栅格数据中提取等值线以及如何由 DEM 栅格数据生成 TIN 三维模型 最后把这个系列所设计的功能整合到一个程序中, 以供感兴趣的朋友参考