65.9K
CodeProject 正在变化。 阅读更多。
Home

用于构建 GIS 和 CAM 应用程序的绘图组件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (13投票s)

2005年11月21日

5分钟阅读

viewsIcon

110122

downloadIcon

8064

一个面向对象的绘图组件,用于构建具有多视图几何模型、多分辨率处理、图层、优化图形等功能的GIS和CAM应用程序。

引言

CanvasGIS 是一个面向对象的二维图形绘图组件。它是 MVisionTech 开源 GIS 和数据可视化框架的一部分。CanvasGIS 已被用于我上一篇文章中介绍的 GisMap 组件。

许多应用程序需要二维图形来提供图形输入并表示不同类型的数据。二维数据呈现的一些示例如下:显示数值数据的图表、表示道路和其他地理对象几何的地图、表示对象关系的图表以及CAD/CAM工具。Canvas 旨在创建一个能够服务于所有这些目的的组件。

不同类型的图形应用程序在功能和需求上存在一些共性:

  • 绘制不同种类的形状并进行图形化操作。
  • 导航几何数据,包括缩放、平移和数据图层选择。
  • 更改显示参数,例如颜色、线条样式等。
  • 为不同比例尺创建数据的不同显示方式,例如,在低分辨率显示地图时,只显示主要道路和国家边界;当用户放大时,显示街道和其他更精细的细节。
  • 创建同一几何数据的多个视图。
  • 执行图形数据操作,创建新对象,并维护显示与实际数据之间的连接。创建、编辑和删除几何对象。
  • 处理不同坐标系统的数据。在不同坐标系统之间进行数据转换。
  • 为不同形状事件创建句柄。事件包括形状创建、编辑、移动和删除。

图层、比例尺和图形优化

处理大量的图形需要特殊的数据结构和优化。考虑显示一个国家道路的场景。当用户缩小以一起查看所有道路时,地图会布满线条(即使是一个小国家),并且这些线条需要很长时间才能绘制。另一方面,当用户放大地图查看一条街道时,需要花费太多时间来找出应该显示的线条(多边形裁剪)。

处理不同详细级别(多分辨率)数据的一种方法是引入在不同比例尺下具有不同可见性的图形图层。在下面的示例中,我们为地球图像和某个城市的航空照片创建了不同的图形图层,并用多边形勾勒出建筑物的边界。

地球图像在 0.1 到 0.5 的范围之间可见(使用图层最小和最大比例尺参数)。

航空照片的范围在 0.5 到 8 之间,因此当我们放大地图时,它会关闭地球图像并打开航空照片。GisMap GIS 组件使用此功能在不同分辨率的地理数据之间切换。

当然,为我们需要的每种分辨率都设置不同的图层是不现实的,因此我们使用了额外的优化技术:

  • 多边形简化 - 没有必要显示我们看不到的东西,例如,我们无法看到屏幕上小于一像素的偏差。因此,根据特定的分辨率,我们可以将原始多边形近似为一个具有更少点的简单多边形。我们采用的方法是连续细分一个简单多边形(近似),直到简单多边形与原始多边形之间的距离(近似误差)小于 1 像素。
  • 几何数据结构 - 有各种数据结构用于加速几何数据,例如范围树、四叉树等。我们目前使用的是具有相等单元格尺寸的网格的图形形状的简单细分。网格中的每个单元格都包含指向包含在单元格中的几何形状的引用。因此,当用户放大到某个区域时,该区域中包含的所有单元格都会显示出来。

使用组件

Canvas 包含两个命名空间:CanvasControlGeomModelCanvasControl 是视图/模型模式中的视图,而 GeomModel 是模型。

using GeomModel;
using CanvasControl;

为了在画布上绘制形状,可以使用“创建形状”方法之一。例如,绘制一条线

 canvas1.CreateLine();

调用方法后,画布将进入绘制状态,以便用户可以绘制形状。有创建直线、矩形和多边形的方法,它也可以被其他形状重用,例如,椭圆可以从矩形派生。

 // create initial shape:
 EllipseCanvasItem ei = new EllipseCanvasItem(canvas1.CurrentLayer);
 // set canvas to rectangle drawing mode:
 canvas1.setMode(CanvasControl.Canvas.DrawingMode.Rectangle);
 // create shape from selected rectangle
 canvas1.CreateShape(ei);

也可以直接在画布上创建形状,而无需用户绘制。

// create polygon
ArrayList pi = new ArrayList();
pi.Add(new PointF(0,0));
pi.Add(new PointF(10,0));
pi.Add(new PointF(10,10));
pi.Add(new PointF(20,20));
// create polygon shape and put it to the canvas
PolygonCanvasItem pi = new PolygonCanvasItem(pi,canvas1.CurrentLayer);
canvas1.AddShape(pi);

画布中的形状按图层组织。图层定义了形状的颜色以及形状在画布中显示的顺序。也可以为一组形状创建一个新形状。

 GeomModel.CanvasLayer lay = 
    new GeomModel.CanvasLayer("new-layer",Color.Blue,0,true);

可以为图层分配不同的属性,例如线条颜色、填充颜色、线宽以及比例尺范围(最小到最大),在该范围内的形状组将可见。最后一个特性用于显示地理地图,其中每个比例尺都有不同的详细程度。

可以将委托分配给形状以处理不同的事件,例如,处理用户单击形状时发生的查找形状事件(画布应处于“查找”模式)。

// connect delegate to find event
this.canvas1.ItemFindEvent += 
  new CanvasControl.Canvas.ItemEventHandler(this.canvas1_ItemFindEvent);
...
// event handler
private void canvas1_ItemFindEvent(object sender, 
                                   GeomModel.ItemEventArgs e)
{
    m_selected = e.indx;
    // show shape properties in property grid:
    propertyGrid1.SelectedObject = canvas1.GetItem(e.indx);
    MessageBox.Show("Item:"+e.indx+"found");
}

设计

Canvas 包含两个主要类 CanvasGeomModel,它们实现了 Model/View 设计模式。

  • Canvas 是几何模型 (GeomModel) 的视图,它在视图和几何模型之间持有客户端到实际世界的转换。当视图因缩放、平移或重调大小而改变时,Canvas会将请求传递给几何模型,以使用改变后的转换绘制其视图中所有可见的形状。
  • GeomModel 保持所有从 CanvasItem 基类派生的形状,并按图层组织。可以将多个 Canvas 连接到同一个 Model。当 Model 发生变化时,所有 Canvas 都会收到通知并相应地更新其视图(Model/View 设计模式)。
  • CanvasLayer 保持一组形状的显示属性。
  • CanvasItem 是 Canvas 中形状的基类。可以通过实现 CanvasItem 接口将新形状添加到 Canvas 中。
  • PolygonCanvasItemPointCanvasItemImageCanvasItem 等是 CanvasItem 接口的不同实现。
© . All rights reserved.