全国高分辨率土地利用数据服务 土地利用数据服务 土地覆盖数据服务 坡度数据服务 土壤侵蚀数据服务 全国各省市DEM数据服务 耕地资源空间分布数据服务 草地资源空间分布数据服务 林地资源空间分布数据服务 水域资源空间分布数据服务 建设用地空间分布数据服务 地形、地貌、土壤数据服务 分坡度耕地数据服务 全国大宗农作物种植范围空间分布数据服务
多种卫星遥感数据反演植被覆盖度数据服务 地表反照率数据服务 比辐射率数据服务 地表温度数据服务 地表蒸腾与蒸散数据服务 归一化植被指数数据服务 叶面积指数数据服务 净初级生产力数据服务 净生态系统生产力数据服务 生态系统总初级生产力数据服务 生态系统类型分布数据服务 土壤类型质地养分数据服务 生态系统空间分布数据服务 增强型植被指数数据服务
多年平均气温空间分布数据服务 多年平均降水量空间分布数据服务 湿润指数数据服务 大于0℃积温空间分布数据服务 光合有效辐射分量数据服务 显热/潜热信息数据服务 波文比信息数据服务 地表净辐射通量数据服务 光合有效辐射数据服务 温度带分区数据服务 山区小气候因子精细数据服务
全国夜间灯光指数数据服务 全国GDP公里格网数据服务 全国建筑物总面积公里格网数据服务 全国人口密度数据服务 全国县级医院分布数据服务 人口调查空间分布数据服务 收入统计空间分布数据服务 矿山面积统计及分布数据服务 载畜量及空间分布数据服务 农作物种植面积统计数据服务 农田分类面积统计数据服务 农作物长势遥感监测数据服务 医疗资源统计数据服务 教育资源统计数据服务 行政辖区信息数据服务
Landsat 8 高分二号 高分一号 SPOT-6卫星影像 法国Pleiades高分卫星 资源三号卫星 风云3号 中巴资源卫星 NOAA/AVHRR MODIS Landsat TM 环境小卫星 Landsat MSS 天绘一号卫星影像
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中那样显示为三维立体的效果呢?MapObjects的ChartRenderer中提供了自定义图表的方法,也就是把ChartType设置为ChartTypeConstants中的moCustom,然后把ChartRenderer的CustomChart属性设置为我们自定义图表对象就可以了。
话是如此,但是如何创建这个自定义图表对象呢,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();
}
图五 示例程序运行效果