GIS软件开发技术

GIS软件开发技术
GIS软件开发技术

第一章MapObjects基础Gis常用开发平台

MapObjects简介

?MapObjects功能

?MapObjects优点

?MapObjects基础

编程规范

01、Gis软件开发常用开发平台

常用开发平台的比较:

VB:较易入门

VBA:对于扩充原有功能较好。如AutoCAD、ArcMap中的VBA。开发效率最高的一种开发方式(常常是一个语名即可实现其它开发工具要几十甚至上百行的代码才能实现的功能)。缺点是所开发出的应用程序不能脱离相应的运行环境。(如在ArcMap中开发的应用程序,必须先要安装ArcMap)

VC++:较为灵活,开发资料众多。可实现对系统的全面操作。缺点是学习起来较难,所开发出的应用程序常常会产生难以预计的错误。(如内存泄露等)

Delphi:可扩充性最好,现已有上万个带源码的控件可供使用,几乎涉及到各各方面。如数据库控件InfoPower3000、OpenGL控件GLScene,工业控制控件等。

GIS组件简介:

MapObjects:ESRI

1、可实现功能:

2、可使用的数据

ArcView Gis Shapefiles:创建新层、读写数据,添加删除记录与几何要素

ArcSDE:不能创建新层

Arcinfo Coverages:只读

CAD格式及VPF数据库:只读(Vector Product Format是一种标准的基于空间关

系数据模型的大型空间数据库的格式、结构与组织。是美国国防部的标准)

外部数据库:只读

ArcObjects:ESRI

MapX:Mapinfo

Supermap:中科院地理所

一般用户(大多数用户)关心的问题:应用程序的运行速度与稳定性。不关心所采用的开发工具及内部实现方式。只有特殊用户(少量用户)考虑与原有系统的兼容性才关心开发平台。

软件开发中应注意的问题:

代码的规范性:1、命名约定2、代码缩进3、逻辑关系的排列次序

对于较为普通的问题尽量使用较常见的解决方式。尽量不使用较为古怪的技巧(如:两数的交换),这样会降低代码的可读性。

Delphi开发环境简介:

1、数据库应用

2、OpenGL应用

3、报表制作

02、通用GIS功能的界面框架设计

1、菜单的设计

2、工具条的设计

3、状态栏提示信息的显示(标准控件及1stClass控件的使用)

4、fcLookoutBar控件的使用

5、TActionList控件的使用

6、图标及标题的设置

03、MapObjects的模块间关系简介

属性、事件、方法:

属性:对象的性质,方法:对象的动作,事件:对象的响应。(只有

Map Control有事件)

可创建对象与不可创建对象

为有效地使用MapObjects中的OLE Automation对象,必须注意一些对象可以创建,一些对象不可创建。如果某个对象可以创建,在对象图中对象名称下有一个Creatable标注。

如一个对象可以创建可用如下代码创建:(假设创建点对象)

Dim NewObject as New MapObjects2.Point

Dim NewObject as MapObjects2.Point

Set NewObject = New MapObjects2.Point

在将对象的引用赋给变量、数据类型的元素或可写对象的属

性时,须使用关键字Set;在创建对象的实例时,须使用关

键字New

Var

NewObject: ImoPoint;

Begin

NewObject := coPoint.Create;

End;

在Delphi中如一个对象可创建,可用coXXX.Create方法进

行创建。XXX为可创建对象名

值传递与引用传递:

值传递:新的变量得到原始数据或对象的一个拷贝,其值的改变不影响原值。Name属性;引用传递:新的变量得到原始数据或对象的内存地址,其值的改变影响原值。Symbol属性

值传递

Dim LayerName As String

LayerName= https://www.360docs.net/doc/674034403.html,yers.Item(0).Name

LayerName = "MyLayerName"

MsgBox LayerName

MsgBox https://www.360docs.net/doc/674034403.html,yers.Item(0).Name

var

LayerName: string;

begin

LayerName := ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(0)).Name;

LayerName := 'MyLayerName';

ShowMessage(LayerName);

ShowMessage(ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(0)).Name);

End;

引用传递

Dim MySymbol As New MapObjects2.Symbol

Set MySymbol = https://www.360docs.net/doc/674034403.html,yers.Item(0).Symbol

MySymbol.Color = moRed

Map1.Refresh

var

MySymbol: imoSymbol;

begin

MySymbol := coSymbol.Create ;

MySymbol := ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(0)).Symbol;

MySymbol.Color := moRed;

Map1.Refresh ; end;

MapObjects中的常量:

常量均以mo开头。在编写代码时,可使用常量名也可使用常量左边的整数。但最好使用常量名称以增强代码的可读性。

MainMap.MousePointer = moArrow; 或MainMap.MousePointer = 1;

第二章地图与图层

M ap Control

L ayers Collection

?MapLayers

