发表用户:clq
收集整理:James.Liu
相关讨论:http://www.mygis.com.cn/forum/dispbbs.asp?boardID=4&ID=1609
信息原始来源:不祥

文章标题:MapX教程关键技术分析与重难点

一、       地图的获取

空间地理数据的获取方式

地理信息系统的最主要特点是能以电子地图的形式,直观地表现背景地物信息,并可做图文互查、综合分析等。因此,在系统开发的最初阶段,首要的问题就是准备一张包括相关地理信息的电子地图。

空间地理数据的获取主要有以下几种方式:

Ø         使用数字化仪

使用手扶跟踪数字化仪,通过人工选点或跟踪线段产生坐标数据。一般用于比较规则的地图或原图质量不太理想的地图,可利用AUTOCAD软件进行编辑修改。

Ø         利用扫描仪

利用扫描仪把图纸信息扫描后以栅格数据结构形式存储,再经其它图象处理软件进一步处理改善图象质量,如图形拼接、降噪、细化等,并把栅格数据转换为矢量数据格式。这种方式要求图纸质量较好软件自动化程度高,交互式工具方便可靠。

Ø         键盘键入

顾名思义,就是通过手工在计算机终端上输入地图数据。

Ø         购买商业性数据

商业性数据可以拿来直接使用。目前电子地图作为一种信息商品,日益受到各界青睐,常见的产品有:卫星影象图——地球资源卫星获得的地表景观影象数据;电子地形图——通过分层技术将多种地理要素分成独立的信息层,每层具有同一属性的地理要素,如等高线、行政界线、道路、水系等;专题电子地图——如土壤类型图、人口专题图等。

Ø         从其它部门获得数字拷贝

根据某些部门标准的原始数据文件,进行数据格式转换,最终形成MapInfo可以识别的数据格式。MapInfo虽然没有公开其内部的数据结构,但它给出了用于格式交换的数据结构,即MIF与MID,其中MIF文件保存图形,MID文件保存文本数据。将其它形式的地图数据转成MIF与MID格式,然后利用MapInfo菜单中的Import命令就可以导入,从而完成转换。另外,MapInfo也支持标准的AUTOCAD数据格式.DXF。

应用分析

在上面谈到的多种方式中,前两种方式获取数据比较精确,也十分专业,但是均需要购买昂贵的专用设备及数字化软件包(常用的有AUTOCADCorelDraw等),成本太高;纯粹的手工操作费时费力,容易出错,已无法满足现时的需要。

在世行项目中,主要涉及到陕西省行政界线、灌区位置等地理信息,地理数据精度要求不高,不牵涉复杂的拓扑关系及计算。

开始,希望能够直接得到标准的矢量地图数据。在网上反复查找,能够利用的只有“图行天下”网站(WWW.GO2MAP.COM)可供下载的栅格数据。于是,最终采用的方法如下:

(1)、          下载陕西省行政区界地图,存成栅格文件;

(2)、          MapInfo中调入该文件,设置投影方式;

(3)、          以配准后得到的地图为蓝本,采用手工绘制方法,自定义新的图层并绘制相关地理对象,包括行政区划界线、灌区位置、地级市等;

配准方法与投影选择

栅格图象也称为位图,由象素组成。MapInfo支持BMPGIFJPEGPCXSPOTTARGATIFF七种栅格图象文件格式。

MapInfo中打开栅格文件时会显示一个信息框,询问是只简单显示还是要进行配准。如果选择简单显示,则MapInfo自动生成一个与该栅格文件同名的.TAB文件,并在地图窗口中显示,此时的图层称为栅格图层。栅格图象只用于显示栅格图层,而不能象矢量图象图层那样附加数据,因此最适合用作矢量图象图层的背景,从而提供比矢量图象更细致的图象。

如果要同时使用栅格图象与矢量图象则必须首先进行图象配准,这样,MapInfo才能在地图窗口中确切地放置图象。配准过程在图象配准对话框中进行,主要有两方面的工作,一是提供准确的控制点信息,二是指定栅格图象的投影。

实际应用中,将从WWW.GO2MAP.COM下载的多幅gif格式的地图在图形处理软件中进行拼接,最终形成一幅完整的陕西省地图,并存为.BMP文件。在MapInfo中打开,新建图层并覆盖在该BMP图象之上,将其作为编辑矢量地图图层的参考。这种基于屏幕图象来进行编辑的过程称为“屏幕数字化”。

