Google Earth API 讲解--02
5.3 Google Earth API 详解
本节介绍的Google Earth API是目前Goolge官方网站上最新的Google Earth API接口定义,也是Google所推荐使用的。与早期的KeyHole API相比有了很多新的特性,增加了很多接口,这些接口基本都是基于Keyhole API封装的,我们将在以后的内容中介绍一些关于Keyhole API的应用,使得读者能够更加深入地理解Google Earth API的实质。
5.3.1 IApplicationGE接口
IApplicationGE接口是Google Earth API开发中最重要的一个接口,通过该接口可以控制Google Earth程序的开启、关闭、获取地图窗口的句柄、操作主窗体句柄,还可以进行获取地图视场照相机对象、获取Google Earth版本号、转换坐标等一系列复杂操作。
在IApplicationGE接口中,可以找到后面5.3.2~5.3.11节中介绍的所有接口的影子,可以说它是基于Google Earth API程序开发的基础。
1.初始化设置
打开Google Earth程序,首先要登录远程的Google地图服务器,Google Earth会在本地与服务器之间打开一个会话通道,然后等待十多秒钟之后,才能看见蓝黑色的地球。通常情况下,进行Google Earth API的二次开发时,自己的程序也需要走这些步骤。
如何才能得知Google Earth已经注册好呢?Google 的API中提供了几个反馈Google Earth是否已经登录到服务器上注册完毕的函数,通过这些函数,可以在Google Earth初始化之后执行自己的业务代码,操作Google Earth完成相应动作。而没判断是否初始化结束就直接操作Google Earth,可能会导致错误。
这些与初始化相关的设置共有4个:IsInitialized、IsOnline、Login、Logout。
1)IsInitialized
IsInitialized介绍如下。
l 定义:返回一个布尔值,反馈Google Earth是否已经登录。
l 方程式:function IsInitialized: Integer; safecall。
Delphi的实例代码:
procedure TForm1.btnIsOnLineClick(Sender: TObject);
begin
if (F_AppGE.IsOnline <> 0) then
begin
showmessage('已经登录');
end
else
begin
showmessage('尚未登录');
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void btloggin_Click(object sender, EventArgs e)
{
if (appGE.IsOnline() != 0)
{
MessageBox.Show("已经登录");
}else{
MessageBox.Show("尚未登录");
}
}
执行以上代码,当Google Earth正在启动的时候,单击代码中名为【btnIsOnLine】的按钮,会弹出【尚未登录】对话框,但是当Google Earth登录状态栏显示如图5-7所示的内容的对话框之后,再单击按钮就会出现【已经登录】提示框了,如图5-8所示。这说明Google Earth在进行“Google Earth Initialization”动作过程中,实施了登录(IsInitialize)。

图5-7 连接初始化 图5-8 登录结果
2)IsOnline
IsOnline介绍如下。
l 定义:返回一个布尔值,反映Google Earth是否已经连接到数据服务器了。
l 方程式:function IsOnline: Integer; safecall;。
代码形式请参见上述IsInitialized中的代码,基本使用方法类似,在此不再赘述。
3)Login
Login介绍如下。
l 定义:登入,即开始一个与服务器之间的会话。
l 方程式:procedure Login; safecall;。
代码形式请参见上述IsInitialized中的代码,基本使用方法类似,在此不再赘述。
4)Logout
Logout介绍如下。
l 定义:登出,即离开与服务器之间的会话。
l 方程式:procedure Logout; safecall;。
代码形式请参见上述IsInitialized中的代码,基本使用方法类似,在此不再赘述。
2.视场相机设置
当用户观察Google Earth地图的时候,是没办法仅仅通过移动头部来获得不同观察体验的。因为虽然我们看到的Google地球是个三维球体,但是地图窗口投射到屏幕上的影像是一个不折不扣的平面,三维效果是通过计算模拟出来的。
要想看到不同方位的图像,例如看到地球的另一面,就必须用鼠标去拖曳,并且进行缩放,缩放到某个地方,而此时用户无须转动头部和眼球。这是操纵视场照相机(ViewCamera)的结果。
|
|
“视场照相机”的详细介绍,请参见ICameraInfo接口。 |
IApplicationGE接口提供了一个获得“视场照相机”的对象的方法GetCamera。
1)GetCamera
GetCamera为取得当前视场的照相机。并不存在一个真实的照相机,只不过是通过当前视场的内容和观察角度的反向推算,认为想像一个虚拟的照相机存在于视场之中。对于ICameraInfoGE接口的详细描述,见下面的方程式:
function GetCamera(considerTerrain: Integer): ICameraInfoGE; safecall;
其参数如表5-1所示。
表5-1 GetCamera参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
considerTerrain |
In |
(Bool) |
是否按照地形起伏而确定照相机焦点 |
参数considerTerrain有两个选择,当选择true(非零)时,则根据地形的起伏计算照相机焦点的位置;当选false(零)时,则表示根据地球曲率计算。后一种不是很准确。
这个参数在照相机行进过程中起着重要的作用,特别是在山地多起伏的地区,照相机的焦点需要根据需要设置。
Delphi实例代码如下:
GeFlag: boolean;
……
function TGETest.Testfun: Double;
var
cm: ICameraInfoGE;
begin
result := 0;
if GeFlag then begin
cm := F_AppGE.GetCamera(1); //在Delphi中为整数型数值,非零表示true
……
if cm <> nil then
result := cm.Azimuth;
end;
end;
……
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private CameraInfoGE getCam()
{
CameraInfoGE cm = new CameraInfoGEClass();
cm = appGE.GetCamera(1);
return cm;
}
这个实例代码表示获取当前视场照相机对象,然后返回照相机的方位角。视场照相机除了这个属性参数外还有其他的如移动速度、倾角、焦点经纬度等参数。
2)SetCamera
IApplicationGE还提供了设置视场照相机的方法SetCamera,使用这个方法,开发人员可以通过程序动态改变观察的方位和角度。
SetCamera为设置照相机的焦点位置和移动速度,移动的效果如同用户坐在飞行中的飞机从舷窗向外看一样。
其方程式如下:
procedure SetCamera(const camera: ICameraInfoGE; speed: Double); safecall;
其参数如表5-2所示。
表5-2 SetCamera参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
Camera |
In |
ICameraInfoGE |
照相机对象 |
|
Speed |
In |
Double |
移动的速度 |
移动的速度从0开始,数字越大,移动越快。
Delphi实例代码如下:
GeFlag: boolean;
……
procedure TGETest.Testfun();
var
cm: ICameraInfoGE;
begin
if GeFlag then begin
try
cm := F_AppGE.GetCamera(1); //在Delphi中为整数型数值,非零表示true
if cm <> nil then begin
F_AppGE.SetCamera(cm, 4);
……
end;
except
……
end;
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void SetCam()
{
CameraInfoGE cm = new CameraInfoGEClass();
cm = appGE.GetCamera(1);
if (cm != null)
{
appGE.SetCamera(cm, 4);
}
}
本例中首先获取当前的视场照相机对象,然后通过SetCamera设置已经获得的照相机对象的速度,这仅仅是个演示程序。还有个类似的方法SetCameraParams,此方法是设置照相机各项参数的,在设置深度上要好于SetCamera,请见下面的段落。
3)SetCameraParams
SetCameraParams为调整当前Google Earth的视场焦点的各个参数,无须重新定义照相对象。
其方程式如下:
procedure SetCameraParams(lat: Double; lon: Double; alt: Double; altMode: AltitudeModeGE; Range: Double; Tilt: Double; Azimuth: Double; speed: Double); safecall;
其参数如表5-3所示。
表5-3 SetCameraParams参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
lat |
In |
double双精度小数 |
纬度 |
|
lon |
In |
double双精度小数 |
经度 |
|
alt |
In |
double双精度小数 |
高度 |
|
altMode |
In |
altMode高度类型值类型 |
高度模式 |
|
Range |
In |
double双精度小数 |
范围 |
|
tilt |
In |
double双精度小数 |
倾角 |
|
Azimuth |
In |
double双精度小数 |
方位角 |
|
speed |
In |
double双精度小数 |
速度 |
|
|
纬度的取值在-90°~ 90°;经度的取值在-180°~ 180°,倾角的取值在为0°~ 90°。速度值为Google Earth自行定义的,取值为0~5,0为最小速度,5为最大。 |
Delphi代码如下:
F_AppGE: IApplicationGE;
……
procedure TForm1.SetCameraParamsClick(Sender: TObject);
var
tmplat,tmplng : double;
tmpalt : double;
tmprange : double;
tmptilt : double;
tmpAzimuth : double;
tmpSpeed: double;
begin
tmplat := 32.0; //焦点纬度
tmplng := 118.0; //焦点经度
tmpalt := 0; //焦点高度
tmprange := 500; //视场范围
tmptilt := 45; //镜头倾角
tmpAzimuth := 0; //镜头方位角
tmpSpeed := 4; //照相机移动速度
F_AppGE.SetCameraParams(tmplat,tmplng,tmpalt,RelativeToGroundAltitudeGE,tmprange, tmptilt,tmpAzimuth,tmpSpeed);
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void SetCamParm()
{
double tmplat, tmplng, tmpalt, tmprange, tmptilt, tmpAzimuth, tmpSpeed;
tmplat = 32.0; //焦点纬度
tmplng = 118.0; //焦点经度
tmpalt = 0; //焦点高度
tmprange = 500; //视场范围
tmptilt = 45; //镜头倾角
tmpAzimuth = 0; //镜头方位角
tmpSpeed = 4; //相机移动速度
appGE.SetCameraParams(tmplat, tmplng, tmpalt, (AltitudeModeGE)1, tmprange, tmptilt, tmpAzimuth, tmpSpeed);
}
这个代码中要注意,不能直接像Delphi代码一样使用RelativeToGroundAltitudeGE,而是要采用强制转换的方式。在C#中AltitudeModeGE是个枚举类型:
RelativeToGroundAltitudeGE = 1,
AbsoluteAltitudeGE = 2,
SetCameraParams是个非常有用的方法,通过此方法,可以动态改变Google地图窗口视点的移动。上面的代码中首先设置了目标地点的经度、纬度、高度,另外还包括范围和方位角转角、速度等指标。然后操纵Google Earth的地图窗口“飞行”到经度为118°,纬度为32°的地点。
以上的例子只是个最简单的应用演示,读者可以自行修改代码以实现更加复杂的功能。
开发时要注意经纬度参数的前后位置,并且注意所有参数的值类型。
关于照相机移动还有个重要的属性,就是自动“飞行(Fly-To)”速度,这是个默认的移动速度值,通过人工或者代码都可以设置。
4)AutoPilotSpeed
AutoPilotSpeed为自动飞行(比如搜索或者定位到某个地理要素时)的照相机焦点的速度。使用方式为“读(Get)/写(Set)”。值类型为Double。
其方程式如下:
property AutoPilotSpeed: Double
read Get_AutoPilotSpeed
write Set_AutoPilotSpeed;
Delphi代码如下:
F_AppGE: IApplicationGE;
……
procedure TForm1.Button3Click(Sender: TObject);
var aspeed :double;
begin
aspeed := F_AppGE.AutoPilotSpeed;
showmessage(floattostr(aspeed));
end;
C#代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private double getAutoPilotSpeed()
{
double sp = appGE.AutoPilotSpeed;
return sp;
}
代码执行后, Google Earth的自动飞行模式被触发,就会按照此处设置好的AutoPilot Speed值飞行。自动飞行模式即通过单击某地理要素(如一个点)或者是执行了KML脚本后,Google Earth视场照相机会自动“飞行”到地理要素所在地。读者自己可以双击地址栏中的某个要素实验一下。
AutoPilotSpeed的结果对应的是【Tools】→【Options】菜单命令中的【Fly-To Speed】值,如图5-9所示。

