http://www.gissky.net- GIS空间站

我要投稿 投稿指南 RSS订阅 网站资讯通告:
搜索: 您现在的位置: GIS空间站 >> 技术专栏 >> ArcGIS >> MapObjects >> 正文

在.NET中使用GDI+为MapObjects构建三维直方图统计

作者:钟良吉    文章来源:本站原创    点击数:    更新时间:2006-7-3
摘要:ESRI公司的GIS开发组件MapObjects中也提供了丰富的专题图功能,如:图表专题(包括直方图和饼图)、独立值、点密度、分类分级等。使用过MapObjects进行专题开发的人会发现:其中图表专题中MapObjects提供的图表显示是平面二维的,显示效果极其平淡,没有ArcMap中图表专题里的那种三维立体效果。有没有办法使这些图表象ArcMap中那样显示为三维立体的效果呢?MapObjects的ChartRenderer中提供了自定义图表的方法,也就是把ChartType设置为ChartTypeConstants中的moCustom,然后把ChartRenderer的CustomChart属性设置为我们自定义图表对象就可以了。

随着社会的发展、科学的进步,地理信息系统(GIS)技术在社会的各个领域中的应用越来越广泛。其中专题图在地理信息系统应用中具有非常重要的作用、专题图的应用大大增强信息表达的直观性。目前在GIS软件领域各种GIS软件平台以及GIS开发组件都提供了丰富的专题图设置功能。

ESRI公司的GIS开发组件MapObjects中也提供了丰富的专题图功能,如:图表专题(包括直方图和饼图)、独立值、点密度、分类分级等。使用过MapObjects进行专题开发的人会发现:其中图表专题中MapObjects提供的图表显示是平面二维的,显示效果极其平淡,没有ArcMap中图表专题里的那种三维立体效果。有没有办法使这些图表象ArcMap中那样显示为三维立体的效果呢?MapObjectsChartRenderer中提供了自定义图表的方法,也就是把ChartType设置为ChartTypeConstants中的moCustom,然后把ChartRendererCustomChart属性设置为我们自定义图表对象就可以了。

话是如此,但是如何创建这个自定义图表对象呢,MapObjects 提供了ICustomChart接口,我们要做的就是实现这个接口。在一般的开发语言中我们需要通过底层的API绘图函数来实现其中图形方面的操作,不过在.NET中我们可以使用强大的GDI+来实现这些操作,下面我们以C#.Net为例使用GDI+实现ICustomChart接口,创建美观、大方、直观、立体感强的三维直方图统计专题。

第一步:新建一个C#类库项目CustomChartRenderer(图一)

图一 新建类库项目CustomChartRenderer

 

第二步:添加程序集的应用。ESRI.MapObjects2.Core ESRI.MapObjects2.Custom并继承 ESRI.MapObjects2.Custom.ICustomChart(图二、三)

图二 添加程序集的应用

 

图三 对我们创建的类添加对ICustomChart的继承

 

 

第三步:添加对ICustomChart继承接口的实现。在.NET开发界面的类似图中找到ICustomChart接口,点击右键菜单中的“添加”——>“实现接口”(图四)

图四 添加对ICustomChart接口的实现

 

    “实现接口”后我们的代码中会多了如下三个函数,我们要做的也就是完成这三个函数在渲染的过程中执行的顺序为SetupDC——> Draw——> ResetDC

#region ICustomChart 成员
public void ResetDC(int hDC)
{
    
// TODO:  添加 Custom3DBarRenderer.ResetDC 实现
}
public void SetupDC(object Map, object MapLayer, object ChartRenderer, int hDC, double dpi)
{
    
// TODO:  添加 Custom3DBarRenderer.SetupDC 实现
}
public void Draw(int hDC, int x, int y, ref double[] values, double normValue, double sizeValue)
{
    
// TODO:  添加 Custom3DBarRenderer.Draw 实现
}
#endregion 

 

第四步:添加成员变量、属性和自定义函数,自定义函数Setup3DBarRenderer主要负责对数据进行预处理和统计计算,计算图表渲染中的最大值,以便根据数值的大小分配直方图柱子的高度。

