『公告』 预祝您龙年大吉,万事如意, 过节期间, 大家如需数据服务,请拨打400 或直接添加客服微信,再祝大家龙年,心想事成。
关注我们 新浪 腾讯

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

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

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

       随着社会的发展、科学的进步,地理信息系统(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();

}

 

 图五 示例程序运行效果

      京ICP备2025132830号-1 京公网安备 号