图5-9 自动飞行速度
3.截屏设置
Google Earth有个很有用的功能,按【Ctrl+Alt+S】组合键,可以保存当前地图的截图照片,默认是JPG格式的彩色图片。IApplicationGE接口也提供了一个SavaScreenShot方法,可以获得当前地图窗口内容的灰度图片,是黑白的。
SaveScreenShot为当前地图视场范围截屏,保存成黑白效果的图片。保存的黑白照片可以定义清晰程度。
其方程式如下:
procedure SaveScreenShot(const fileName: WideString; quality: Integer); safecall;
其参数如表5-4所示。
表5-4 SaveScreenShot参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
fileName |
In |
WideString |
保存文件的完整路径,包括名称 |
|
quality |
In |
Integer |
保存文件的质量级别 |
quality参数表示图片的清晰度质量,对保存结果的清晰度有很大影响,数字越大越清晰。如图5-10和图5-11所示,这两张图的清晰程度就有鲜明的对比。

图5-10 高清晰度 图5-11 低清晰度
4.加载KML操作
在Google Earth中选择【File】→【Open】命令,可以打开KML/KMZ文件。Google Earth的API中也提供了两个功能类似的方法——OpenKMLFile和LoadKMLData,这两个方法都可以向Google Earth加载KML文件,都能操作KMZ文件,但是各自略有不同。
1)OpenKMLFile
OpenKMLFile可以使Google Earth打开KML文件。注意要和LoadKMLData方法区别开。OpenKMLFile会清空执行历史,而LoadKMLData却不会清空执行历史,这一点在开发的时候一定要注意。
其方程式如下:
procedure OpenKmlFile(const fileName: WideString; suppressMessages: Integer); safecall;
其参数如表5-5所示。
表5-5 OpenKMLFile参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
filename |
In |
WideString |
要打开的KML文件完整路径,包括名称 |
|
suppressMessages |
In |
Bool |
是否关闭Google Earth在打开KML文件时提示或者报错的窗口 |
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TGETest.OpenKML(kmlpath: WideString);
begin
……
F_AppGE.OpenKmlFile(kmlpath, 1);
end;
……
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
//<param name="fp">fp为KML文件的地址</param>
private void open_KMLfile(string fp)
{
appGE.OpenKmlFile(fp,1);
}
本例中的参数kmlpath为KML文件地址,如“c:\test.kml”。这里的所有代码都未加入容错机制,例如此处实际使用过程中可能还会出现文件不存在的情况,需要首先加入判断代码,确保运行无误。
2)LoadKMLData
LoadKMLData可以使Google Earth加载KML文件。注意要和OpenKMLFile区别开来。
其方程式如下。
procedure LoadKmlData(var kmlData: WideString); safecall;
其参数如表5-6所示。
表5-6 LoadKmlData参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
kmlData |
In |
WideString |
需要加载入Google Earth的KML文档 |
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TGETest.LoadKMLData(kmlData: WideString);
begin
……
F_AppGE.LoadKmlData(kmlData);
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
// 加载KML文件内容
// <param name="kmlstr">KML文件内容</param>
private void load_KML(string kmlstr)
{
appGE.LoadKmlData(ref kmlstr);
}
|
|
注意:C#中编程,在引用参数的时候为传址。 |
本段代码中的LoadKMLData方法的参数kmlData应该是一个KML文档实体,而不是KML文件名(OpenKMLFile方法的参数为KML文件的文件名)。
例如,参数kmlData可以加载下面的KML语句。
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://earth.google.com/kml/2.1'>
<Document>
<Placemark>
<name>CantonmentPoint_1</name>
<LookAt>
<longitude>118.27715</longitude>
<latitude>32.2517</latitude>
<altitude>0</altitude>
<range>2000</range>
<tilt>-5.821565606503298e-015</tilt>
<heading>7.29646319265843</heading>
</LookAt>
<Point>
<coordinates>118.322,32.27,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>CantonmentPoint_2</name>
<LookAt>
<longitude>118.27715</longitude>
<latitude>32.2517</latitude>
<altitude>0</altitude>
<range>2000</range>
<tilt>-5.821565606503298e-015</tilt>
<heading>7.29646319265843</heading>
</LookAt>
<Point>
<coordinates>118.2323,32.2334,0</coordinates>
</Point>
</Placemark>
</Document>
</kml>
以上的KML语句,可以放在一个字符串变量中,然后将该变量作为LoadKMLData的参数加载。
5.地理要素操作
获取Google Earth中加载的地理要素,可以采用GetFeatureByName方法,该方法通过要素名称确定要素对象,请参考IFeatureGE的name属性。
1)GetFeatureByName
定义为按照要素的名称得到地图要素对象,返回值类型为IFeatureGE对象。
其方程式如下:
function GetFeatureByName(const Name: WideString): IFeatureGE; safecall;
其参数如表5-7所示。
表5-7 GetFeatureByName参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
Name |
In |
WideString |
要素的名称 |
Delphi实例代码:
……
procedure TGETest.SetFeature(name: string; v: Integer);
var
myFeature: IFeatureGE;
begin
myFeature:= F_AppGE.GetFeatureByName(name);
if myFeature <> nil then begin
myFeature.Visibility := v;
……
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
/// <summary>
/// 设置某要素是否可见
/// </summary>
/// <param name="f_name">要素名称</param>
private void setFeatureVisibility(string f_name)
{
FeatureGE i_f = appGE.GetFeatureByName(f_name);
if (i_f != null)
{
i_f.Visibility = 1;
}
}
myFeature取到的是IFeatureGE对象,而不是对象名称,所以后面的代码可以直接针对myFeature进行操作,如设置是否可视(见代码)。
2)GetFeatureByHref
定义为按照要素的HREF得到地图要素对象,返回值类型为IFeatureGE对象。
其方程式如下。
function GetFeatureByHref(const href: WideString): IFeatureGE; safecall;
其参数如表5-8所示。
表5-8 GetFeatureByHref参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
href |
In |
WideString |
要素对象的HFEF |
在Google Earth加载了KML文档之后,地址要素栏中会有响应的项目呈树状显示,此时双击某一项要素之后,地图窗口会自动缩放和旋转,“飞行”到那个被双击要素的所在地。这个过程其实是Google Earth首先判断该要素有无视场(View),有视场才能有“飞行”定位的过程,无视场则无法定位。
3)SetFeatureView
IApplicationGE接口也提供了一种“飞行”定位的功能SetFeatureView。表示设置当前地图照相机的焦点位置和移动速度,移动到某个要素处定焦。
其方程式如下:
procedure SetFeatureView(const feature: IFeatureGE; speed: Double); safecall;
其参数如表5-9所示。
表5-9 SetFeatureView参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
feature |
In |
IFeatureGE |
要素对象 |
|
speed |
In |
Double |
相机焦点的移动速度 |
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnsetFeatureViewClick(Sender: TObject);
var
tmpFeature :IFeatureGE;
begin
try
tmpFeature := F_AppGE.getFeatureByName('testplacemark1');
F_AppGE.setFeatureView(tmpFeature,4.0);
except
//……
end;
end;
C#的实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
/// <summary>
/// 设置要素的视场
/// </summary>
/// <param name="f_name">要素名称</param>
private void setFeatureView(string f_name)
{
FeatureGE i_f = appGE.GetFeatureByName(f_name);
if (i_f != null)
{
appGE.SetFeatureView(i_f, 4.0);
}
}
通过要素名称获取要素对象tmpFeature,然后通过setFeatureView方法,实现从其他位置飞行定位到tmpFeature所在的位置,并且飞行的速度设置为4.0,如图5-12所示。