private int[] m_iColors;                  //记录直方条的颜色
private float    m_MaxBarHeight = 50;       //直方图的最大高度
private float    m_MinBarHeight = 1;        //直方图的最小高度
private float    m_BarWidth = 10;           //直方图的宽度
private float    m_fTotal = 0;              //用于记录统计字段中的最大直
private
bool     m_blDrawOutline = true;    //是否绘制边框
private System.Drawing.Color m_OutlineColor = System.Drawing.Color.Black; //边框的颜色

public
void Setup3DBarRenderer(ESRI.MapObjects2.Core.MapLayer lyr,ESRI.MapObjects2.Core.ChartRenderer cr)
{
    
if(lyr != null && cr != null)
     {            
        
//初始化颜色数组根据FieldCount动态创建
         this.m_iColors = new int[cr.FieldCount];
        
for(short i=0;i<cr.FieldCount;i++)
         {
             
this.m_iColors[i] = int.Parse(cr.get_Color(i).ToString());  
         }
         ESRI.MapObjects2.Core.Recordset rec;
        
float fTotal = 0;
         rec = lyr.Records;
        
while (!rec.EOF)
         {                 
             
for(short i = 0 ; i < cr.FieldCount - 1;i++)
              {
                  
float fTemp = float.Parse(rec.Fields.Item(cr.get_Field(i)).ValueAsString);
                  
if(fTotal < fTemp)
                   {
//保存最大的值 以便计算绘制直方图的高
                       fTotal = fTemp;
                   }
              }                 
              rec.MoveNext();
         }
        
this.m_fTotal = fTotal;
     }
}

// 公开一些属性以便根据需要进行修改
public float
BarWidth { get; set; }
public bool
DrawOutline { get; set; }
public float
MaxBarHeight { get; set; }
public float
MinBarHeight { get; set; }
public Color
OutlineColor { get; set; }

 

第五步:实现继承的接口ESRI.MapObjects2.Custom.ICustomChart中的方法Draw()

