ArcGIS Engine专题地图渲染器的实现(入门版)
专题地图(Thematic Map)是着重表示一种或数种自然要素特征或社会经济现象的地图
专题地图的内容由两部分构成:
1、专题内容——图上突出表示的自然或社会经济现象及其有关特征
2、地理基础——用以标明专题要素空间位置与地理背景的普通地图内容,主要有经纬网、水系、境界、居民地等。
专题地图制作依据要素的一个或多个不同的属性字段,根据字段值赋予地理对象不同的符号样式或者颜色,以区分不同属性值的地理要素。
ArcGIS Engine提供了8种标准的着色方案,每一种方案都对应了一类特征渲染器(Renderer)。
特征渲染器是绘制专题地图的入口。
特征渲染器使用专题地图的一般性表示方法,如质底法、点值法、分级比例法等,以目标要素类图层的某个字段作为渲染依据,合理渲染不同字段值的要素,直至一个要素类中的所有要素都被渲染。完成渲染工作,配上制图要素——比例尺、指北针、图名、图例等后输出,即可完成一幅专题图的制作。其中,IGeoFeatureLayer的Renderer属性提供了专题图渲染的入口。简言之,通过对目标图层的Renderer属性进行渲染即可完成专题图的渲染工作。
下面将介绍五种渲染器的实现方法
1、简单符号法渲染器
2、分等级法渲染器
3、唯一值法渲染器
4、比例符号法渲染器
5、点状密度法渲染器
还剩下三种渲染器以后再实现
6、图表渲染器
7、分级唯一值法渲染器
8、依比例法渲染器
各类专题图均用的函数
getRGB(int r, int g, int b)
getGeoLayer(string layerName)
#region 各类专题图均用的函数 /// <summary> /// 获得颜色的函数 /// </summary> /// <param name="r">红色Red</param> /// <param name="g">绿色Green</param> /// <param name="b">蓝色Blue</param> /// <returns>返回颜色</returns> private IRgbColor getRGB(int r, int g, int b) { IRgbColor pColor = new RgbColorClass(); pColor.Red = r; pColor.Green = g; pColor.Blue = b; return pColor; } /// <summary> /// 获取渲染图层 /// </summary> /// <param name="layerName">图层名字</param> /// <returns>图层</returns> private IGeoFeatureLayer getGeoLayer(string layerName) { ILayer pLayer; //定义图层 IGeoFeatureLayer pGeoFeatureLayer; //定义要素图层 Geo? //遍历图层 for (int i = 0; i < axMapControl1.LayerCount; i++) { pLayer = axMapControl1.get_Layer(i); //若当前图层不为空且与与layerName的值相同 if (pLayer != null && pLayer.Name == layerName) { //强转成IGeoFeatureLayer pGeoFeatureLayer = pLayer as IGeoFeatureLayer; //返回pGeoFeatureLayer对象 return pGeoFeatureLayer; } } return null; //返回null } #endregion
1、简单符号法渲染器
简单符号法渲染(SimpleRenderer), 用同一个符号绘制所有特征
①设置简单填充符号(SimpleFillSymbol)的颜色、样式、外边界线等参数
②设置简单线型符号(SimpleLineSymbol)的样色和样式等参数
③实例化简单渲染(SimpleRender)对象并设置Symbol、Lable、Description等相关参数
④对指定图层的Render属性赋值, 完成专题图制作
⑤刷新主地图
/// <summary> /// 简单符号法渲染器(SimpleRenderer), 用同一个符号绘制所有特征 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void 简单符号法渲染ToolStripMenuItem_Click(object sender, EventArgs e) { //实例化ISimpleFillSysmbol变量, 提供简单的填充符号类型 ISimpleFillSymbol pSimpleFillSymbol = new SimpleFillSymbolClass(); //设置填充符号的样式——为呈45度的交叉线(xxx) ///Horizontal and vertical crosshatch ++++++. pSimpleFillSymbol.Style = esriSimpleFillStyle.esriSFSCross; //设置填充符号的颜色——红色 pSimpleFillSymbol.Color = getRGB(96, 96, 96); //创建边线符号变量, 提供简单的线条符号类型 ISimpleLineSymbol pSimpleLineSymbol = new SimpleLineSymbolClass(); //设置线符号样式——线呈交替虚线和双点(_.._.._) //The line has alternating dashes and double dots _.._.._. pSimpleLineSymbol.Style = esriSimpleLineStyle.esriSLSDashDotDot; //设置线符号颜色——绿色 pSimpleLineSymbol.Color = getRGB(255, 0, 0); //设置线符号宽度——1.5 pSimpleLineSymbol.Width = 1.5; //将线符号强转成ISymbol符号变量 ISymbol pSymbol = pSimpleLineSymbol as ISymbol; //设置符号属性ROP2为二元栅格esriROPNotXOrPen pSymbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen; //设置填充符号外边界的样式为pSimpleLineSymbol pSimpleFillSymbol.Outline = pSimpleLineSymbol; //实例化简单渲染变量 ISimpleRenderer pSimpleRender = new SimpleRendererClass(); //设置pSimpleRender的符号样式 pSimpleRender.Symbol = pSimpleFillSymbol as ISymbol; //设置标签名称, 用于设置图例 pSimpleRender.Label = "北部湾"; //设置符号描述, 用于设置图例 pSimpleRender.Description = "简单渲染"; //定义IGeoFeatureLayer变量, 提供一个要素图层对成员控制地理特征渲染的入口, 即Renderer属性 IGeoFeatureLayer pGeoFeatureLayer; //调用函数获取渲染图层 pGeoFeatureLayer = getGeoLayer("北部湾"); if (pGeoFeatureLayer != null) { //调用Renderer属性, 具体说明如何通过图层要素渲染器渲染图层 pGeoFeatureLayer.Renderer = pSimpleRender as IFeatureRenderer; } axMapControl1.Refresh(); //刷新axMapControl1 axTOCControl1.Update(); //更新axTOCControl1 }
2、分等级法渲染器
分等级法渲染器(ClassBreakRenderer), 可以用分级的颜色和符号来绘制
①获得目标图层的属性表后赋值到ITableHistogram对象
②利用IBasicHistogram的GetHistogram方法对属性表内数据进行统计
③利用IClassifyGEN分级
④实例化分级渲染器(ClassBreakRenderer),渲染所有地图
⑤赋值目标图层的Renderer, 完成渲染
⑥刷新地图
/// <summary> /// 分等级法渲染器(ClassBreakRenderer), 可以用分级的颜色和符号来绘制 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void 分等级法渲染ToolStripMenuItem_Click(object sender, EventArgs e) { //数据分成10个等级 int classCount = 10; //声明一个ITableHistogram变量 //该变量用于控制从表格中生成的直方图的样式 ITableHistogram pTableHistogram; //声明一个IBasicHistogram变量 //该变量用于控制从不同数据源中生成的直方图 IBasicHistogram pBasicHistogram; //实例化表格对象 ITable pTable; //获取生成分级专题图的目标图层 IGeoFeatureLayer pGeoFeatureLayer; //获取渲染图层 pGeoFeatureLayer = getGeoLayer("北部湾"); //将pGeoFeatureLayer强转成ILayer ILayer pLayer = pGeoFeatureLayer as ILayer; //将目标图层(要素类)的属性表强转成ITable pTable = pLayer as ITable; //实例化 //BasicTableHistogram采用表对象输入数据的结构(如自然断点、分位数)生成直方图。 pTableHistogram = new BasicTableHistogramClass(); //赋值pTableHistogram的Table属性字段 pTableHistogram.Table = pTable; //确定分级字段 pTableHistogram.Field = "年"; //pTableHistogram强制转换为IBasicHistogram pBasicHistogram = pTableHistogram as IBasicHistogram; //先统计每个值出现的次数, 输出结果赋予values, frequencys object values; object frequencys; //out参数可以在一个方法中返回多个不同类型的值 pBasicHistogram.GetHistogram(out values, out frequencys); //创建平均分级对象 IClassifyGEN pClassifyGEN = new QuantileClass(); //用统计结果(values——值, frequences——出现频率)进行分级, 级别数目为classCount pClassifyGEN.Classify(values, frequencys, ref classCount); double[] classes; classes = pClassifyGEN.ClassBreaks as double[]; //获得分级结果, 是个双精度类型数组 //注意:获得双精度数组记录条数出现不可修复性错误, 故使用以下代码修复该错误 double[] myclasses; myclasses = new double[classCount]; //当classes不为null时 if (classes != null) { //遍历classes, 从后往前移一位 for (int j = 0; j < classCount; j++) { myclasses[j] = classes[j + 1]; } } //定义一个颜色枚举变量, 通过函数获取颜色带 IEnumColors pEnumColors = CreateAlgorithmicColorRamp(myclasses.Length).Colors; IColor color; //声明并实例化分级渲染器对象类 //该变量提供成员控制渐变色、渐变符号专题图的制作 IClassBreaksRenderer classBreaksRenderer = new ClassBreaksRendererClass(); //确定分级渲染的属性字段 classBreaksRenderer.Field = "年"; //分级数量 classBreaksRenderer.BreakCount = classCount; //指示该专题图是否按升序显示 classBreaksRenderer.SortClassesAscending = true; //简单填充符号(ISimpleFillSymbol) //该变量提供对成员的访问, 控制简单的填充符号 ISimpleFillSymbol simpleFillSymbol; //通过一个循环, 给所有渲染的等级附上渲染颜色 for (int i = 0; i < myclasses.Length; i++) { color = pEnumColors.Next(); simpleFillSymbol = new SimpleFillSymbolClass(); simpleFillSymbol.Color = color; //设置填充的样式(Style)为实体填充 simpleFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid; //指定分级渲染的符号(Symbol) classBreaksRenderer.set_Symbol(i, simpleFillSymbol as ISymbol); //按照分级进行渲染 classBreaksRenderer.set_Break(i, myclasses[i]); } if (pGeoFeatureLayer != null) { //调用Renderer属性, 具体说明如何通过图层要素渲染器绘制图层 pGeoFeatureLayer.Renderer = classBreaksRenderer as IFeatureRenderer; } axMapControl1.Refresh(); //刷新axMapControl1 axTOCControl1.Update(); //更新axTOCControl1 }
需要用到的函数:CreateAlgorithmicColorRamp(int count)
/// <summary> /// 创建规则的颜色带 /// </summary> /// <param name="count"></param> /// <returns></returns> private IColorRamp CreateAlgorithmicColorRamp(int count) { //创建一个新渐变色带(AlgorithmicColorRampClass)对象 IAlgorithmicColorRamp algColorRamp = new AlgorithmicColorRampClass(); IRgbColor fromColor = new RgbColorClass(); IRgbColor toColor = new RgbColorClass(); //创建其实颜色对象, 采用三原色定律 fromColor.Red = 255; fromColor.Green = 235; fromColor.Blue = 214; //创建终止颜色对象 toColor.Red = 196; toColor.Green = 10; toColor.Blue = 10; //设置AlgorithmicColorRampClass的起止颜色属性 algColorRamp.ToColor = toColor; algColorRamp.FromColor = fromColor; //设置梯度类型 algColorRamp.Algorithm = esriColorRampAlgorithm.esriCIELabAlgorithm; //设置颜色带颜色数量 algColorRamp.Size = count; //创建颜色带 bool bture = true; algColorRamp.CreateRamp(out bture); return algColorRamp; }
注:out参数可以在一个方法中返回多个不同类型的值
3、唯一值法渲染器
唯一值法渲染器(UniqueValueRender)——根据特征的某不同属性值来绘制该特征的符号
①遍历要素类
②获得渲染字段下的值
③使用IUniqueValueRenderer所提供的Addvalue方法渲染各个值
④赋值目标图层的Renderer属性, 完成渲染
⑤刷新地图
/// <summary> /// 唯一值法渲染器(UniqueValueRender)——根据特征的某不同属性值来绘制该特征的符号 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void 唯一值法渲染ToolStripMenuItem_Click(object sender, EventArgs e) { //定义IGeoFeatureLayer变量, 提供一个要素图层对成员控制地理特征的入口 IGeoFeatureLayer geoFeatureLayer = getGeoLayer("北部湾"); //使用查询的方式, 获得参与渲染的记录条数 int get_Count = geoFeatureLayer.FeatureClass.FeatureCount(null); //提供操作唯一值的相关成员 IUniqueValueRenderer uniqueValueRenderer = new UniqueValueRendererClass(); //设置渲染的字段个数范围:0~3个 //这里仅设置1个字段 uniqueValueRenderer.FieldCount = 1; //设置渲染字段, 并制定到索引处 //索引从0开始; 设定渲染字段为"地市名" uniqueValueRenderer.set_Field(0, "地市名"); //简单填充符号 ISimpleFillSymbol simpleFillSymbol; //获得指向渲染要素的游标 IFeatureCursor pFtCursor = geoFeatureLayer.FeatureClass.Search(null, false); IFeature pFeature; if (pFtCursor != null) { //定义枚举颜色带, 调用函数, 生成随机颜色带 IEnumColors enumColors = CreateRandomColorRamp(get_Count).Colors; //查找到"地市名"字段的索引(index) int fieldIndex = geoFeatureLayer.FeatureClass.Fields.FindField("地市名"); while ((pFeature = pFtCursor.NextFeature()) != null) { //获取要素值 string nameValue = pFeature.get_Value(fieldIndex).ToString(); //实例化填充符号 //使用填充符号来赋值地图的背景值 simpleFillSymbol = new SimpleFillSymbolClass(); //给要素附上样式 simpleFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid; //给要素附上颜色 simpleFillSymbol.Color = enumColors.Next() as IColor; //值和符号对应 uniqueValueRenderer.AddValue(nameValue, "地市", simpleFillSymbol as ISymbol); } } //赋值目标图层的渲染器属性 geoFeatureLayer.Renderer = uniqueValueRenderer as IFeatureRenderer; axMapControl1.Refresh(); //刷新axMapControl1 axTOCControl1.Update(); //更新axTOCControl1 }
需要用到的函数:CreateRandomColorRamp(int Number)
/// <summary> /// 创建随机的颜色条带 /// </summary> /// <param name="Number"></param> /// <returns></returns> private IColorRamp CreateRandomColorRamp(int Number) { //请注意色度、饱和度、最大值、最小值、随机种子数等参数的设定 //参数不同, 所产生的色带也不同 IRandomColorRamp pRandomColorRamp = new RandomColorRampClass(); pRandomColorRamp.StartHue = 0; //开始色度 pRandomColorRamp.EndHue = 360; pRandomColorRamp.MinValue = 99; pRandomColorRamp.MaxValue = 100; pRandomColorRamp.MinSaturation = 15; //最小饱和度 pRandomColorRamp.MaxSaturation = 30; //最大饱和度 pRandomColorRamp.Size = Number; //设置颜色带数量 pRandomColorRamp.Seed = 23; //随机数种子 bool bture = true; pRandomColorRamp.CreateRamp(out bture); return pRandomColorRamp; }
4、比例符号法渲染器
比例符号法渲染器(ProportionalSymbolRenderer)——用不同大小的符号绘制要素, 其大小对应某一字段值的比例。
①统计目标字段, 获得相关统计值
②设计标记符号
③补充完整ProportionalSymbolRenderer对象的重要属性值
④赋值目标图层的Renderer属性, 完成渲染
⑤刷新地图
/// <summary> /// 比例符号法渲染器(ProportionalSymbolRenderer)——用不同大小的符号绘制要素, 其大小对应某一字段值的比例。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void 比例符号法渲染ToolStripMenuItem_Click(object sender, EventArgs e) { //声明IGeoFeatureLayer变量, 提供一个要素图层对成员控制地理特征的入口 IGeoFeatureLayer geoFeatureLayer; //声明要素图层 IFeatureLayer pFtLayer; //声明专题图变量 //在利用该方法进行着色时, 需获得最大和最小标识符号所代表的字段及其各个数值, 还需要确定每个字段数值所匹配的着色符号。 IProportionalSymbolRenderer proportionalSymbolRenderer; //声明表格 ITable table; //声明游标 ICursor cursor; //用于统计变量 IDataStatistics dataStatistics; //用于存放统计结果 IStatisticsResults statisticsResults; //声明一个字体对象 stdole.IFontDisp fontDisp; //获取图层 geoFeatureLayer = getGeoLayer("北部湾"); //强转为要素图层 pFtLayer = geoFeatureLayer as IFeatureLayer; //图层类型转换成表 table = geoFeatureLayer as ITable; //获取游标 cursor = table.Search(null, true); //实例化数据统计对象 dataStatistics = new DataStatisticsClass(); //赋游标给数据统计对象的游标 dataStatistics.Cursor = cursor; //获取图层要素中进行专题地图制图的字段名称, 此实例中所用的数据中字段名为"年"(2010年GDP增长速率) dataStatistics.Field = "年"; //存放统计结果为统计对象的统计数据 statisticsResults = dataStatistics.Statistics; //如果统计结果不为空 if (statisticsResults != null) { //简单填充符号 IFillSymbol fillSymbol = new SimpleFillSymbolClass(); //设置颜色 fillSymbol.Color = getRGB(195, 255, 255); //设置简单线型符号 ISimpleLineSymbol SLS = new SimpleLineSymbolClass(); SLS.Color = getRGB(196, 196, 196);//颜色 SLS.Width = 1.5;//宽度 fillSymbol.Outline = SLS;//外边界线 //利用ESRI特殊符号调用成员进行填充 ICharacterMarkerSymbol characterMarkerSymbol = new CharacterMarkerSymbolClass(); fontDisp = new stdole.StdFontClass() as stdole.IFontDisp; //调用指定子库(ESRI Default Marker是子库名称) fontDisp.Name = "ESRI Default Marker"; //对characterMarkerSymbol的font属性 characterMarkerSymbol.Font = fontDisp; //特征标记符号(Character Marker Symbol)的索引值 //0xB6是C#特殊的16进制表示方法, 换算为十进制值182 characterMarkerSymbol.CharacterIndex = 0xB6; //特征标记符号的颜色 characterMarkerSymbol.Color = getRGB(253, 191, 110); //设计特征标记符号的尺寸 characterMarkerSymbol.Size = 18; //实例化一个比例符号渲染器 proportionalSymbolRenderer = new ProportionalSymbolRendererClass(); proportionalSymbolRenderer.ValueUnit = esriUnits.esriUnknownUnits; //获取渲染字段 proportionalSymbolRenderer.Field = "年"; //是否启用颜色补偿(默认为否) proportionalSymbolRenderer.FlanneryCompensation = false; //赋值统计数据(比例符号渲染器) //MinDataValue获取数据中最小值 proportionalSymbolRenderer.MinDataValue = statisticsResults.Minimum; //获取数据中最大值 proportionalSymbolRenderer.MaxDataValue = statisticsResults.Maximum; //在多边形特征上绘制比例标记符号时使用的背景填充符号 proportionalSymbolRenderer.BackgroundSymbol = fillSymbol; //用于绘制具有规格化最小数据值的特征的符号。 proportionalSymbolRenderer.MinSymbol = characterMarkerSymbol as ISymbol; //目录和图例中显示的符号数为3 proportionalSymbolRenderer.LegendSymbolCount = 3; //创建图例, 设置完所有属性后调用。 proportionalSymbolRenderer.CreateLegendSymbols(); //赋值目标图层的渲染器属性 geoFeatureLayer.Renderer = proportionalSymbolRenderer as IFeatureRenderer; } axMapControl1.Refresh(); //刷新axMapControl1 axTOCControl1.Update(); //更新axTOCControl1 }
5、点状密度法渲染器
点状密度法渲染器(DotDensityRenderer)——在多边形特征中绘制不同密度的点
①制作点符号
②使用IDotDensityFillSymbo包装制作好的符号
③赋值点密度渲染(dotDensityRenderer)的点密度符号(DotDensitySymbol)属性
④赋值其它参数
⑤赋值目标图层的Renderer属性, 完成渲染
⑥刷新地图
/// <summary> /// 点状密度法渲染器(DotDensityRenderer)——在多边形特征中绘制不同密度的点 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void 点状密度法渲染ToolStripMenuItem_Click(object sender, EventArgs e) { //声明IGeoFeatureLayer变量, 提供一个要素图层对成员控制地理特征的入口 IGeoFeatureLayer geoFeatureLayer; //定义点密度填充符号变量, 控制点符号的属性 IDotDensityFillSymbol dotDensityFillSymbol; //定义点密度渲染对象 IDotDensityRenderer dotDensityRenderer; //获取渲染图层 geoFeatureLayer = getGeoLayer("北部湾"); //实例化点密度渲染对象 dotDensityRenderer = new DotDensityRendererClass(); //强转点密度渲染对象并强转成渲染字段对象 IRendererFields rendererFields = dotDensityRenderer as IRendererFields; //设置渲染字段 string field1 = "年"; //向渲染器添加字段(字段名、别名) rendererFields.AddField(field1, field1); //实例化点密度填充符号 dotDensityFillSymbol = new DotDensityFillSymbolClass(); dotDensityFillSymbol.DotSize = 4;//设置点的大小 dotDensityFillSymbol.Color = getRGB(0, 255, 0);//设置点的颜色 //将点密度填充符号强转为符号数组成员 ISymbolArray symbolArray = dotDensityFillSymbol as ISymbolArray; //实例化简单标记符号 ISimpleMarkerSymbol simpleMarkerSymbol = new SimpleMarkerSymbolClass(); //设置点的符号为圆圈 simpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle; simpleMarkerSymbol.Size = 4;//设置大小 simpleMarkerSymbol.Color = getRGB(0, 255, 0);//设置颜色 //点符号的外边不填充颜色 simpleMarkerSymbol.OutlineColor = getNoRGB(); //将简单标记符号样式增加到符号数组成员中 symbolArray.AddSymbol(simpleMarkerSymbol as ISymbol); //赋值点密度渲染(dotDensityRenderer)的点密度符号(DotDensitySymbol)属性 dotDensityRenderer.DotDensitySymbol = dotDensityFillSymbol; //设置渲染密度 dotDensityRenderer.DotValue = 0.003; //设置点密度填充符号的背景色 dotDensityFillSymbol.BackgroundColor = getRGB(255, 255, 255); //创建图例 dotDensityRenderer.CreateLegend(); //赋值目标图层的渲染器属性 geoFeatureLayer.Renderer = dotDensityRenderer as IFeatureRenderer; axMapControl1.Refresh(); //刷新axMapControl1 axTOCControl1.Update(); //更新axTOCControl1 }
需要用到的函数:getNoRGB()
/// <summary> /// 不填充颜色 /// </summary> /// <returns></returns> private IColor getNoRGB() { IRgbColor pColor = new RgbColorClass(); //.NullColor指示此颜色是否为空。true表明颜色为空 pColor.NullColor = true; return pColor;//返回pColor }
谢谢观看!本人初学GIS二次开发,如果有不对的地方,请多多包涵!