图5-12 定焦后
4)GetHighlightedFeature
IFeatureGE接口中有高亮某个要素的方法Highlight及一个判断是否要素被高亮的属性,这里提供了一个获取被高亮要素的方法GetHighlightedFeature。
GetHighlightedFeature表示得到当前高亮显示的地理要素。
其方程式如下:
function GetHighlightedFeature: IFeatureGE; safecall;
此方法的使用请参见Highlight方法,Highlight是高亮显示某一个要素。
6.要素的气泡信息窗口操作
地图窗口内的地理要素,绝大多数会拥有一个标记(Placemark),特别是点状要素。单击这个标记,会弹出一个信息气泡窗口,这个窗口里可以包含各种各样的信息,如图片、文字、表格、超链接等。这些信息可以通过KML定义要素的时候设置。
IApplicationGE接口提供了显示和隐藏气泡窗口的两个方法,分别是ShowDescription Balloon和HideDescriptionBalloons。
1)ShowDescriptionBalloon
ShowDescriptionBalloon表示针对某一个地图要素,Google Earth弹出一个带有相应的表述信息的气泡窗口。
其方程式如下:
procedure ShowDescriptionBalloon(const feature: IFeatureGE); safecall;
其参数如表5-10所示。
表5-10 ShowDescriptionBalloon参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
feature |
In |
IFeatureGE |
地理要素对象 |
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnShowDescriptionBalloonClick(Sender: TObject);
var
tmpFeature :IFeatureGE;
begin
try
tmpFeature := F_AppGE.getFeatureByName('testplacemark1');
F_AppGE.ShowDescriptionBalloon(tmpFeature);
except
//……
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void showDesBallon(string f_name)
{
FeatureGE i_f = appGE.GetFeatureByName(f_name);
if (i_f != null)
{
appGE.ShowDescriptionBalloon(i_f);
}
}
这是一个很实用的方法,有很多Web应用中都使用到它。这个方法和KML、HTML结合起来可以实现如弹出对话框这样的功能和显示效果。ShowDescriptionBalloon的参数为要素对象,而不是对象名称。
代码执行后的效果如图5-13所示。