?ImageLayers

R ectangle、point

D ataConnection

G eoDatasets Collection

G eoDataset

T rackingLayer

查看地图

地图的放大、缩小、平移等操作

交互式方法:Pan、TrackRegtangle、TrackPolygon、TrackCircle。当使用上述方法时,运行时线程将暂停,等待用户使用鼠标与Map控件交互。

实现对地图的基本操作。(地图的放大、缩小、平移)

Private Sub MainMap_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)

Dim r As new MapObjects2.Rectangle

If barDisplay.Buttons("Zoom in").Value = 1 Then

MainMap.Extent = MainMap.TrackRectangle

ElseIf barDisplay.Buttons("Zoom out").Value = 1 Then

r = MainMap.Extent

r.ScaleRectangle(1.25)

MainMap.Extent = r

ElseIf barDisplay.Buttons("Pan").Value = 1 Then

MainMap.Pan

ElseIf barDisplay.Buttons("Identify").Value = 1 Then

Call frmIdentify.Identify(x, y)

Endif

MainMap.Refresh

End sub procedure TMainFRM.MainMapMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

var

r: imoRectangle;

begin

if tbZoomIn.Down then

MainMap.Extent := MainMap.TrackRectangle

else

if tbZoomOut.Down then

begin

r := coRectangle.Create;

r := MainMap.Extent; //(Extent:为地图的空间区域

可理解为当前的显示范围)r.ScaleRectangle(1.25); //

MainMap.Extent := r;

end

else

if tbPan.Down then

MainMap.Pan

else

if (tbIdentify.Down) and (Button = mbLeft) then

// GetIdentify(X, Y) ;

MainMap.Refresh;

End;

获取鼠标坐标

在创建面向图形的应用程序时,必须解决两种坐标系统的转换问题:定义窗体中控件的尺寸与位置的控制坐标,以及定义在打印机或显示器上图形的大小与位置的设备坐标。MapObjects开发人员还须使用第三种坐标系统:地图坐标系统。此坐标定义了地图上几何要素或影像的笛卡尔位置。为保证有效,此坐标系统必须与某种投影或非投影坐标相匹配,以

定义物体在地表的位置。

在MapObjects中,ToMapPoint方法以参数形式接收MouseDown、MouseUp、MouseMove事件传递的鼠标位置的x,y参数。这些x,y值是以控制坐标来表达的。ToMapPoint 方法将窗体上点的位置转换成相应的地图上的点位置。FromMapPoint方法实现相反的转换。类式的方法有:ToMapDistance与FromMapDistance

Private Sub Map1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)

Dim MyPoint As New Point

Set MyPoint = Map1.ToMapPoint(X, Y)

Text1.Text = Str(MyPoint.X) + " " + Str(MyPoint.Y) End Sub procedure TForm1.Map1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);

var

MyPoint: ImoPoint;

begin

MyPoint := coPoint.Create ;

MyPoint := Map1.ToMapPoint(x,y);

Edit1.Text := FloatToStr(MyPoint.X) + ' ‘+

FloatToStr(MyPoint.Y );

end;

图层集合(Layers)

?每个地图控件有且只有一个Layers集合

?Layers集合可包含MapLayer与ImageLayer两类地图文件?每个图层可有自已的显示方式

Dim i As Integer

For i = 0 To https://www.360docs.net/doc/674034403.html,yers.Count - 1 MsgBox https://www.360docs.net/doc/674034403.html,yers.Item(i).Name Next i var

i: integer;

MyLayers: imoLayers;

begin

MyLayers := https://www.360docs.net/doc/674034403.html,yers ;

for i := 0 to MyLayers.Count - 1 do

ShowMessage(ImoMapLayer(MyLayers.Item(i)).Name); end;

或:

var

i: integer;

begin

for i := 0 to https://www.360docs.net/doc/674034403.html,yers.Count - 1 do

ShowMessage(ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(i)).Name); end;

04、MapObjects图层操作

1、ArcView格式地图

2、AutoCAD图形

3、位图

注意观察如下图形中的红线部份:

加入ArcView格式地图

步骤:

1、生成数据连接对象(ImoDataConnection)

2、设定数据连接对象的DataBase属性

4、取得空间数据集

5、生成新的图层

6、将新生成的图层加入地图控件

Private Sub Command1_Click()

Dim dc As New MapObjects2.DataConnection

Dim lyr As New MapObjects2.MapLayer

dc.Database = "C:\USA"

If dc.Connect Then

Set lyr.GeoDataset = dc.FindGeoDataset("Counties") If lyr.Valid Then

https://www.360docs.net/doc/674034403.html,yers.Add lyr

Else

MsgBox "无法加入图层"

End If

Else

MsgBox "出错,请确定数据是否存在?"

End If

End Sub var

dc: imoDataConnection;