由于此处栅格图象只用作背景参考,因此不必进行栅格图象配准;倘若与矢量图象一起使用,则必须进行配准。

投影是一种方法,用于减少球面上的对象显示在平面上时产生的变形。有许多不同类型的投影,每种投影都是针对某一给定区域的,但是允许使用不同的投影来显示同一幅地图。投影最常用于数字化有明确投影的地图。

坐标系是与投影密切相关的一个概念。一个坐标系是一组参数,说明如何判断对象的定位坐标,其中一个参数就是投影。因此可以认为投影是坐标系的一部分。

地图可以区分为地球地图何非地球地图两类,通常需要进行不同的处理。地球地图包含在地球表面有特定位置的对象,坐标一般用经纬度代表对象的位置;非地球地图包含在地球表面没有特定位置的对象且其对象并不显式地参照地球表面位置的地图,如楼层平面图地功能。非地球地图不包含投影。

小结

充分利用现有资源,发挥栅格图在矢量图层建立过程中的作用,大大减少了地图的准备工作,降低了开发过程中的设备投入和成本,缩短了系统的开发周期。因此选用栅格图作为背景地图,无疑对地理信息系统的开发起到很大的帮助。

在数据准备过程中,深刻体会到国家基础地理数据的缺乏。几个大型的GIS专业网站基本上只提供地图的在线浏览和查询,用户无法直接使用相关的地图数据;商品化的地理数据也并不完善;只有国家基础地理信息系统网站提供一些数据的下载,包括国界、省级行政区划、一级河流、二级河流等,无法进行进一步细致的开发。

二、       地图数据与属性数据的关联

开发过程中涉及的数据主要包括两个来源:一部分是Geoset中包含的地图数据文件,即Djqh.tabDjs.tabGq.tab;其它所有的非几何数据即属性数据均由MS SQL Server管理。因此,要实现图文互动,必须建立几何数据和属性数据之间的关系。

MapX支持的外部数据

MapX中可以引用多种类型的外部数据。

(1)、         地图数据:如果用户已经购买了或是利用MapInfo创建了MapInfo地图,可以直接将它们在应用中打开。

(2)、         远程空间数据库:利用MapX可以访问保存在Oracle8iMapInfo SpatialWare中的地图数据。其中,对Oracle8i的支持是MapX 4.0的新特性。通过Oracle8 Call InterfaceOCI),MapX可以将存储在Oracle8i数据库服务器中的MapInfo空间数据和属性数据同时下载到本地。

(3)、       其它远程数据:MapX支持多种对外远程数据的访问方式,如ADODAO、及RDO等,更可以通过ODBC使用更广范围内的数据。

数据库设计原则

GIS系统中涉及的数据包括图形矢量数据、空间属性数据和工程管理数据。为了增强整个系统数据处理的灵活性,采用分开存储的方法。图形矢量数据以MapInfo标准文件格式存储在特定目录下,图形中每个地物均有其对应的唯一的标识(ID号),系统以此为索引建立该地物的图形数据文件。空间属性数据与工程管理数据均采用MS SQL Server来存储,各地物属性记录的关键字为图形文件中该地物的ID号,由此便实现了图形文件与属性文件的一一对应关系。

3.1  图形数据与属性数据的关联关系

关联属性数据的方法

MapX中,属性数据与几何数据的关联是通过数据绑定实现的。

(1)、          什么叫数据绑定

数据绑定是将外部数据引入MapX的过程。

可以绑定的数据源包括以下类型:

类型

描述

ADO

使用ADOActive data objects

DAO

DAO对象,可以是VB中的data controlAccess表格等,也可自己创建

Delphi

使用Borland BDE数据源

Global Handle

lets you pass in a block of tab-delimited data

Layer

创建一个Dataset,使用MapInfo表字段

Notes View/NotesQuery

专门用于Lotus Notes

ODBC

可以使用ODBC从任何ODBC数据源中获取数据

OLE Data

用于containers,如PowerBuilder

RDO

MS Remote Data ObjectsRDO结果集对象

safeArra

COM数据集,与safearray中的数据进行静态绑定

Unbound

兼容其它

(2)、          数据绑定的强大作用

数据绑定主要有两个作用。

Ø       以地图中的图形对象来显示数据