图5-13 气泡窗口
2)HideDescriptionBalloons
HideDescriptionBalloons为关闭所有地理要素的气泡窗口。
其方程式如下。
procedure HideDescriptionBalloons; safecall;
7.屏幕坐标和地理坐标的转换问题
进行GIS开发项目时常常遇到的问题,也是最头疼的问题之一就是屏幕坐标和地理坐标之间的转换问题。如屏幕中点或者鼠标位置和地理坐标之间的关系算法等。Google Earth虽然谈不上是个GIS软件,但是也提供了一个初级的坐标转换方法GetPointOnTerrainFrom ScreenCoords,它可以把屏幕的四角及中心点转换成地理坐标。
GetPointOnTerrainFromScreenCoords为取得地面上某一点的屏幕坐标。
其方程式如下:
function GetPointOnTerrainFromScreenCoords(screen_x: Double; screen_y: Double): PSafeArray; safecall;
其参数如表5-11所示。
表5-11 GetPointOnTerrainFromScreenCoords参数
|
参 数 |
输 入 方 向 |
值 类 型 |
定 义 |
|
screen_x |
In |
Double |
屏幕坐标X |
|
screen_y |
In |
Double |
屏幕坐标Y |
Google Earth很有意思,只提供了单向的屏幕坐标到地理坐标的装换。在这里screen_x和screen_y的取值都是在-1~+1的,屏幕坐标的取值如图5-14所示。
|
图5-14 屏幕坐标
Delphi实例代码:
procedure TForm1.Button1Click(Sender: TObject);
var
tmpArr : IPointOnTerrainGE;
begin
tmpArr := F_AppGE.GetPointOnTerrainFromScreenCoords(0.0,0.0); //获得屏幕中心坐标
showmessage(floattostr(tmpArr.Latitude) + ',' + floattostr(tmpArr.Longitude));
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void GetCoordinateFromScreen()
{
PointOnTerrainGE pt = appGE.GetPointOnTerrainFromScreenCoords(0.0, 0.0);
if (pt != null)
{
double m_lat = pt.Latitude;
double m_lng = pt.Longitude;
MessageBox.Show(m_lng.ToString() + "," + m_lat.ToString());
}
}
图5-12中已经表明,地图窗口的中心点坐标为(0.0, 0.0),代码执行后,弹出的提示框内容如图5-15所示,反映的是目前地图窗口中心点的坐标。
所以要想获得鼠标当前在地图窗口中实地对应的位置,就必须按照比例关系来确定。
8.要素文件夹操作
1)GetMyPlaces
GetMyPlaces介绍如下。
l 定义:得到Google Earth中的“My Places”。虽然它是个文件夹,但Google Earth也将之视为一个要素。
l 方程式:function GetMyPlaces: IFeatureGE; safecall;。
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnGetmyPlaceClick(Sender: TObject);
var
tmpFeature :IFeatureGE;
begin
try
tmpFeature := F_AppGE.GetMyPlaces;
showmessage(tmpFeature.Name);
except
//……
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private FeatureGE getMyPlaceFeature()
{
FeatureGE ft = appGE.GetMyPlaces();
if (ft != null)
{
return ft;
} else {
return null;
}
}
执行上述代码后,程序弹出提示框,说明取到的要素是“My Places”,中文版Google Earth中名称为“我的位置”,如图5-16所示。
2)GetTemporaryPlaces
GetTemporaryPlaces介绍如下。
l 定义:得到临时位置文件夹,中文版的Google Earth中文名称为“临时位置”。
l 方程式:function GetTemporaryPlaces: IFeatureGE; safecall;。
Delphi实例代码如下:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnGetTemporaryPlacesClick(Sender: TObject);
var
tmpFeature :IFeatureGE;
begin
try
tmpFeature := F_AppGE.GetTemporaryPlaces;
if (tmpFeature.HasView <> 0) then
showmessage(tmpFeature.name +'有视场')
else
showmessage(tmpFeature.name +'无视场')
except
//……
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private FeatureGE getTempFeature()
{
FeatureGE ft = appGE.GetTemporaryPlaces();
if (ft != null)
{
return ft;
} else {
return null;
}
}
本例Delphi代码指出了临时父要素的视场(View)情况,执行后的效果如图5-17所示。
3)GetLayersDatabases
GetLayersDatabases介绍如下。
l 定义:根据图层列表获取要素数据源集合,该数据源就是要素集合。
l 方程式:function GetLayersDatabases: IFeatureCollectionGE; safecall;。
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnGetLayersDatabasesClick(Sender: TObject);
var
tmpFeatures :IFeatureCollectionGE;
i:integer;
tmpstr : string;
begin
try
tmpFeatures := F_AppGE.GetLayersDatabases;
for i := 1 to tmpFeatures.Count do
begin
tmpstr := tmpstr + #13#10 + tmpFeatures[i].name;
end;
showmessage(tmpstr);
except
//……
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
/// <summary>
/// 获得图层列表名称
/// </summary>
/// <returns>字符串数组</returns>
private string[] getLayersDatabase()
{
FeatureCollectionGE lyDB = appGE.GetLayersDatabases();
if (lyDB != null)
{
int i;
string[] namelist = new string[lyDB.Count];
for (i = 0; i < lyDB.Count - 1; i++)
{
namelist[i] = lyDB[i].Name;
}
return namelist;
}
else
{
return null;
}
}
执行后的效果如图5-18所示。

图5-16 My Places文件夹 图5-17 临时位置 图5-18 要素集合
9.窗口句柄操作
如果要开发一个包含Google Earth的程序,获得主窗口的句柄是必要的。例如,通过代码控制Google Earth主窗口的大小和状态这种需求,首先就需要采用GetMainHWnd取得主窗口的句柄再做处理。
1)GetMainHwnd
GetMainHwnd的介绍如下。
l 定义:取得Google Earth程序主窗口的句柄。
l 方程式:function GetMainHwnd: SYSUINT; safecall;。
|
|
在Delphi中,可以将句柄变量申明成HWND类型,其实HWND类型就是LongWord类型的派生,是整型的一种,取值范围为0~4 294 967 295之间。 |
Delphi实例代码:
var GEMainWinHandle:HWND;
……
GEMainWinHandle := F_AppGE.GetMainHwnd; //主窗口句柄
……
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private IntPtr getGEHandle()
{
try
{
int GEMainWinHandle = appGE.GetMainHwnd();
return new IntPtr(GEMainWinHandle);
}
finally { }
}
在获取了Google Earth的主窗口之后,有时候还需要对地图窗口进行操作,如需要移动地图窗口到用户自己的程序上。这个时候就需要获得地图窗口句柄,然后调用Windows的API来移动和设置地图窗口句柄的父窗口,通过 GetRenderHwnd可以获取地图窗口的句柄。
以前Keyhole版本的API没有提供这个方法,这时候只有通过其他的方法获取地图窗口句柄,如利用第三方工具获取。
2)GetRenderHwnd
GetRenderHwnd的介绍如下。
l 定义:返回Google Earth的地图窗口。
l 方程式:function GetRenderHwnd: SYSUINT; safecall;。
|
|
在Delphi中,可以将句柄变量申明成HWND类型,其实HWND类型就是LongWord类型的派生,是整型的一种,取值范围在0~4 294 967 295之间。下面例子中的两个句柄变量正好申明成了HWND类型和LongWord类型。 |
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.getmaphandleClick(Sender: TObject);
var
GEMapWinHandle:LongWord;
GEMainWinHandle,pnlMap:HWND;
r: TRect;
begin
GEMainWinHandle := F_AppGE.GetMainHwnd;
GEMapWinHandle := F_AppGE.GetRenderHwnd;
pnlMap := Panel2.Handle;
Windows.SetParent(GEMapWinHandle, pnlMap); //将地图的父窗口设置为panel
……
end;
如上面的例子,Google Earth这一版本的API比较明确地突出了地图窗口的句柄,可以通过这个方法获得地图子窗口句柄,并结合前面获取的Google Earth程序主窗口句柄的方法,能够写出很多复杂的程序,如图5-19所示。

图5-19 地图窗口句柄
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void button1_Click(object sender, EventArgs e)
{
try
{
int GEMapHandle = appGE.GetRenderHwnd();
IntPtr mapPtr = new IntPtr(GEMapHandle);
Apilibs.SetParent(mapPtr, plmap.Handle);
}
finally { }
}
|
|
在C#中调用Windows的API有点麻烦,需要引入User32.dll动态链接库,利用DllImport方法可以做到: [DllImport("User32.dll")] public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); |
具体Windows API函数在.net平台上的调用和使用,不同的编程语言和环境有所不同,具体请自行参考相关文档,在此不做赘述。
C#代码执行后可得到如图5-20所示的效果。