lyr: imoMapLayer;

begin

dc := coDataConnection.Create;

lyr := coMapLayer.Create;

dc.Database := 'C:\USA';

if dc.Connect then

begin

lyr.GeoDataset := dc.FindGeoDataset('Counties');

if lyr.Valid then

https://www.360docs.net/doc/674034403.html,yers.Add(lyr)

else

ShowMessage('无法加入图层')

end else

ShowMessage('出错,请确定数据是否存在?'); end;

注意要点:

DataBase:对于shapefile,数据库属性仅为一包含有shapefile的文件夹或目录字符串。FindGeoDataset:对于shapefile,参数字符串只须设为没有扩展名的ShapeFile文件名。较为完整的加入ShapeFile的Delphi代码:

function TMapManage.AddShapeFile(sFileName: string; LayerColor: integer = 16711680): string;

var

gs: IMoGeoDataset;

dc: IMoDataConnection;

name, fname: string;

Newlayer: IMoMapLayer;

begin

dc := IMoDataConnection(CreateOleObject('MapObjects2.DataConnection'));

// 或dc := coDataConnection.Create ;;

name := SFileName;

fname := ExtractFileDir(name); //获取某一文件所在的路径

dc.database := fname; //DataBase属性:指明所采用的数据,如为SDE则为数据库名,如为Shp文件则为Shp文件所在的目录

if not dc.connect then exit;

Name := GetFileName(Name);

if not LayerExist(Name) then

begin

gs := dc.FindGeoDataset(name);

gs.AllowSharing := true;

if VarIsEmpty(gs) then exit; //判断对象是否为空,(在Delphi6中此函数存在错误)

NewLayer := IMoMapLayer(CreateOleObject('MapObjects2.MapLayer'));

NewLayer.GeoDataset := gs;

NewLayer.Symbol.Color := LayerColor;

https://www.360docs.net/doc/674034403.html,yers.Add(NewLayer);

end

else begin

MessageBox(Handle, '已存在图层', '图层管理', MB_OK + MB_ICONINFORMA TION);

Result := '';

Exit;

end;

Result := Name;

end;

//假设sFileNmae 为C:\Projects\Lean.shp函数返回值为Lean

function GetFileName(sFileName: string): string;

begin

while pos('\', sFileName) > 0 do

begin

delete(sFileName, 1, 1);

end;

while pos('.', sFileName) > 0 do

delete(sFileName, Pos('.', sFileName), 4);

Result := sFileName;

end;

更正Delphi6中的VarIsEmpty函数:

将:

Result := FindVarData(V)^.VType = varEmpty;

改为:

with TVarData(V) do

Result := (VType = varEmpty) or ((VType = varDispatch) or

(VType = varUnknown)) and (VDispatch = nil);

//判断指定的图层是否存在

function LayerExist(sLayerName: string): boolean;

var

i: integer;

CurrentMap: ImoMapLayer;

begin

CurrentMap := CoMapLayer.Create;

for i := 0 to https://www.360docs.net/doc/674034403.html,yers.Count - 1 do

begin

CurrentMap := ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(i));

if https://www.360docs.net/doc/674034403.html, = sLayerName then

begin

Result := true;

exit;

end;

end;

Result := false;

end;

加入Coverage图层:

加入SDE图层

加入Image图层:

Private Sub Command1_Click()

Dim lyr As New MapObjects2.ImageLayer

lyr.File = "D:\ Washington\Wash.bmp" https://www.360docs.net/doc/674034403.html,yers.Add lyr

End Sub procedure TForm1.Button1Click(Sender: TObject); var

Lyr: imoImageLayer;

begin

lyr := coImageLayer.Create ;

Lyr.File_ := 'D:\ Washington\Wash.bmp';

https://www.360docs.net/doc/674034403.html,yers.Add(Lyr);

end;

注意要点:

与失量数据不同,在创建ImageLayer时不需要创建DataConnection和GeoDataset对象,中需设置ImageLayer对象实例的File属性,再将ImageLayer加入Map控件即可。

加入CAD文件:

Private Sub Command2_Click()

Dim dc As New MapObjects2.DataConnection

Dim lyr As New MapObjects2.MapLayer

dc.Database = "[CADPoint]D:\\ARCVIEW\CAD"

Set lyr.GeoDataset = dc.FindGeoDataset("Parcels.dwg")

https://www.360docs.net/doc/674034403.html,yers.Add lyr

End Sub procedure TForm1.Button3Click(Sender: TObject); var

dc: imoDataConnection;

Lyr: imoMapLayer;

begin

dc := coDataConnection.Create ;

Lyr := coMapLayer.Create ;

dc.Database := '[CADPoint]D:\ ARCVIEW\CAD'; lyr.GeoDataset := dc.FindGeoDataset('Parcels.dwg');