通过数据绑定,可以将BindLayer对象作为一个参数,使用Datasets.Add方法将自己的表转变为一个DataSet。这将在地图中创建一个新的图层,并且将表中的数据以点等图形对象表示。一旦将数据引入地图,就可以很容易地使用MapX创建应用程序,并实现多种地图功能。

Ø       将属性数据绑定到地图中,并创建专题图

如果地图对象中包含相应的属性信息,也可以使用Datasets.Add方法将某个属性字段添加到地图中,进而就可以按照需要创建相关的专题图。

(3)、          数据绑定的实现方法

使用Datasets.Add可以将用户数据绑定到地图中。

MapX中,每张地图对应多个图层(Layers),每一个图层(Layer)都有一个Datasets,其中包含DataSet对象。Datasets拥有一些属性和方法,用来在集合中添加和删除Dataset 对象,主要方法包括AddRemove

使用Datasets.Add绑定的最终结果是Dataset对象的创建。这个Dataset对象被加入到Datasets集合中,包含了被绑定图层的对象的计算结果。比如说,如果数据被绑定到US_States地图,每一个州将对应一个新的数据值,这个数据值被用来控制地图的绘制。如果数据源中含有某个州的多个记录,则这些记录的值可以进行累加、平均值等计算。使用DatasetValue方法可以取得地图中每一个对象的计算结果。

DataSets.Add方法详解

Datasets.Add方法的使用主要需确定所绑定数据源的类型、绑定到地图的哪一层以及与地图之间关联的字段。语法如下:

Datasets.Add  Type, SourceData, [Name], [Geofield], [SecondaryGeofield], [BindLayer], [Fields], [Dynamic]

[]中的参数是可选的,程序中可以省略或传递EmptyParamEmptyParamDelphi中已定义的OleVariant类型参数,表示未用参数。

Ø         Type

Type的取值范围为DatasetType常量,对应于可绑定的数据类型, DatasetType的定义如下:

DatasetType=[miDatasetADOmiDatasetDelphi,……,miDatasetLayermiDatasetODBCmiDatasetUnbound]    

其中miDatasetLayer表示绑定的是MapInfo表(.TAB),miDatasetODBC表示绑定的是ODBC 数据源中的表。

Ø         SourceData

根据DatasetType的不同,SourceData有不同的取值,如miDatasetLayer对应MapInfo表,miDatasetODBC对应ODBCQueryInfo对象等等。因此,在引如ODBC数据时,需要首先创建ODBCQueryInfo对象,并为其参数ConnectStringDatasourceSqlQuery赋值

Ø         Name

String类型,唯一标识Dataset,默认名称为Dataset1Dataset2……。

Ø         Geofield

指定数据源中包含地理信息的字段名称或索引。如果不指定,则MapX会自动在GeoDictionary中搜索,看哪个字段包含地理信息。比如在“世行项目”中,表T_DJQHxzqybh字段其实就是用来标识地图中地级行政区划的,因此在调用Datasets.AddGeofield参数即传递xzqybh

如果要将数据表示为地图上的图形对象,数据源中GeoField所表示的字段必须唯一,并且被用来命名新的图层中的对象。非唯一值将在新的图层中以一点代替,重复记录对应的数据值将被求和。

如果定义了Fields,则Geofield参数将表示Fields中的字段,而不是sourcedata

可以看到,Geofield在几何数据与属性数据关联中起了绝对关键的作用。

Ø         Secondary Geofield

只有当被绑定的数据集有非唯一主键时才定义该参数。

Ø         BindLayer 

指明外部数据应该绑定到地图中的哪一层。.该参数可选,未指定时MapX自动在GeoDictionary中查找相匹配的图层。但是从性能考虑,在肯定的情况下应当明确指定。

Ø         Fields 

描述外接数据源中的哪些字段被引用,以及当数据源中有多条记录对应一个地图对象时使用哪些集合函数,默认的集合函数是SUM(求和)。

如果该参数有定义,则GeofieldSecondaryGeofield参数均将其作为参照。

Ø         Dynamic

布耳类型参数,用于控制数据绑定是否动态,默认为False,表示静态绑定,即当数据库被打开时MapX将拷贝所需数据;如果设定为TrueMapX会以实时的方式访问数据。

三、       专题图的生成

1、 专题地图的概念