图5-20 抓取地图窗口到Panel上
上图中Google Earth的地图窗口被嵌入到了用户自己编写的程序中。其实承载地图窗口的是一个Delphi中的panel,通过Windows的API将地图窗口的父窗口设置为panel,得以在自己的程序中嵌入地图,在本地后台仍然是启动了一个Google Earth进程。
10.IApplicationGE属性。
1)Google Earth版本
Google Earth版本介绍如下。
① VersionMajor
l 定义:Google Earth程序的版本号主号。
l 使用方式:读(Get)。
l 值类型:Integer。
l 方程式:property VersionMajor: SYSINT
read Get_VersionMajor;。
② VersionMinor
l 定义:Google Earth程序的版本号辅号。
l 使用方式:读(Get)。
l 值类型:Integer。
l 方程式:property VersionMinor: SYSINT
read Get_VersionMinor;。
③ VersionBuild
l 定义:Google Earth程序的构建号。
l 使用方式:读(Get)。
l 值类型:Integer。
l 方程式:property VersionBuild: SYSINT
read Get_VersionBuild;。
以上介绍的几个版本操作方法的Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnMajorVerClick(Sender: TObject);
var
tmpMajor,tmpMinor,tmpBuild, tmpVerApptype : integer;
begin
tmpMajor := F_AppGE.VersionMajor;
tmpMinor := F_AppGE.VersionMinor;
tmpBuild := F_AppGE.VersionBuild;
tmpVerApptype := F_AppGE.VersionAppType;
edVer.Text := inttostr(tmpMajor) + '.'
+ inttostr(tmpMinor) +'.'
+ inttostr(tmpBuild) + '.'
+ inttostr(tmpVerApptype);
end;
以上代码的运行结果如图5-21所示。
对应的C#代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void getVersonNumber()
{
int tmpMajor, tmpMinor, tmpBuild, tmpVerApptype;
tmpMajor = appGE.VersionMajor;
tmpMinor = appGE.VersionMinor;
tmpBuild = appGE.VersionBuild;
}
在如图5-21所示的4.1.7087.5中,第一段“4”是程序版本号主号,第二段“1”是辅号,第三段“7087”是构建号,最后一段数字为版本类型编号。这4段数字构成了Google Earth的版本全编号。
版本类型编号请参照后面的VersionAppType的详细解释,在Dephi中数值和版本号的对应关系如表5-12所示。
表5-12 Google Earth版本号
|
版 本 |
名 称 |
值 |
|
EnterpriseClientGE |
|
0 |
|
ProGE |
|
1 |
|
PlusGE |
|
2 |
|
FreeGE |
|
5 |
|
UnknownGE |
Unknown |
null |
如图5-22所示的是Google Earth的“关于”窗口界面。
![]()
图5-21 程序构建号 图5-22 Google Earth的“关于”窗口界面
④ VersionAppType
l 定义:Google Earth程序版本类型,是免费版还是专业版或其他版本。此处该类型为一个枚举值。
l 使用方式:读(Get)。
l 值类型:Integer。
l 方程式:property VersionAppType: AppTypeGE
read Get_VersionAppType;。
程序的版本类型如表5-13所示。
表5-13 Google Earth版本
|
版本类型枚举值 |
定 义 |
|
EnterpriseClientGE |
Google Earth企业版客户端 |
|
ProGE |
Google Earth Pro版 |
|
PlusGE |
Google Earth Plus版 |
|
FreeGE |
Google Earth Free版 |
|
UnknownGE |
未知版本 |
例子代码请参看前面的VersionMajor、VersionMinor、VersionBuild的例子和图。
2)读取地图数据流进度
① StreamingProgressPercentage
StreamingProgressPercentage介绍如下。
l 定义:反映Google Earth获取当前地图数据流的进度。
l 使用方式:读(Get)。
l 值类型:Integer。
l 方程式:property StreamingProgressPercentage: Integer
read Get_StreamingProgressPercentage;。
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.Button2Click(Sender: TObject);
begin
TimerStream.Enabled := true;
end;
procedure TForm1.TimerStreamTimer(Sender: TObject);
var
tepStream : Double;
begin
tepStream := F_AppGE.StreamingProgressPercentage;
edStream.Text := floattostr(tepStream);
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private double getDownloadStreamProcess()
{
return appGE.StreamingProgressPercentage;
}
通过StreamingProgressPercentage方法可以获取现时的地图传输完成率,这个完成率是和地图窗口下方的“Streaming”联系起来的,如图5-23所示。

图5-23 Google Earth的数据读取进度
② ViewExtents
ViewExtents介绍如下。
l 定义:返回当前视场区域,获取值是IViewExtentsGE接口对象。
l 使用方式:读(Get)。
l 值类型:IViewExtentsGE。
l 方程式:property ViewExtents: IViewExtentsGE
read Get_ViewExtents;。
此方法的实例请参见IFeatureGE接口的HasView。
③ ElevationExaggeration
传统GIS的三维模块的必备功能就是地形拉伸,介绍如下。
l 定义:纵向拉伸地形,使之被扩大。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property ElevationExaggeration: Double read Get_ElevationExaggeration writeSet _ElevationExaggeration;。
该属性的取值可为0~3。当取值为0的时候,地形是平的;当取值为1的时候,地形保持真实的形状;当大于1的时候,以倍数拉伸地形。
Delphi实例代码:
F_AppGE: IApplicationGE;
……
procedure TForm1.btnElevationExaggerationClick(Sender: TObject);
begin
F_AppGE.ElevationExaggeration := 1;
end;
以上代码取值不同的时候,地形的拉伸效果也不同。如图5-24和图5-25所示,对比可以发现地图起伏明显不同。图5-24中的地形起伏较大,是由于ElevationExaggeration取值为3的结果;图5-25地形起伏正常,是由于ElevationExaggeration取值为1的结果。