https://www.360docs.net/doc/674034403.html,yers.Add(Lyr);

end;

注意要点:

DataConnection的Database属性字符串不仅要提供文件所在的路径,而且要包括实体类型的前缀。如[CADPoint]、[CADArea]及[CADText]等,前缀[CAD]默认为线实体。

在使用FindGeoDataset方法时,其参数必须包括扩展名在内的完整文件名。

小结:

测试数据库联接:

Connect与DisConnect:

Connect与DisConnect是作用在DataConnection对象上的方法。Connected与ConnectErr 是DataConnection对象的属性,可以在任何时间读取检验连接状态。

Connect首先读取数据库属性,确定数据的存储位置;读取存储的文件并创建数据的GeoDataset集合;Connect返回一布尔值,并在Connected属性中写入这一布尔值;若Connect 返回的布尔值为False,它将设置ConnectError的值。

DisConnect方法释放DataConnection对象和数据存储位置间的连接,清空GeoDataSets 集合,并重新设置Connected值为False。

加入图层时应注意到不同类型的数据其DataConnection的DataBase属性字符串的值格式不同。

文件类型DataConnection的Database属性DataConnection的FindGetDataset方法ShapeFile:Shp文件所在的路径不带扩展名的Shp文件名

AutoCAD:[类型]+CAD文件所在的路径包括扩展名在内的完整文件名

Image:不需要设置不需要设置

Coverage:

05、图层的显示次序

图层在地图控件的次序决定或影响整个地图的显示效果,点状信息或线状信息常常会被面状信息所掩盖。可通过Layers集合中的MoveTo、MovtToBottom、MoveToTop方法控制图层的次序。及MapLayer对象中的Visible属性控制某个图层显示与否。

//获取当前所打开的所有图层名及状态

procedure TLayerManagerFRM.FormActivate(Sender: TObject);

var

i: Integer;

CurrentLayer: ImoMapLayer;

begin

CheckListBoxLayers.Clear;

for i := 0 to https://www.360docs.net/doc/674034403.html,yers.Count - 1 do

begin

CurrentLayer := ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(i));

if https://www.360docs.net/doc/674034403.html,yerType = moMapLayer then

checkListBoxLayers.Items.Add(https://www.360docs.net/doc/674034403.html,);

CheckListBoxLayers.Checked[i] := CurrentLayer.Visible;

end;

end;

//确定各个按钮的状态

procedure TLayerManagerFRM.CheckListBoxLayersClick(Sender: TObject); var

CurrentLayer: Integer;

LayerCount: Integer;

Layer: ImoMapLayer;

begin

CurrentLayer := CheckListBoxLayers.ItemIndex;

Layer := ImoMapLayer(https://www.360docs.net/doc/674034403.html,yers.Item(CurrentLayer)); LayerCount := https://www.360docs.net/doc/674034403.html,yers.Count;

if (LayerCount = 1) or (LayerCount = 0) then

else

begin

sbTop.Enabled := CurrentLayer <> 0;

sbButtom.Enabled := CurrentLayer < LayerCount - 1;

sbUp.Enabled := CurrentLayer <> 0;

sbDown.Enabled := CurrentLayer < LayerCount - 1;

end;

CmbRemove.Enabled := CheckListboxLayers.Items.Count > 0; bbtnAttribute.Enabled := CmbRemove.Enabled;

end;

//移动图层

procedure TLayerManagerFRM.MoveLayer(Sender: TObject);

var

CurrentLayerIndex: Integer;

begin

CurrentLayerIndex := CheckListBoxLayers.ItemIndex;

if CurrentLayerIndex < 0 then

ShowMessage('请选择所要移动的图层。')

else

begin

with https://www.360docs.net/doc/674034403.html,yers do

begin

case (Sender as TSpeedButton).tag of

1:

MoveToTop(CurrentLayerIndex);

2:

MoveTo(CurrentLayerIndex, CurrentLayerIndex - 1);

3:

MoveTo(CurrentLayerIndex, CurrentLayerIndex + 1);

4:

MoveToBottom(CurrentLayerIndex);

end;

end;

end;

LayerManagerFRM.FormActivate(Sender);

CurrentMap.Refresh;

end;

Map控件

1)BeforeLayerDraw (index as Integer, hDC as stdole.OLEHandle)

绘制图层

2)AfterLayerDraw (index as Integer, canceled as Boolean, hDC as stdole.OLEHandle)

3)BeforeTrackingLayerDraw (hDC as stdole.OLEHandle)

绘制Tracking图层

4)AfterTrackingLayerDraw (hDC as stdole.OLEHandle)

BeforeLayerDraw事件:在绘制图层前执行,主要用于检查当前图层的显示比例,决定在当前显示比例下是否显示此图层。这样可使地图更具有地图学意义,同时提高显示速度。

第三章数据集

相关主题
相关文档
最新文档