public void Draw(int hDC, int x, int y, ref double[] values, double normValue, double sizeValue)
{
    
// TODO:  添加 Custom3DBarRenderer.Draw 实现
     float iBarHeight = 0;
    
float iBarWidth  = 0;
     System.Drawing.Graphics g = System.Drawing.Graphics.FromHdc(
new System.IntPtr(hDC));         //创建Graphics对象
     g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;       
//消除图形的锯齿
     System.Drawing.SolidBrush tempBrush =
null;
     System.Drawing.Pen pOutLine =
new System.Drawing.Pen(new System.Drawing.SolidBrush(this.m_OutlineColor),0.2f);
     iBarWidth  =
this.m_BarWidth;
    
float CurrentX,CurrentY;
     CurrentX = x -
this.m_BarWidth * values.Length / 2;
     CurrentY = y;
    
for(int i=0;i<values.Length;i++)
     {
        
//创建画刷 并计算矩形的高度
         tempBrush =  new System.Drawing.SolidBrush(System.Drawing.ColorTranslator.FromWin32(this.m_iColors[i]));
         iBarHeight = System.Convert.ToSingle((values[i] *
this.m_MaxBarHeight/this.m_fTotal).ToString());
        
if(iBarHeight < this.m_MinBarHeight)
         {
              iBarHeight =
this.m_MinBarHeight;
         }
        
if(iBarHeight > this.m_MaxBarHeight)
         {
              iBarHeight =
this.m_MaxBarHeight;
         }
        
//绘制矩形
         System.Drawing.PointF[] pRect = new System.Drawing.PointF[4];
         pRect[0].X = CurrentX;
         pRect[0].Y = CurrentY;
         pRect[1].X = CurrentX + iBarWidth ;
         pRect[1].Y = CurrentY;
         pRect[2].X = CurrentX + iBarWidth ;
         pRect[2].Y = CurrentY - iBarHeight;
         pRect[3].X = CurrentX;
         pRect[3].Y = CurrentY - iBarHeight; 
        
//绘制矩形顶部的阴影
         System.Drawing.PointF[] pTopFill = new System.Drawing.PointF[4];
         pTopFill[0].X = CurrentX;
         pTopFill[0].Y = CurrentY - iBarHeight;
         pTopFill[1].X = CurrentX + iBarWidth ;
         pTopFill[1].Y = CurrentY - iBarHeight;
         pTopFill[2].X = CurrentX + iBarWidth * 3/2 ;
         pTopFill[2].Y = CurrentY - iBarHeight - iBarWidth * 1/2;
         pTopFill[3].X = CurrentX + iBarWidth * 1/2 ;
         pTopFill[3].Y = CurrentY - iBarHeight - iBarWidth * 1/2;             

         CurrentX = CurrentX +iBarWidth; 
        
//斜面阴影部分
         System.Drawing.PointF[] pShadow= new System.Drawing.PointF[4];
         pShadow[0].X = CurrentX;
         pShadow[0].Y = CurrentY;
         pShadow[1].X = CurrentX + iBarWidth/2 ;
         pShadow[1].Y = CurrentY - iBarWidth/2;
         pShadow[2].X = CurrentX + iBarWidth/2 ;
         pShadow[2].Y = CurrentY - iBarHeight - iBarWidth * 1/2;
         pShadow[3].X = CurrentX  ;
         pShadow[3].Y = CurrentY - iBarHeight;                  

         //绘制3D图形 包括正面、斜面、顶部
         g.FillPolygon(tempBrush,pRect);               
         g.FillPolygon(
new HatchBrush(HatchStyle.Percent50,tempBrush.Color),pTopFill);
         g.FillPolygon(tempBrush,pShadow);
        
//如果设置了绘制边界线 则绘制边界
         if(this.m_blDrawOutline)
         {
              g.DrawPolygon(pOutLine,pRect);
              g.DrawPolygon(pOutLine,pTopFill);
              g.DrawPolygon(pOutLine,pShadow);
         }                     
     }
}

 

最后,建立测试工程应用我们创建的三维直方图统计专题(点击按扭为地图设上此专题),看看设置完成后的效果,是不是比普通的二维直方图更好呢?。关键代码如下:

prprivate void button1_Click(object sender, System.EventArgs e)
{
        
//取得图层
         ESRI.MapObjects2.Core.MapLayer lyr =
this.axMap1.Layers.Item(0) as ESRI.MapObjects2.Core.MapLayer;
        
//创建ChartRenderer对象 并使用moCustom类型
         ESRI.MapObjects2.Core.ChartRenderer pChartRenderer =
new ESRI.MapObjects2.Core.ChartRendererClass();
         pChartRenderer.FieldCount = 3;
         pChartRenderer.set_Field(0, "GDP");
         pChartRenderer.set_Color(0,(
uint)ESRI.MapObjects2.Core.ColorConstants.moRed);
         pChartRenderer.set_Field(1,"AGRICULTUR");
         pChartRenderer.set_Color(1,(
uint)ESRI.MapObjects2.Core.ColorConstants.moYellow);
         pChartRenderer.set_Field(2,"Industry");
         pChartRenderer.set_Color(2,(
uint)ESRI.MapObjects2.Core.ColorConstants.moGreen);
         pChartRenderer.ChartType = ESRI.MapObjects2.Core.ChartTypeConstants.moCustom;

         //创建Custom3dBarRenderer对象并赋值给pChartRenderer       
         Gissky.Common.Mo.CustomChartRenderer.Custom3DBarRenderer r =
new Gissky.Common.Mo.CustomChartRenderer.Custom3DBarRenderer();
         r.Setup3DBarRenderer(lyr,pChartRenderer);
         pChartRenderer.CustomChart = r;
          lyr.Renderer = pChartRenderer;
         this.axMap1.CtlRefresh();
}

 

图五 示例程序运行效果

Tags:GIS,Arcgis,MapObjects  
责任编辑:gissky
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 中国地图