图5-24 拉伸状态 图5-25 真实状态
3)Google Earth控件
① TourController
TourController介绍如下。
l 定义:返回漫游控件。
l 使用方式:读(Get)。
l 值类型:ITourControllerGE。
l 方程式:property TourController: ITourControllerGE
read Get_TourController;。
|
|
例子代码请参见5.3.11节中对ITourControllerGE接口的描述与实例。 |
② SearchController
SearchController介绍如下。
l 定义:返回搜索控件。
l 使用方式:读(Get)。
l 值类型:ISearchControllerGE。
l 方程式:property SearchController: ISearchControllerGE
read Get_SearchController;。
|
|
例子代码请参见5.3.9节中对ISearchControlerGE接口的描述与实例。 |
③ AnimationController
AnimationController介绍如下。
l 定义:返回动画控件。
l 使用方式:读(Get)。
l 值类型:ISearchControllerGE。
l 方程式:property AnimationController: IAnimationControllerGE
read Get_AnimationController;。
|
说明 |
例子代码请参见5.3.2节中对IAnimationControllerGE接口的描述与实例。 |
5.3.2 ICameraInfoGE接口
ICameraInfoGE接口是Google Earth照相机的接口,表示Google Earth地图上的某一点位置的照相机,可以获取并设置照相机的焦点位置、转角、仰角、方位角等参数。通过设置照相机的焦点位置,可以达到移动照相机的目的。这些操作的效果与IApplicationGE接口的方法SetCameraParams很类似。
地球移动和旋转的参照面此时就是屏幕,而并非人眼的视平面。所以在针对屏幕时,Google Earth提供了一个叫做“视场照相机”的对象。通过该对象,可以转换视角,获得不同的视觉体验,如旋转角度、倾斜角度等。
目前所有的三维场景的算法,都是基于如图5-26所示的原理的。
|
|
图5-26 视场参考面
视场照相机就是替代视平面的工具,通过视场照相机的移动、旋转和倾斜,将不同的视觉场景展现出来。
一般来说,确定空间3个点的位置需要经纬度和高度,确定一个轴向需要方位角和倾角,确定场景的大小还需要知道范围。以上这些确定准则,简称为“三确定”。Google Earth视场照相机的“三确定”一共需要6个参数,另外加上一个选项参数。
1.空间位置
1)FocusPointLatitude
FocusPointLatitude介绍如下。
l 定义:照相机焦点位置的纬度。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property FocusPointLatitude: Double
read Get_FocusPointLatitude
write Set_FocusPointLatitude;。
Delphi实例代码:
GeFlag: boolean;
……
procedure TGETest.SetLat(lat: double);
var
cm: ICameraInfoGE;
begin
if GeFlag and (F_AppGE <> nil) then begin
try
cm := F_AppGE.GetCamera(1);
if cm <> nil then begin
cm.FocusPointLatitude := lat;
F_AppGE.SetCamera(cm, 4);
end;
except
……
end;
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamFocusLat(double cmlat)
{
CameraInfoGE cm = appGE.GetCamera(1);
if (cm != null)
{
cm.FocusPointLatitude = cmlat;
appGE.SetCamera(cm, 4);
}
}
2)FocusPointLongitude
FocusPointLongitude介绍如下。
l 定义:照相机焦点的经纬位置。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property FocusPointLongitude: Double
read Get_FocusPointLongitude
write Set_FocusPointLongitude;。
Delphi实例代码:
……
procedure TGETest.SetLon(lng: double);
var
cm: ICameraInfoGE;
begin
if FConnected and (F_AppGE <> nil) and geGrabbed then begin
try
cm := F_AppGE.GetCamera(1);
if cm <> nil then begin
cm.FocusPointLongitude := lng;
F_AppGE.SetCamera(cm, 5);
end;
except
……
end;
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamFocusLng(double cmlng)
{
CameraInfoGE cm = appGE.GetCamera(1);
if (cm != null)
{
cm.FocusPointLongitude = cmlng;
appGE.SetCamera(cm, 4);
}
}
3)FocusPointAltitude
FocusPointAltitude介绍如下。
l 定义:照相机焦点位置的高度,不过返回值取决于AltitudeMode的设置,参见下面对AltitudeMode的介绍。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property FocusPointAltitude: Double
read Get_FocusPointAltitude write Set_FocusPointAltitude;。
Delphi实例代码:
……
function TFormCameraSample.GetAltitude: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.FocusPointAltitude;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamFocusAlt(double cmAlt)
{
CameraInfoGE cm = appGE.GetCamera(1);
if (cm != null)
{
cm.FocusPointAltitude = cmAlt;
appGE.SetCamera(cm, 4);
}
}
4)FocusPointAltitudeMode
FocusPointAltitudeMode介绍如下。
l 定义:照相机焦点位置的高度模式。
l 使用方式:读(Get)/写(Set)。
l 值类型:AltitudeModeGE。
l 方程式:property FocusPointAltitudeMode: AltitudeModeGE
read Get_FocusPointAltitudeMode
write Set_FocusPointAltitudeMode;。
Delphi实例代码:
function TForm1.GetAltitude: AltitudeModeGE;
var
cm: ICameraInfoGE;
begin
cm := FApplicationGE.GetCamera(1);
if cm <> nil then
result:= cm.FocusPointAltitudeMode;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamAltMode()
{
CameraInfoGE cm = appGE.GetCamera(1);
cm.FocusPointAltitudeMode = (AltitudeModeGE)1;
}
在5.3.1(2)节中曾经说明,FocusPointAltitudeMode是个枚举类型。
RelativeToGroundAltitudeGE = 1,
AbsoluteAltitudeGE = 2,
2.轴向
1)Azimuth
Azimuth介绍如下。
l 定义:相机镜头的方位角。通常情况下方位角的取值范围在0~360°,而Google Earth中取值范围被定义在-180°~ +180°之间。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property Azimuth: Double
read Get_Azimuth
write Set_Azimuth;。
Delphi实例代码:
GeFlag: boolean;
……
function TGETest.GetAzimuth: Double;
var
cm: ICameraInfoGE;
begin
result := 0;
if GeFlag then begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result := cm.Azimuth;
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamAzimuth()
{
CameraInfoGE cm = appGE.GetCamera(1);
cm.Azimuth = 90.0;
}
2)Tilt
Tilt介绍如下。
l 定义:照相机镜头的倾角。在Google Earth中倾角的取值范围在0~90°之间。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property Tilt: Double
read Get_Tilt
write Set_Tilt;。
如图5-27所示,可以很容易弄懂方位角Azimuth和倾角Tilt的区别。

图5-27 方位角与倾角
Delphi实例代码:
function TGEPanel.GetTilt: Double;
var
cm: ICameraInfoGE;
begin
result := 0;
if FConnected then begin
cm := F_AppGE.GetCamera(1);
result := cm.Tilt; //取得倾角
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamTilt()
{
CameraInfoGE cm = appGE.GetCamera(1);
cm.Tilt = 45.0;
}
3.视场范围(三确定)
Range介绍如下。
l 定义:照相机到被观察点的距离,单位是“米”。
l 使用方式:读(Get)/写(Set)。
l 值类型:Double。
l 方程式:property Range: Double
read Get_Range
write Set_Range;。
Delphi实例代码:
function TGEPanel.GetRange: Double;
var
cm: ICameraInfoGE;
begin
result := 0;
if FConnected then begin
cm := F_AppGE.GetCamera(1);
result := cm.Range;
end;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setCamRange()
{
CameraInfoGE cm = appGE.GetCamera(1);
cm.Range = 1000;
}
4.一个视场照相机的完整例子
1)实例代码
下面给出了一个完整的关于ICameraInfoGE的Delphi代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TFormCameraSample = class(TForm)
……
private
{ Private declarations }
……
public
{ Public declarations }
end;
var
FormCameraSample: TFormCameraSample;
implementation
uses EARTHLib_TLB;
{$R *.dfm}
var F_AppGE: IApplicationGE;
首先窗体运行,创建新的Google Earth的进程:
//程序开始运行
procedure TFormCameraSample.FormCreate(Sender: TObject);
begin
try
F_AppGE := CoApplicationGE.Create();
except
showmessage('启动Google Earth失败');
end;
end;
先获取当前的视场照相机,并获取照相机的各个参数,显示在TextBox上,代码如下:
//单击【获取】按钮
procedure TFormCameraSample.btnGetClick(Sender: TObject);
begin
if ((F_AppGE <> nil) and (F_AppGE.IsInitialized <> 0)) then
begin
edAlt.Text:= floattostr(GetAltitude());
edLng.Text := floattostr(GetLng());
edLat.Text := floattostr(GetLat());
edAzi.Text := floattostr(GetAzimuth());
edTilt.Text := floattostr(GetTilt());
edRan.Text := floattostr(GetRange());
end
else
begin
showmessage('请稍等……');
end;
end;
//程序窗口关闭
procedure TFormCameraSample.FormClose(Sender: TObject; var Action: TCloseAction);
begin
F_AppGE := nil;
end;
function TFormCameraSample.GetAltitude: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.FocusPointAltitude;
end;
获取照相机各个参数的方法函数,如方位角、经纬度等信息的代码如下:
//获取照相机方位角
function TFormCameraSample.GetAzimuth: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.Azimuth;
end;
//获取照相机纬度
function TFormCameraSample.GetLat: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.FocusPointLatitude;
end;
//获取照相机经度
function TFormCameraSample.GetLng: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.FocusPointLongitude;
end;
//获取照相机倾斜角
function TFormCameraSample.GetTilt: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.Tilt;
end;
//获取照相机高度
procedure TFormCameraSample.SetAltitude(v: double);
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
cm.FocusPointAltitude := v;
end;
//获取照相机范围
function TFormCameraSample.GetRange: double;
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
result:= cm.Range;
end;
设置Google Earth的视场照相机的各个参数,代码如下:
//设置照相机方位角
procedure TFormCameraSample.SetAzimuth(v: double);
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
cm.Azimuth := v;
end;
//设置照相机纬度
procedure TFormCameraSample.SetLat(v: double);
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
cm.FocusPointLatitude := v;
end;
//设置照相机经度
procedure TFormCameraSample.SetLng(v: double);
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
cm.FocusPointLongitude := v;
end;
//设置照相机倾斜角
procedure TFormCameraSample.SetTilt(v: double);
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
cm.Tilt := v;
end;
//设置照相机范围
procedure TFormCameraSample.SetRange(v: double);
var
cm: ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
cm.Range := v;
end;
单击按钮时调用的方法代码如下:
//单击【设置】按钮
procedure TFormCameraSample.BtnSetClick(Sender: TObject);
begin
if (F_AppGE <> nil) then
begin
SetAltitude(strtofloat(edAlt.Text));
SetLat(strtofloat(edLat.Text));
SetLng(strtofloat(edLng.Text));
SetAzimuth(strtofloat(edAzi.Text));
SetTilt(strtofloat(edTilt.Text));
SetRange(strtofloat(edRan.Text));
SetGoogleEarthCamera;
end
else
begin
showmessage('请稍等……');
end;
end;
//设置照相机
procedure TFormCameraSample.SetGoogleEarthCamera;
var
cm: ICameraInfoGE;
cmobj :ICameraInfoGE;
begin
cm := F_AppGE.GetCamera(1);
if cm <> nil then
begin
cmobj := CoCameraInfoGE.create();
cmobj.FocusPointLatitude := cm.FocusPointLatitude;
cmobj.FocusPointLongitude := cm.FocusPointLongitude;
cmobj.FocusPointAltitude := cm.FocusPointAltitude;
cmobj.Tilt := cm.Tilt;
cmobj.Azimuth := cm.Azimuth;
cmobj.Range := cm.Range;
F_AppGE.SetCamera(cmobj, 5.0);
end;
end;
end.
2)代码分析
本例子代码的逻辑主要包括两个方面:一是获取参数值;另一个是设置参数值。经纬度、高度可以确定照相机的空间位置,而视线的方位则是通过方位角、倾角和范围确定的。
上面的这个例子,用户可以截获当前的Google Earth地图视场照相机的各个参数,也可以通过设置自定义数值调整照相机的方位和视线方向。
代码执行后的效果如图5-28所示。

