如何解决栅格色彩拉伸后TocControl里的图例不能更新的问题
2012-09-19 16:55
459 查看
关于栅格图层色彩拉伸,有很多例子,网上也可以找到各种资料,但是所有的资料都没有解决一个问题,那就是只说如何做拉伸,但是做色彩拉伸以后的图例更新问题一直没有正解。最早提出这个问题的帖子,在这里:http://forums.esri.com/thread.asp?c=93&f=1170&t=191617#848069,但是答案却一直空缺着,本文就来说明一下如何解决这个问题。
首先说一下如何让做栅格色彩拉伸,请看下面的代码:
可以看到,这里面很重要的一点就是逐一设置了图例的符号。从这里,我们可以受到一点启发,那就是我们的栅格拉伸处理,是不是也需要做这样的一个处理。可以看到RasterStretchColorRampRender实现了ILegendInfo接口,而ILegendInfo接口就是用来管理图层图例的接口。据此,我们就需要详细研究一下ILegendInfo对象在做完上面的栅格色彩拉伸后有什么变化。经过跟踪发现,执行栅格拉伸后,ILegendInfo接口对象始终含有一个LegendGroup,而这个LegendGroup则含有三个LegendItem,查看这三个LegendItem的Label发现正是图层图例里列出的“高值”,"中间值“,”低值“,因此可以推断他们就是解决图例色带问题的核心。研究ILegendCalss接口,发现里面果然有Symbol成员,直觉告诉我们,应该修改这个属性。查找所有实现了ISymbol接口的类,发现IColorRampSymbol最有嫌疑。通过使用ArcMap***一个彩色拉伸图层,然后保存为MXD文档并用自己的程序加载,对比发现,果然自己做拉伸后所有LegendItem的Symbol都是null,而ArcMap做拉伸后LegendItem的Symbol都有值,并且可以转换为IColorRampSymbol,这样问题似乎已经浮出水面了,于是我们来添加下面的一段处理代码:
很遗憾,图例中的色带出现了,但是并不是我们想看到的那样。继续探索,发现关于IColorRampSymbol接口,AE的帮助里几乎找不到任何有用的说明,于是我们不得不发挥想象力,考虑一下如果你是设计这个接口的人,你会怎么去做。很明显,栅格拉伸后的图例由三个LegendItem组成,每一个都带有一个Symbol,而这个Symbol都是IColorRampSymbol,但是这个色带符号很长,需要横跨三个图例项,唯一的办法就是把它分成3份,于是我们可能需要一个标记来告诉这三个图例项,他们分别应该对应这个色带符号的那一部分。据此,再来研究一下IColorRampSymbol接口,发现里面有两个属性非常可疑,一个是ColorRampInLegendGroup,一个是LegendClassIndex,很明显,作为一个图例项的成员,肯定知道自己的Index,但是这里却要多加这样一个属性,所以问题可能就在这里了。关于这个ColorRampInLegendGroup属性,网上以及AE的帮助里找不到任何有用的信息,所以也只好用猜的了。直白的来说,根据字面意思,这个属性的意思就是”图例组的色带“,所以我们可以猜测到实际处理中,这个图例组实际上使用的是一个色带,每个图例项也都是用这个色带,唯一需要做的就是用一个标记来标注每个图例项对应色带的哪里。下面就再做验证,仍然查看ArcMap下***的正确的色彩拉伸结果,发现三个图例项果然都使用同一个IColorRamp对象,于是问题就明朗了,毋庸置疑,LegendClassIndex的作用,正是我们所猜测的那样。于是对图例更新代码做一些修改,如下:
至此问题解决了。下面画个图,说明一下ColorRampSymbol与图例的关系:
![](http://img.my.csdn.net/uploads/201209/19/1348045850_2272.png)
简单说来,就是色彩拉伸后的图例实际上是一个由三个图例项组成的图例组,每个图例项都带有一个ColorRampSymbol,而借助这个ColorRampSymbol也可以指定整个图例组使用的色带,对于这个完整的色带,如何让图例项去自动对应呢,就是靠ColorRampSymbol的LengendClassIndex属性来完成的。
首先说一下如何让做栅格色彩拉伸,请看下面的代码:
IRasterLayer pRasterLayer = wndMap.CustomProperty as IRasterLayer; IRasterRenderer pRasterRender = pRasterLayer.Renderer; IRasterRenderer pNewRasterRender = null; IRgbColor pFromColor = new RgbColorClass(); pFromColor.RGB = 0xffffff; IRgbColor pToColor = new RgbColorClass(); pToColor.RGB = 0x000000; IAlgorithmicColorRamp pAlgorithmColorRamp = new AlgorithmicColorRampClass(); pAlgorithmColorRamp.Size = 256; pAlgorithmColorRamp.FromColor = pFromColor; pAlgorithmColorRamp.ToColor = pToColor; bool bColorRampCreated = false; pAlgorithmColorRamp.CreateRamp(out bColorRampCreated); IRasterStretchColorRampRenderer pRasterStretchColorRamp = new RasterStretchColorRampRendererClass(); pNewRasterRender = pRasterStretchColorRamp as IRasterRenderer; pNewRasterRender.Raster = pRasterLayer.Raster; pRasterStretchColorRamp.BandIndex = 0; pRasterStretchColorRamp.ColorRamp = pAlgorithmColorRamp; IRasterStretch pRasterStretch = pNewRasterRender as IRasterStretch; pRasterStretch.StretchType = esriRasterStretchTypesEnum.esriRasterStretch_MinimumMaximum; pNewRasterRender.Update(); pRasterLayer.Renderer = pNewRasterRender;这是基本的处理方式,这里出于使示例整洁完整使用的是一个自定义的色带。更为详尽的示例,请参考这里:http://www.gisall.com/html/59/26859-2432.html做色彩拉伸时,通常使用的色带是ArcGIS SymbologyControl里的预定义色带,加载的类型为esriSymbologyStyleClass.esriStyleClassColorRamps。可以将SymbologyControl里选中的色带直接转换为IColorRamp,然后作为IRasterStretchColorRampRenderer的ColorRamp。基本流程清除了,但问题也会凸显出来,那就是TocControl里的图例并不会自动显示色带。那么问题在哪里呢?下面来看一下AE附带的示例里相关的例子里是怎么做的,下面是AE的C#例子"SymbologyControlColorRamps"里对矢量图层做分段设色处理的代码:
private void button2_Click(object sender, System.EventArgs e) { //Create a new ClassBreaksRenderer and set properties m_classBreaksRenderer = new ClassBreaksRenderer(); m_classBreaksRenderer.Field = comboBox1.SelectedItem.ToString(); m_classBreaksRenderer.BreakCount = Convert.ToInt32(textBox1.Text); m_classBreaksRenderer.MinimumBreak = Convert.ToDouble(textBox2.Text); //Calculate the class interval by a simple mean value double interval = (Convert.ToDouble(textBox3.Text) - m_classBreaksRenderer.MinimumBreak) / m_classBreaksRenderer.BreakCount; //Get the color ramp IColorRamp colorRamp = (IColorRamp) m_styleGalleryItem.Item; //Set the size of the color ramp and recreate it colorRamp.Size = Convert.ToInt32(textBox1.Text); bool createRamp; colorRamp.CreateRamp(out createRamp); //Get the enumeration of colors from the color ramp IEnumColors enumColors = colorRamp.Colors; enumColors.Reset(); double currentBreak = m_classBreaksRenderer.MinimumBreak; ISimpleFillSymbol simpleFillSymbol; //Loop rhough each class break for (int i = 0; i <= m_classBreaksRenderer.BreakCount-1; i++) { //Set class break m_classBreaksRenderer.set_Break(i,currentBreak); //Create simple fill symbol and set color simpleFillSymbol = new SimpleFillSymbolClass(); simpleFillSymbol.Color = enumColors.Next(); //Add symbol to renderer m_classBreaksRenderer.set_Symbol(i, (ISymbol)simpleFillSymbol); currentBreak += interval; } //Hide the form this.Hide(); }
可以看到,这里面很重要的一点就是逐一设置了图例的符号。从这里,我们可以受到一点启发,那就是我们的栅格拉伸处理,是不是也需要做这样的一个处理。可以看到RasterStretchColorRampRender实现了ILegendInfo接口,而ILegendInfo接口就是用来管理图层图例的接口。据此,我们就需要详细研究一下ILegendInfo对象在做完上面的栅格色彩拉伸后有什么变化。经过跟踪发现,执行栅格拉伸后,ILegendInfo接口对象始终含有一个LegendGroup,而这个LegendGroup则含有三个LegendItem,查看这三个LegendItem的Label发现正是图层图例里列出的“高值”,"中间值“,”低值“,因此可以推断他们就是解决图例色带问题的核心。研究ILegendCalss接口,发现里面果然有Symbol成员,直觉告诉我们,应该修改这个属性。查找所有实现了ISymbol接口的类,发现IColorRampSymbol最有嫌疑。通过使用ArcMap***一个彩色拉伸图层,然后保存为MXD文档并用自己的程序加载,对比发现,果然自己做拉伸后所有LegendItem的Symbol都是null,而ArcMap做拉伸后LegendItem的Symbol都有值,并且可以转换为IColorRampSymbol,这样问题似乎已经浮出水面了,于是我们来添加下面的一段处理代码:
ILegendInfo pLengendInfo = m_RasterStretchColorRampRenderer as ILegendInfo; ILegendGroup pLegendGroup = pLengendInfo.get_LegendGroup(0); IColorRamp pColorRamp = m_StyleGalleryItem.Item as IColorRamp; for (int j = 0; j < pLegendGroup.ClassCount; j++) { ILegendClass pLegendClass = pLegendGroup.get_Class(j); pLegendClass.Symbol = new ESRI.ArcGIS.Carto.ColorRampSymbolClass(); ISymbol pSymbol = pLegendClass.Symbol; IColorRampSymbol pColorRampSymbol = pSymbol as IColorRampSymbol; pColorRampSymbol.ColorRamp = pColorRamp; pLegendClass.Symbol = pColorRampSymbol as ISymbol; } (m_RasterStretchColorRampRenderer as IRasterRenderer).Update();
很遗憾,图例中的色带出现了,但是并不是我们想看到的那样。继续探索,发现关于IColorRampSymbol接口,AE的帮助里几乎找不到任何有用的说明,于是我们不得不发挥想象力,考虑一下如果你是设计这个接口的人,你会怎么去做。很明显,栅格拉伸后的图例由三个LegendItem组成,每一个都带有一个Symbol,而这个Symbol都是IColorRampSymbol,但是这个色带符号很长,需要横跨三个图例项,唯一的办法就是把它分成3份,于是我们可能需要一个标记来告诉这三个图例项,他们分别应该对应这个色带符号的那一部分。据此,再来研究一下IColorRampSymbol接口,发现里面有两个属性非常可疑,一个是ColorRampInLegendGroup,一个是LegendClassIndex,很明显,作为一个图例项的成员,肯定知道自己的Index,但是这里却要多加这样一个属性,所以问题可能就在这里了。关于这个ColorRampInLegendGroup属性,网上以及AE的帮助里找不到任何有用的信息,所以也只好用猜的了。直白的来说,根据字面意思,这个属性的意思就是”图例组的色带“,所以我们可以猜测到实际处理中,这个图例组实际上使用的是一个色带,每个图例项也都是用这个色带,唯一需要做的就是用一个标记来标注每个图例项对应色带的哪里。下面就再做验证,仍然查看ArcMap下***的正确的色彩拉伸结果,发现三个图例项果然都使用同一个IColorRamp对象,于是问题就明朗了,毋庸置疑,LegendClassIndex的作用,正是我们所猜测的那样。于是对图例更新代码做一些修改,如下:
IColorRamp pColorRamp = m_StyleGalleryItem.Item as IColorRamp; m_RasterStretchColorRampRenderer.ColorRamp = pColorRamp; (m_RasterStretchColorRampRenderer as IRasterRenderer).Update(); ILegendInfo pLengendInfo = m_RasterStretchColorRampRenderer as ILegendInfo; ILegendGroup pLegendGroup = pLengendInfo.get_LegendGroup(0); for (int j = 0; j < pLegendGroup.ClassCount; j++) { ILegendClass pLegendClass = pLegendGroup.get_Class(j); pLegendClass.Symbol = new ESRI.ArcGIS.Carto.ColorRampSymbolClass(); ISymbol pSymbol = pLegendClass.Symbol; IColorRampSymbol pColorRampSymbol = pSymbol as IColorRampSymbol; pColorRampSymbol.ColorRamp = pColorRamp; pColorRampSymbol.ColorRampInLegendGroup = pColorRamp; pColorRampSymbol.LegendClassIndex = j; pLegendClass.Symbol = pColorRampSymbol as ISymbol; } (m_RasterStretchColorRampRenderer as IRasterRenderer).Update();
至此问题解决了。下面画个图,说明一下ColorRampSymbol与图例的关系:
![](http://img.my.csdn.net/uploads/201209/19/1348045850_2272.png)
简单说来,就是色彩拉伸后的图例实际上是一个由三个图例项组成的图例组,每个图例项都带有一个ColorRampSymbol,而借助这个ColorRampSymbol也可以指定整个图例组使用的色带,对于这个完整的色带,如何让图例项去自动对应呢,就是靠ColorRampSymbol的LengendClassIndex属性来完成的。
相关文章推荐
- 如何解决栅格色彩拉伸后TocControl里的图例不能更新的问题2
- 如何解决因为找不到Notepad++的安装路径而导致的不能更新CS-Script的问题
- Android SDK代理服务器解决国内不能更新下载问题
- 如何解决使用Java Entity不能插入自增列的问题
- Android SDK代理服务器解决国内不能更新下载问题
- 用 ERD 盘解决 Win8 自己主动更新后不能启动的问题
- 如何解决Sublime Text 3不能正确显示中文的问题
- 安装office2007之windows installer 服务不能更新一个或多个受保护的windows文件问题解决
- 如何解决Ubuntu10.10装ATI驱动后不能进桌面的问题
- Xcode更新后,第三方插件不能用的问题解决方法
- .NETC#下AE二次开发过程中出现的属性表不能更新问题解决办法
- WPF中如何解决3d模型与贴图不能完全匹配的问题
- WPF中如何解决3d模型与贴图不能完全匹配的问题
- 如何解决fedora 13中root用户不能登录的问题
- 如何解决VMware上MAC虚拟机不能上网问题
- 解决TextView数据不能更新的问题以及Android Button事件响应函数的两种方法
- 如何解决USB设备在Windows Vista下不能识别的问题!
- 如何解决Sublime Text 3不能正确显示中文的问题
- 如何解决 Sublime Text 3 不能正确显示中文的问题