MapInfo的一个显著特征就是能将数据库中的信息进行直观的可视化分析。专题地图就是用于分析和表现数据的一种强有力的方式。用户可以通过使用专题地图的方式将数据图形化,使数据以更直观的形式在地图上体现出来。当使用专题渲染在地图上显示数据时,可以清楚地看出在数据记录中难以发现的模式和趋势,为用户的决策支持提供依据。专题地图是MapInfo中的一个重要概念,是用户使用好MapInfo的一种体现。

制作专题地图是根据某个特定专题对地图进行“渲染”的过程。所谓的专题渲染,就是以某种图案或颜色填充来表明地图对象(点、线、区域)的某些信息(例如人口、大小、年降雨量、日期等等),也就是说,这类渲染存在着主题,经过这样渲染的地图就是专题地图。利用MapInfo,可根据数据库表中特定的值来赋给地图对象颜色、图案或符号,从而创建不同的专题地图。

2、专题图的六种类型

MapInfo为创建专题地图提供了强有力的支持。用户可以使用范围值、等级符号、点密度、独立值、直方图和饼图等多达六种方式来创建不同的专题地图。

(1)、          范围值

按照设置的范围显示数据。这些范围用颜色和图案进行渲染。范围专题地图能够通过点、线和区域来说明数值,在反映数值和地理区域的关系(如销售数字,家庭收入),或显示比率信息如人口密度(人口除以面积)时是很有用的。

(2)、          等级符号

等级符号为表中每条记录显示一个符号,符号大小与数据值成比例。等级符号地图用特定的数值来显示数据点,对于阐明定量信息(如由高到低依次变化)很有用处。符号的大小与该点对应的数值成比例,数值越大点就越大,数值越小点就越小。因此,等级符号最适合数据值数据。

(3)、          点密度

在地图上用点来显示数据,每一点都代表一定数量,某区域中点的总数与该区域数值成比例。每个点代表一定数量的单元,该数乘以区域内总的点数,就等于该区域的数据值。

(4)、          独立值

按独立数值渲染地图,可以表达多个变量。根据独立值绘制地图对象的专题地图有助于强调数据的类型差异而不是显示定量信息(如给定区域内的商店类型、分区类型等等)

(5)、          直方图

将表中每条记录的专题变量显示为一个直方图。使用直方图可分析地图中每条记录的多个变量。比较每个直方图中各直方条的大小可考察表中某条记录,比较所有直方图中某一条的大小可考察所有记录的某个变量,而比较各直方图的高度可考察整张表。用直方图来表达负值时,该条会沿直方图反方向伸展。在叠加直方图中不显示负值。

(6)、          饼图

以饼图显示表中各记录的专题变量。饼图可包含多个变量。在地图上使用饼图可一次分析多个变量,比较每个图中饼扇的大小可考察表中某条记录,比较所有饼图中某一个饼扇,可考察所有记录中某个变量的变化,比较各饼图的直径可考察整张表。

3、 MapX对专题图的支持

MapX中使用Themes集合与Theme对象来实现对专题图的支持,每个Themes集合中可以包含多个Theme对象,也就是说,针对一个Dataset,可以创建多幅不同的专题地图。

每个Dataset都拥有一个Themes集合,并以其属性的形式存在,即Dataset.Themes。使用ThemesAddRemoveRemoveAll等方法可以控制专题的添加和删除。

Ø         Add方法:创建一个专题并将其加入到某个特定的DataSetThemes集合中,

Map1.Datasets(1).Themes.Add(miThemeRanges’’’area,Myranges Theme)

Ø         Remove方法:从集合中删除某一特定的专题图

Map1.Datasets(1).Themes.Remove "My Ranges Theme"

Ø         RemoveAll方法:从集合中删除所有的的专题图

Map1.Datasets(1).Themes.RemoveAll 

Theme对象用于设置每个专题图的属性。

比较重要的有

Ø         Layer:返回一个Layer对象,表示该专题图所在的图层

Ø         Legend:控制    对专题地图的说明,即图例

Ø         ComputeTheme    控制是否可以对原始数据进行计算,默认为True

Ø         Type  即专题图类型,取值范围为ThemeTypeConstants

Ø         Fields  只读属性,返回该专题图所基于的Dataset中的字段集合

ThemeProperties  复合型属性,对应ThemeProperties对象,包含了专题图详尽的定义信息,如范围定义、显示风格设置等。

4、专题图的规划

在创建专题图的过程中,有几个关键因素,包括专题图变量的确定、属性数据的获取以及专题图层的显示与控制。

(1)、          确定专题图变量