图5-28 照相机参数
程序运行后会自动启动Google Earth。当Google Earth启动之后,用户单击【获取】按钮,程序能够获取当前地图视场照相机的各项参数。可以改动任何一个值,然后单击【设置】按钮,反向控制Google Earth的视场焦点转移。
5.3.3 IFeatureGE接口
IFeatureGE接口是针对Google Earth要素对象操作的接口。所谓的Google Earth要素,指的是加载的由KML描绘的地理要素。此接口提供的最终目的仅仅是捕获并显示,并没有如添加、删除这种操作类型。地理要素在Google Earth中是由KML组织的,通过组织文字、图片、超链接等资源,丰富Google Earth的附加资源。
这些要素包括:地标(Placemark)、图层(Overlay)、文件夹节点(Folder)、文档节点(Document)、 超链接(NetworkLink),Google Earth的官方资料上还提及了流层(Streamed Layers)要素。
1.IFeatureGE
1)子要素和父要素的操作
通常情况下,与KML的文档结构类似,在Google Earth中地理要素的层次分布呈现“树”状结构——一个父要素可以包含一个或者多个子要素,其下的子要素还可以再包含子要素,以此类推。这样一来,需要有一种方法,以获得某个父要素所拥有的子要素,并且以集合的形式返回,Google Earth API提供了GetChildren的方法。
① GetChildren
定义为得到当前要素下所有子要素的集合。这是个集合,不是单个元素。
其方程式如下:
function GetChildren: IFeatureCollectionGE; safecall;
方程式原型提供了这样的信息:GetChildren返回值为IFeatureCollectionGE类型,而不是IFeature。前者是要素集合,后者为单个要素。在使用的时候要认清这一点,从下面的代码中可以清楚地看到。
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.btngetChClick(Sender: TObject);
var
FFeatures :IFeatureCollectionGE; //要素集合
ParFeature : IFeatureGE;
i: integer;
tmpstr : string;
begin
ParFeature := F_AppGE.GetFeatureByName('folerTest');
FFeatures := ParFeature.GetChildren;
for i := 1 to FFeatures.Count do
begin
tmpstr := tmpstr + #13#10 + FFeatures[i].Name;
end;
showmessage(tmpstr);
end;
首先用Google Earth程序打开本书第3章的KML代码Folder.kml,然后执行。
上述的Delphi代码中父要素取的是名为“folderTest”的Folder元素,该要素有7个子要素,程序中使用了for循环来遍历要素集合。例子中的逻辑是取各个子要素的名字,然后用对话框显示出来,如图5-29所示。
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private string[] getFeatureChildren(string ft_name)
{
FeatureGE parentFt = appGE.GetFeatureByName(ft_name);
string[] name_kids = null;
if (parentFt != null)
{
FeatureCollectionGE childrenFt = parentFt.GetChildren();
if (childrenFt != null)
{
name_kids = new string[childrenFt.Count];
for (int i = 0; i < childrenFt.Count - 1; i++)
{
name_kids[i] = childrenFt[i].Name;
}
}
}
return name_kids;
}
对照上面的这幅地图,代码执行后可显示如图5-30和图5-31所示的对话框。

图5-30 要素框 图5-31 结果集
图5-30中的要素框最上面的父要素是foderTest,7个子要素以树状形式展示开来。这里讲述了如何根据父要素获取子要素集合。有时候也需要有反向获取的需求,如知道某一个子要素,要想获知其他所有同级别的子要素的话,通常的做法是首先知道它们共同的父要素是谁,再根据父要素查找子要素集合,Google Earth提供了GetParent方法来反向获取。
② GetParent
定义为得到包含当前要素的父要素。其方程式如下:
function GetParent: IFeatureGE; safecall;
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.BtnGetParClick(Sender: TObject);
var
parentFeature : IFeatureGE; //父要素
childFeature : IFeatureGE; //子要素
tmpstr : string;
begin
childFeature := F_AppGE.GetFeatureByName('testplacemark2');
parentFeature := childFeature.GetParent;
tmpstr := parentFeature.Name;
showmessage(tmpstr);
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private FeatureGE getFeatureParent(string ft_name)
{
FeatureGE ft = appGE.GetFeatureByName(ft_name);
return ft.GetParent();
}
首先用Google Earth程序打开本书第3章的KML代码Folder.kml,然后执行。
代码中的子要素取的是名为“testplacemark2”的要素,其父要素是“folderTest”,在执行程序后,程序按要求找到了父要素节点名称,如图5-32所示。

图5-32 父要素
2)高亮选中要素
IFeartureGE接口提供的Highlight方法,仅仅是使得在地址要素框中选中的项目呈现高亮状态,而在地图窗口内要素的外观并没有发生改变。
Highlight将当前的要素设置为被选中的高亮状态。其方程式如下:
procedure Highlight; safecall;
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.BtnHighLightClick(Sender: TObject);
var
SelFeature : IFeatureGE;
tmpstr : string;
begin
SelFeature := F_AppGE.GetFeatureByName('testplacemark2');
SelFeature.Highlight;
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private void setFeatureHighlight(string ft_name)
{
FeatureGE ft = appGE.GetFeatureByName(ft_name);
ft.Highlight();
}
首先用Google Earth程序打开本书第3章的KML代码Folder.kml,然后执行。
代码执行后,在地址栏中名为“testplacemark2”的要素被高亮显示,如图5-33所示。

图5-33 高亮显示
该方法的使用,还可以参考和配合IFeartureGE的属性项Highlighted,返回该要素是否被高亮选中了。例如这样的需求:通过程序判断某个要素是否已经为选中状态,如果在被选中状态则被高亮显示。
2.IFeatureGE属性
1)高亮选中要素Highlighted
介绍如下。
l 定义:返回一个布尔值,表示当前的要素是否被高亮选中。如果被高亮选中,返回true,否则返回false。
l 使用方式:读(Get)。
l 值类型:Integer(Bool)。
l 方程式:property Highlighted: Integer
read Get_Highlighted;。
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.btnClick(Sender: TObject);
var
tmpFeature : IFeatureGE;
tmpstr : string;
boolflag : integer;
begin
tmpFeature := F_AppGE.GetFeatureByName('folerTest');
if (radfolerTest.Checked) then
begin
boolflag := tmpFeature.Highlighted;
if (boolflag <> 0 ) then
tmpstr := '高亮'
else
tmpstr := '没选中';
showmessage(tmpstr);
end;
end;
C#实例代码:
FeatureGE ft = appGE.GetFeatureByName(ft_name);
if (ft.Highlighted == 1)
{
MessageBox.Show("要素被选中高亮。");
}
首先用Google Earth程序打开本书第3章的KML代码Folder.kml,然后执行。
上述的代码逻辑是,如果“folderTest”被选中则弹出“高亮”提示框,如图5-34所示。

