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二次開發,如果有不對的地方,請多多包涵!