在专题图中显示的数据就是专题图变量。例如在行政区面积专题图中,表示面积的字段“area”就是这个专题地图的专题地图变量。

一个专题变量可以是一个字段或表达式。取决于专题图的类型,在一张地图上可以显示一个或多个专题图变量。范围值、等级符号、点密度和独立值地图都只检查一个变量。可以利用饼图或直方图一次显示多个专题变量。也可以创建双变量专题地图,其中一个地图对象可代表两个不同的数据,入符号的颜色代表一个专题变量,符号的大小代表另一个专题变量。

(2)、          属性数据的获取

在创建专题地图之前,必须确定需要显示何种信息,信息存储在什么位置。它可以在创建地图时所基于的表中,也可以在ODBC支持的外部数据库中。数据来源于Field对象或Field集合,在Themes.Add方法中通过Fields参数传递。

(3)、          创建专题图

首先应将某个产生专题图数据的dataset引入地图中,之后使用Themes.Add方法创建一个Theme对象。

curmap.Datasets(1).Themes.AddmiThemeRanges,TotPop,‘’);

语法:  Themes.Add  [Type],  [Field],  [Name]

Type用于定义要创建的专题图的类型,它的取值范围是ThemeTypeConstants,该参数可选,如果没有定义或者定义为miThemeAutoMapX会根据字段数以及已经存在的专题图类型自动在ThemeTypeConstants中选择一个。如果MapX无法自行确定专题类型,就会产生一个错误。

Field(s)定义在专题图中使用的一个或多个字段,可以通过字段名、字段索引或字段对象来引用。当创建多变量专题图时,可以使用数组表示。该字段是可选的,若不特意指定,MapX会使用DataSet中的第一个数字型字段。

Name,即专题图的名称,String类型参数,若不指定,MapX会自动生成一个名字。

(4)、          专题图类型常量

专题图变量由Theme.Typeproperty取得,其定义如下:

miThemeRanged  = 0

miThemeBarChart = 1

miThemePieChart = 2

miTheme GradSymbol = 3

miThemeDotDensity = 4

miThemeIndividualValue = 5

miThemeAuto = 6

miThemeNone = 9

5、控制专题地图

有两种方法可以控制专题地图。

(1)、          使用Theme.ThemeDlg方法

该方法显示一个对话框,用户可以直接修改专题图特性。语句如下:

curmap.Datasets(1).Themes(1).ThemeDlg

这种方法虽然简单,但是而且很难与自己的程序风格相一致,用户界面不友好,而且在这个默认的对话框中,用户可以随意改变任何设置,使得程序的控制难度加大。

(2)、          改变ThemeProperties对象属性

通过设置ThemeProperties对象属性,可以使用自己定制的界面,给用户有限的修改能力,实现起来也非常简单,而且对用户的操作有全部的控制权。

ThemeProperties对象是Themes集合中的一员,主要用于定义专题地图的显示,包括颜色、符号等。不同类型的专题图有自己与众不同的一些特性,在ThemeProperties中有其分别的定义。如DotSize专用于设定点密度专题图中点的大小,NumRanges专用于设定范围值专题图中的范围分布,SymbolStyle控制等级符号专题图使用的符号类型,ValuePerDot用于在点密度专题图中每个点所代表的值。

ThemeProperties对象的属性中有许多又属于其他对象,如RangeCategoryIndividualValueStyle 等,可进行更深层次的设定。

6、 自定义图例

专题地图被创建后,MapX会自动生成一个图例来解释颜色、符号或大小所代表的含义。同ThemeDlg一样,可以直接用LegendDlg 方法调用默认的Legend对话框,但更常用的依旧是访问Theme.Legend 属性来进行一些个性化的设置。

如在程序中可以做如下设置:

    var lgd: CMapXLegend;

    lgd:=curmap.datasets.item(1).themes.item(1).legend;

    with lgd do

    begin

          title:='面积专题图';

          subtitle:='图例';

          ShowCount := false;//去掉默认生成的结果个数

      end;

需要注意的是,LegendWidthHeight属性是只读的,显示位置应该由TopLeft改变,单位为屏幕象素点。

7、代码分析

以下是面积专题图的实现代码:

procedure Tmainform.Ntheme1Click(Sender: TObject);

var

  par : Variant;

  ds : CMapXdataset;

  fields: CMapXFields;

begin

  try

    curmap.datasets.removeall;//清空数据集中的所有Dataset对象<