图5-34 “高亮”提示框
在遍历要素集合(Fearture Collection)的过程中,确定指定某个要素的最好方法是对比要素名称(Name)。
2)视场HasView
在使用Google Earth的时候,通常鼠标会发挥很巧妙的作用,例如,要仔细浏览某个要素的时候,只需要双击该要素的标识,地图画面就会自动缩放并移动,“飞行”到那个要素所在地。但是如果双击图5-30中的父要素folderTest,会不会也能促使地图画面的“飞行”?答案是否定的,因为父要素folderTest没有视场(View),IFeartureGE接口提供了一个HasView属性,来判断要素是否拥有视场。
HasView介绍如下。
l 定义:返回一个布尔值,表示这个要素是否有视场,即能否操作Google Earth“飞到”要素的所在地。
l 使用方式:读(Get)。
l 值类型:Integer(Bool)。
l 方程式:property HasView: Integer
read Get_HasView;。
例如线段、标记、面等KML要素都有视场(View),而包含这些要素的文件夹节点却没有视场,即Google Earth是不可能“飞到”文件夹节点那里的。返回true表示有视场,没有视场则返回false。
从KML的语法上分析原因,是因为<Folder>、<Document>等KML节点本身并不包含经纬度点位信息,而如< Polygon >、<PlaceMark>等子节点反而包含经纬度点位信息,因此可以控制Google Earth“飞到”要素所在地。
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.Button1Click(Sender: TObject);
var
tmpFeature1,tmpFeature2 : IFeatureGE; //要素变量
tmpstr : string;
boolflag : integer; //是否要素被选中了
begin
tmpFeature1 := F_AppGE.GetFeatureByName('folerTest');
tmpFeature2 := F_AppGE.GetFeatureByName('testplacemark1');
if (radfolerTest.Checked) then
begin
boolflag := tmpFeature1.HasView;
if (boolflag <> 0 ) then
tmpstr := '有视场'
else
tmpstr := '无视场';
showmessage(tmpstr);
end
else
begin
……
end;
end;
首先用Google Earth程序打开本书第3章的KML代码Folder.kml,然后执行。
folderText是父节点要素,是没有视场的,所以执行程序后,会弹出“无视场”提示框;而testplacemark1是有视场的,所以执行程序后,会弹出如图5-32所示的“有视场”提示框。

图5-35 “有视场”提示框
Highlighted可参考IFeartureGE的方法Highlight,该方法已经在前面介绍了。
3)四维空间和时间轴
Google Earth API另一个亮点就是引入了四维空间的概念——除了通常意义上的三维,剩下的一维是时间轴。
在前面KML的介绍中,说明了可以通过设置要素的有效性,将地理要素与时间进行绑定,从而在Google Earth中展现不同历史时间段的切面。对于KML的有效期设置,Google Earth API提供了TimeInterval属性来获取和判断。
① TimeInterval
TimeInterval介绍如下。
l 定义:表示要素的有效期,从KML的语法上分析,本书在第3章讲过关于KML时间类的标签,这种标签拥有开始和结束时间,此属性的返回值为ITimeIntervalGE接口类型。
l 使用方式:读(Get)。
l 值类型:ITimeIntervalGE。
l 方程式:property TimeInterval: ITimeIntervalGE
read Get_TimeInterval;。
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.BtnGetTimeIntervalClick(Sender: TObject);
var
FFeatures :IFeatureCollectionGE;
ParFeature : IFeatureGE;
i: integer;
tmpstr : string;
tmpYear,tmpMonth,tmpDay:integer;
begin
ParFeature := F_AppGE.GetFeatureByName('folerTest');
FFeatures := ParFeature.GetChildren;
for i := 1 to FFeatures.Count do
begin
if (FFeatures[i].Highlighted <> 0) then
begin
tmpYear := FFeatures[i].TimeInterval.BeginTime.Year;
tmpMonth := FFeatures[i].TimeInterval.BeginTime.Month;
tmpDay := FFeatures[i].TimeInterval.BeginTime.Day;
tmpstr := inttostr(tmpYear) + '-'+ inttostr(tmpMonth) + '-' +inttostr(tmpDay);
end;
end;
showmessage('开始时间是:'+tmpstr);
end;
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
private DateTime getFeatureTime(string ft_name)
{
try
{
FeatureGE ft = appGE.GetFeatureByName(ft_name);
int myYear = ft.TimeInterval.BeginTime.Year;
int myMonth = ft.TimeInterval.BeginTime.Month;
int myDay = ft.TimeInterval.BeginTime.Day;
DateTime tm = new DateTime(myYear, myMonth, myDay);
return tm;
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
}
首先用Google Earth打开第3章的例子“TimeSpan.kml”,然后执行。
运行上述的Delphi程序之后,选择名为“nanjing”的要素,单击Delphi程序按钮,会弹出提示框,返回要素“nanjing”的开始时间,如图5-36所示。

图5-36 时间段
② Name
Name介绍如下。
l 定义:返回一个字符串,表示当前的要素的名称。
l 使用方式:读(Get)。
l 值类型:字符串(string)。
l 方程式:property Name: WideString
read Get_Name;。
这个属性很容易令人联想到IApplicationGE中的另一个方法GetFeatureByName(),该方法也是通过要素的名称获得要素对象的。下面Delphi的例子,说明了如何使用Name属性来完成同样的效果:
……
F_FeartureCollectionGE := coFeatureCollectionGE.Create;
for i:=0 to F_FeartureCollectionGE.Count -1 do
begin
F_FeartureGE := F_FeartureCollectionGE.Item[i];
if (F_FeartureGE.Name = 'testFeature') then
begin
showmessage('找到了!'); //如果名称为“'testFeature'”,则说明找到了该要素
end;
end;
③ Visibility
Visibility介绍如下。
l 定义:定义了要素的可见性。
l 使用方式:读(Get)/写(Set)。
l 值类型:Integer。
l 方程式:property Visibility: Integer
read Get_Visibility
write Set_Visibility;。
Delphi实例代码:
var F_AppGE: IApplicationGE;
……
procedure TForm1.btnVisibiltyClick(Sender: TObject);
var
tmpFeature : IFeatureGE;
begin
tmpFeature := F_AppGE.GetFeatureByName('folerTest');
if (tmpFeature.Visibility <>0 ) then
begin
tmpFeature.Visibility := 0; //不显示
end
else
begin
tmpFeature.Visibility := 1; //显示
end;
end;
首先用Google Earth程序打开本书第3章的KML代码Folder.kml,然后执行。这段代码可以控制Google Earth上地标的显示。
C#实例代码:
ApplicationGEClass appGE = new ApplicationGEClass();
……
// 检查某个要素是否可见,0为检查不成功,1为可见,2为不可见
private int isFeatureVisible(string ft_name)
{
int isFtVi = 0;
FeatureGE ft = appGE.GetFeatureByName(ft_name);
if (ft != null)
if (ft.Visibility == 1)
{
isFtVi = 1;
}
else
{
isFtVi = 2;
}
return isFtVi;
}
|
提示 |
IFeatureGE接口提供了操作地图要素的方法,如高亮选中、获取名称操作,但Google Earth并没有进一步深入对要素的支持,对比Google Maps丰富的要素方法和属性,IFeatureGE接口仅仅提供了几个对于现有要素对象的操作,其他例如创建要素对象这样的方法却未能提供。这的确是Google Earth API的一大不足,开发人员只能通过KML或者Google Earth Plus本身提供的工具,甚至Google SetchUp来创建地理要素。 |
浙公网安备 33010602011771号