一、利用MapBasic开发
MapBasic是Mapinfo自带的二次开发语言,它是一种类似Basic的解释性语言,利用MapBasic编程生成的mbx文件能在Mapinfo软件平台上运行,早期的Mapinfo二次开发都是基于MapBasic进行的。MapBasic学起来容易,用起来却束缚多多,无法实现较复杂的自定义功能,用它来建立用户界面也很麻烦,从现在角度看,MapBasic比较适合用于扩展Mapinfo功能。
二、利用OLE自动化开发
1 建立Mapinfo自动化对象
基于OLE自动化的开发就是编程人员通过标准化编程工具如VC、VB、Delphi、PB等建立自动化控制器,然后通过传送类似MapBasic语言的宏命令对Mapinfo进行 *** 作。实际上是将Mapinfo用作进程外服务器,它在后台输出OLE自动化对象,供控制器调用它的属性和方法。
OLE自动化开发的首要一步就是建立Mapinfo自动化对象,以Delphi为例(后面都是如此),你可设定一个Variant类型的全程变量代表OLE自动化对象,假设该变量名为olemapinfo,那么有:
oleMapinfo := CreateOleObject('MapinfoApplication')
一旦OLE自动化对象建立,也就是后台Mapinfo成功启动,你就可以使用该对象的Do方法向Mapinfo发送命令,如:
oleMapinfoDo('Set Next Document Parent' + WinHand + 'Style 1')
这一命令使Mapinfo窗口成为应用程序的子窗口,WinHand是地图窗口句柄,style 1 是没有边框的窗口类型。你还可以使用自动化对象的Eval方法返回MapBasic表达式的值,如下面语句返回当前所打开的表数:
TablesNum:=olemapinfoeval('NumTables()')
你也可以直接调用Mapinfo菜单或按钮命令对地图窗口进行 *** 作,如地图放大显示:
oleMapinfoRunMenuCommand(1705)
2 建立客户自动化对象触发CallBack
基于OLE自动化开发的难点在于所谓的CallBack,Mapinfo服务器对客户程序地图窗口的反应叫CallBack,假如你在地图窗口中移动地图目标,Mapinfo能返回信息告诉你地图目标当前的坐标位置,这就是CallBack功能。如果你想定制自己的地图 *** 作工具或菜单命令,你必须依靠CallBack。但是想捕获CallBack信息,你的客户程序必须具备接收CallBack信息的能力,为此需要在客户程序中定义自己的OLE自动化对象,如:
//定义界面
IMyCallback = interface(IDispatch)
['{2F4E1FA1-6BC7-11D4-9632-913682D1E638}']
function WindowContentsChanged(var WindowID: Integer):SCODE;safecall;
function SetStatusText(var StatusText: WideString): SCODE; safecall;
//定义界面实现
TMyCallback = class(TAutoObject, IMyCallback)
function SetStatusText(var StatusText: WideString): SCODE; safecall;
function WindowContentsChanged(var WindowID: Integer): SCODE;safecall;
其中WindowContentsChanged函数用于返回变化窗口的ID号,即当地图窗口变化时(如放大、缩小),让Mapinfo将地图窗口的ID号返回给客户程序; 另一个SetStatusText函数返回Mapinfo状态条变化信息。编程人员不能随意定义这些函数,因为只有在三种情况下Mapinfo服务器的CallBack才会被触发:(1)地图窗口发生变化,触发函数为WindowContentsChanged;(2)Mapinfo状态条信息改变,触发函数为SetStatusText;(3)用户选择自定义工具或菜单命令在地图窗口上 *** 作,如用户定制的画线工具,当用户在地图窗口画线时触发Mapinfo的CallBack返回线的坐标位置。
建立客户自动化对象后,调用MapInfo自动化对象的SetCallback方法将客户自己定义的自动化对象告诉Mapinfo,只要程序一运行,客户自动化对象就会自动在注册表中注册,然后就能收到CallBack信息了,如:
My:=MyCallBackCreate
oleMapInfoSetCallBack(My)
这里打一个比方我想会有助于理解上述机制,客户程序与Mapinfo之间的交互就像舞台指挥与木偶演员的交流,客户程序中的地图窗口或说Mapinfo子窗口只不过是一个牵线木偶,后台的Mapinfo才是真正 *** 纵木偶的演员,所以客户程序必须与后台Mapinfo建立正向、反向的联系机制,才能 *** 纵地图窗口中的图形目标。
三、利用MapX开发
1 掌握使用MapX
MapX是Mapinfo公司最新推出的ActiveX控件产品,目前已经发展到MapX45。由于MapX是基于Windows *** 作系统的标准控件,因而能支持VC、VB、Delphi、PB等标准化编程工具,使用时只需将控件装入开发环境,装入控件后,开发环境ActiveX工具条上会增加一个控件按钮Map,把它拖放到窗体上就可建立一个TMap类型的ActiveX地图对象Map,通过设置或访问该Map对象的属性、调用该Map对象的方法及事件,便能快捷地将地图 *** 作功能溶入到你的应用程序中。
MapX由一系列Object(对象)和Collection(对象集合)组成,Map是最基本的对象,每个Map由Layer(层)、Dataset(数据集)和Annotation(标注)这三个对象及对象集合(Layers、Datasets、Annotations)来定义, 其中Layer用于 *** 作地图图层,Dataset用于访问空间对象的属性数据,Annotation用于在地图上添加文本、符号等标注,掌握上述三个主要对象的特征后,再顺藤摸瓜掌握下一级对象的特征,如每个Layer又由Feature(点、线、面、文本图形目标)对象及对象集合(Features)定义,每个Dataset由Field(属性数据域)对象及对象集合(Fields)定义,这样很快就能把MapX学到手。
2 定义地图坐标系
在MapX开发中需要特别注意地图坐标系问题,MapX地图坐标系分为地图显示坐标系和内部计算坐标系,两者互为独立,在GIS应用开发中根据应用需要设置好这两种坐标系非常重要,因为坐标系一方面影响软件系统的内部坐标处理,另一方面影响地图的外观显示。Map对象的坐标系及投影通过CoordSys对象的Set方法定义:
Set(Type, [Datum], [Units], [OriginLongitude], [OriginLatitude],
[StandardParallelOne], [StandardParallelTwo], [Azimuth], [ScaleFactor],
[FalseEasting], [FalseNorthing], [Range], [Bounds], [AffineTransform])
其中主要参数:Type表示投影类型,Type为1时地图坐标以经纬度表示,后面都为可选参数,其中Datum为地球基准面;Units为坐标单位,如Units为7表示以米为单位;OriginLongitude、OriginLatitude分别为起始经度和纬度;StandardParallelOne、StandardParallelTwo为第一、第二标准纬线,该参数与地图投影相关。
通过设置Map对象的DisplayCoordSys和NumericCoordSys属性返回的CoordSys对象,就可设定地图显示坐标系和内部计算坐标系。举例如下:
procedure TMainDefineMapParam();
var
MapDatum: Variant;//地球基准面
begin
try
MapDatum := CreateOleObject('MapXDatum4'); //建立基准面对象
//定义北京54坐标系基准面
// (Ellipsoid, ShiftX, ShiftY, ShiftZ, RotateX, RotateY, RotateZ, ScaleAdjust, PrimeMeridian)
MapDatumset(3, 24, -123, -94, -002, 025, 013, 11, 0);
//定义北京54坐标系经纬度作为内部计算坐标系
Map1NumericCoordSysSet_(1, MapDatum);
//定义北京54坐标系30度标准纬线麦卡托投影作为显示坐标系,单位为米
Map1DisplayCoordSysSet_(26,MapDatum,7,0,0,30);
finally
VarClear(MapDatum);
end;
坐标系是GIS系统的基石,正确设置坐标系是系统成败的关键。
3 *** 纵地图对象
你可以简单地加载一个GeoSet文件,给Layers对象集合赋予具体的内容,随之在Map对象中就能看到地图显示,GeoSet文件类似MapInfo中的工作空间,MapX中带有Geoset文件的编辑器GeosetMangaterexe,用户可在编辑器中组合及设置图层,然后保存生成一个 gst 文件直接调入Map对象,这样可以节省时间。你也可以通过Layers对象的Add 或 Remove 方法添加或移走地图图层,如:
MaplayersAdd(FileName); // 添加图层,FileName为文件全路径名
MapLayersRemove(3); // 移走地图第三层
Layers对象由一组Layer对象组成,通过Layer对象的Features和Selection对象集合你可以 *** 纵和选择图层上的图形目标,如:
MapLayersItem(1)AddFeature(Newobj); //将新建对象Newobj添加到图层一
4 地图数据捆绑
数据捆绑是将不同来源的数据对应到地图层的过程,捆绑结果会产生一个Dataset对象,Dataset对象的集合组成Datasets Collection,它定义了Map对象的数据集属性。 你可以通过Datasets将不同来源的数据捆绑到地图上实现图文互动,或创建专题图,如下例ODBC Access数据的捆绑及专题分析:
procedure TMapFormODBC1Click(Sender: TObject);
var
param: ODBCQueryInfo ;
ds: Dataset; //定义数据集
Datafields: Fields; //定义数据域
begin
paramSqlQuery := 'select from China'; //选择Access数据库中的China表
paramDataSource := 'MapChina'; //ODBC 数据源名
paramConnectString := 'ODBC;'; //或是user = Pwd = , 定义ODBC连接
DatafieldsAdd('GEONAME','GEONAME', miAggregationAuto,miTypeString); //添加数据域GEONAME
DatafieldsAdd('POPU','POPU', miAggregationAuto,miTypeNumeric); //添加数据域POPU
//将Access数据捆绑到Mapinfo China表
ds := MapDatasetsAdd(miDataSetODBC, param, unassigned, unassigned, unassigned, 'CHINA', Datafields, unassigned);
dsThemesAdd(miThemeRanged, 'POPU', 'MyTheme'); //添加一个范围专题图
end;
5 建立客户定制工具
你还可以定制自己的地图 *** 作工具,下面通过定制一个名为Info的信息按钮工具简述方法步骤:
(1)定义客户工具常量
Const CUSTOM_INFO_TOOL = 1
(2)利用Map对象的CreateCustomTool方法定义客户工具,方法为:
CreateCustomTool (ToolNumber, Type, Cursor, [ShiftCursor] , [CtrlCursor], [InfoTips])
其中ToolNumber为工具号,即上面定义的常量;Type为工具类型;Cursor为光标形状,其他参数可选。
//定义Info工具为十字光标点触发工具
MapCreateCustomTool(CUSTOM_INFO_TOOL, miToolTypePoint, miCrossCursor, miArrowCursor, miArrowCursor, unassigned)
(3)在Map对象事件ToolUsed中编写工具的Handler( *** 作内容)
procedure TMainMapToolUsed(Sender: TObject; ToolNum: Smallint; X1, Y1, X2, Y2, Distance: Double;
Shift, Ctrl: WordBool; var EnableDefault: WordBool);
begin
Case ToolNumber of
CUSTOM_INFO_TOOL : //信息工具Info
try
……
end;
(4)定义信息按钮的Click事件
procedure TMainInfoClick(Sender: TObject);
begin
MapCurrentTool:=CUSTOM_INFO_TOOL;
end
四、小结
基于MapBasic的开发简单但受限制较多,比较适合Mapinfo功能扩展编程。而基于OLE自动化的开发比较繁琐,因为需要来回向后台的Mapinfo发送MapBasic字符串命令,所建立的应用程序运行速度也相对较慢,但这种开发方法能随心所欲制作出美观友好的界面,将地理 *** 作与非地理 *** 作溶为一体,并且能实现几乎100%的Mapinfo功能,这是目前的MapX45也不能比拟的。与传统GIS专业性开发环境相比,像MapX这类组件式GIS系统的出现可说是一种质的飞跃,它小巧灵活,开发简捷,价格便宜,以后会越来越大众化。 用MapX开发的GIS系统运行速度快,因为它不需要在Mapinfo软件平台上运行。但从目前MapX45看,MapX并没能实现所有的Mapinfo功能(据称95%以上),使用过程中发现其生成或编辑地图能力及地理分析能力不足,而且里面Bug也不少,当然随着今后新版的推出,MapX会越来越稳定、完美。可不可以画一条线,然后选择面,设置目标对象,用线将它分解啊
选中要合并的面:“对象”→“合并”,出现“数据聚合”对话框,聚合方法:“值”→“确定”
分割的方法类似同上
一、概述:
本课,将使用合并、设置目标和清除目标等命令将许多区域合并成一个大区域。在合并对象时,还要实践如何聚合数据。当使用擦除命令从大区域中删除一个区域时,要从大区域中分解数据。最后,使用更新列命令来更新一列。
二、涉及的特性和概念:
数据聚合:把若干分离的地图对象合并成单一对象的过程。MapInfo基于原对象数值的总和或平均值,计算新对象的列的值。
数据分解:把地图对象分割成若干较小部分的过程。在这一过程中MapInfo把同地图对象相关的数据分割成较小的部分以匹配新的地图对象。
三、实际应用:
创建区域对象时,合并命令执行一个简单但重要的任务,它将选择的多个多边形合并成—个区域对象。使用该命令的一个典型例子就是将一些州合并成一个销售区域。同样,擦除和分割命令允许你擦除对象以及从销售区域中分割对象。
首先,清除桌面。
选择File>Close All。
用户经常需要通过聚合将较小的对象合并到一起来创建新区域对象。在本练习中,我们要将美国各州合并成四个大区域。
由于不想对STATES表中的对象进行编辑或修改,需要为 STATES表创建一个备份并且使用新的文件。
a、选择File (文件) >Open Table (打开表)。
b、选择STATES表。
c、单击Open。
d、选择File (文件)>Save Copy As (另存为)。
e、在File Name (文件名) 列表框中,输入ZONESTAB。
f、单击Save。
g、关闭原始表。选择File>Close All。
现在,打开新的文件:
a、选择File>Open Table(打开表)。
b、选择ZONES。
c、单击Open。
合并州时,我们同时能够计算销售区域内的数值总和。在本例中,MapInfo将计算出用于合并创建区域的州的1990年的销售总额。为此,需要修改表结构。
a、选择Table (表) >Maintenance (维护) >Table Structurs (表结构)。
b、从下拉列表中选择 ZONES并单击 OK,Modify Table Structure (修改表结构)对话框显示出来。
c、单击Add Field (增加字段)。
d、在Field Information (字段信息) 部分,在Name (名字) 框中输入Name。
e、在Type (类型) 框中确定Character (字符)。
f、在Width (宽度) 框中输入15。
g、除了Sales_1990和刚才创建的新字段Name之外,删除其它所有字段。为此,选择每一个要删除的字段并单击Remove Field (删除字段)。
h、使用 UP (上) 按钮将Name字段移到顶部。
i、单击OK。
j、在MapInfo提示confirm our changes (确认所做的修改) 时单击OK。
由于将在ZONES图层中编辑地图对象,我们要将它增加到当前地图上,并且使它可编辑。
a、选择Map (地图) >Layer Control (图层控制)。
b、单击Add (增加)。
c、从下拉列表中选择ZONES,并单击OK。
d、使ZONES图层可编辑。
e、单击OK。
现在准备创建第一个区域,首先,选择组成该区域的州。
a、按住Shift键的同时,在美国西部选择11个相邻的州。
b、选择Objects (对象) >Combine (合并)。
Data Aggregation (数据聚合) 对话框显示出来。用该对话框命名新区域,并且计算总的销售额。
c、在 Destination (目标) 框中选择Name,并且在 Aggregation Method (聚合方法)下选择Value,在文本区输入: Wostern。
d、在Destination框中选择Sales—1990,并在Aggrgation Method下选择Sum。
e、单击OK,新的对象被创建。
为了查看与新区域相关的新信息,使用 Info (信息) 按钮。
为了将其它相邻的州加到新区域中,在使用合并命令的同时,使用 Set Target (设置目标)命令。
a、选择该区域。
b、选择Objects>Set Target,注意高亮改变了,我们告诉MapInfo将要改变该对象。
c、使用选择按钮选择用来追加到Western区域的州。
d、选择objects (对象) >Combine (合并)。
可以在Data Aggregation (数据聚合) 对话框中,预览新近调整的销售数额。
e、单击OK。
f、选择objects>Clear Target (清除目标)。
新的区域现在包括新的州。我们也许想从区域中删除一个州,在这种情况下,要使用擦除命令。我们需要从原 STATES表选择一个州作为“剪切器”,但首先,要告诉 MapInfo将修改哪个区域。
a、选择将修改的区域。
b、选择Objcets (对象) >Set Target (设置目标)。
c、在使用选择工具选择将要从区域中删除的州的同时,按住 Ctrl键,这样就从 STATES表中选择了对象。
d、选择objects>Erase (擦除)。
在本课的后半部分,我们需要保证各州不被删除,所以必须恢复擦除 *** 作。
e、选其Edit (编辑) >Undo (恢复)。
f、单击OK。
有的应用程序要求将一个区域分割成两个或更多的区域,为此使用SPLTT命令。
a、选择将分割的区域。
b、选择Objects (对象),Set Target (设置目标)。
c、从STATES表中选择州,可能需要按住Ctrl 键。
d、选择Objects (对象) >SPLIT (分割)。
e、从 Field Name (字段名) 框中选择Name,在Disaggregation Method (分解方法) 组框中选择Value。
f、从 Field Name框中选择 Salcs—1990,并在Disaggregation Method (分解方法) 组框中选择Area Proportion (面积比率)。
g、在Data Disaggregation (数据分解) 对话框中单击OK.
使用面积比率方法分解数据会导致与前述整个区域相关的数据成比例分配到每个新的 区域中。
注意根据起始选择的洲的数目,该区域被分割成较小的区域。
创建另外三个区域将美国余下的部分覆盖,为了赋给区域不同的填充模式,选择Options (选项) >Region Style (区域样式) 定义具体的线型和填充模式。
由于我们一直在合并ZONES表中的地图对象,现在将表压缩。
a、选择Table>Maintenance>Pack Table (紧缩表)。
b、单击OK。
c、单击Save。
由于紧缩表命令将从所有的窗口中删除ZONES表,为了再次显示它,选择Window (窗口) >New Map并从对话框中选择ZONES。
使用更新列
Update Column (更新列) 命令允许你以很大的灵活性自动改变列。你可以从其它表或已有表中的其它列转移数据,可以通过对一些数据聚合来改变列,还可以通过创建表达式或从已有数据中获得附加信息,这些值都可以放到永久列中或者MapInfo创建的一个临时列中。
现在将使用包含每个消费者的销售区域的名字来更新US_CUST文件。我们将更新 TERR列,销售区域的信息来自 ZONES表。在开始之前,通常做一些初始化,需要将 US_CUST 文件中的TERR列扩展以使它能包含与ZONES表中的Name字段同样多的字符数。为此,我们要使用前面第13课中提到的表结构 (Table Structure) 命令。
打开US_CUST 文件,对结构作修改:
a、选择Table> Maintenance>Table Structurc。
b、从下拉列表中选择US_CUST ,并单击OK。
c、从Fields列表中选择TERR列。
d、在Field Information部分,将Width 改变为15。
e、单击OK。
下面,准备更新列:
a、选择Table>Update Column。
b、从Table to Update (要更新的表)下拉列表中选择US_CUST 。
c、从Get Value From Table (从中获得值的表)下拉列表中选择ZONES。
d、从Calculate (计算)下拉列表中选择Value。
e、从of (属于) 下拉列表中选择Name。
f、从Column To Update (要更新的列) 下拉列表中选择TERR。
注意,当你指定ZONES (从中获得值的表) 时,MapInfo自动将Add new Temporary Column (增加新的临时列) 输入到Column to Update (要更新的列) 框中。我们要确保将该列确定为TERR。
当将信息从一表传递到另一表时,Join (连接) 按钮被激活。需要确认MapInfo在两个文件之间是否建立起了正确的联系。由于US_CUST 和 ZONES之间没有共同列,我们将依赖于地理连接。换句话说,如果 ZONES (多边形) 对象包含了US_CUST (点)对象,那么这两个表就被联系起来。
g、选择Join (连接)。
h、在Specify Join (确定连接) 对话框中选中Where Object From table ZONES (来自 ZONES表的对象)。在其下方的列表框中选中Contains (包含) 单击OK。
i、单击OK,退出Update Column (更新列) 对话框。
为US_CUST创建了一个新的浏览窗口。查看TERR列,浏览窗口中的每个消费者都包含了他所位于的销售区域的名字。别忘了保存US_CUST 。
四、小结:
你学会了如何使用Objects (对象) 菜单下的合并、擦除和分割命令来创建区域。合并命令允许你将选择的多个多边形合并成一个较大的多边形对象。擦除命令从区域中删除多边形,而分割命令使用一个已知多边形作为剪切器。将一个区域分割成两个区域。为编辑一个区域,该区域必须被选择,并且被设置为目标。当编辑结束时,目标必须被清除。使用 File>Save Table (保存表) 命令保存区域。我们使用更新列命令能根据其它表中的信息更新列。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)