分享

【转】windows 程序以COM接口开发的Google Earth API(有C#和VC...

 caodaoquan 2013-04-23

【转】windows 程序以COM接口开发的Google Earth API(有C#和VC源代码)

http://www./article/58.htm

这里的Google Earth API(本文的Google Earth API和最新Google Earth API概念不同,前者是windows 程序以COM接口开发,目前的Google Earth API是通过Google Earth 插件在浏览器理开发的API函数,本文主要是讲windows 程序以COM接口开发)不同于GoogleMAP API:大家可能对于GoogleMAP API有一些印象了而且网上对于GoogleMAP API的应用也有很多比如http://www./那么什么是GoogleEarth API呢?GoogleEarth API能作什么呢?下面我就结合我编的一些东西讲讲GoogleEarth API
Google Earth API Keyhole 1.0 Type Library当你要使用GoogleEarth API时首先要在工程里引用他,以VB为例,在“工程”菜单中选择“引用”,如果你已经安装了GoogleEarth,那么引用栏里会有“Keyhole 1.0 Type Library ”而它是定位于GoogleEarth的主程序的。引用完毕后,打开对象浏览器,你就可以看到GoogleEarth API的类和函数及属性了!!
GoogleEarth API有4个类,每个类下面有多个函数及属性 下面将我常用的函数的说明写到下面:
Class KHFeature
Property hasView As Long          只读   
暂时还不知道什么意思,没用过,哪位高手能给个解释
Property visibility As Long                      地标的可视选项

Class KHInterface   
Property autopilotSpeed As Double               
GE的自动飞行速度
Function currentView(terrain As Long) As KHViewInfo   
GE的当前视图
Property currentViewExtents As KHViewExtents          只读
Function getFeatureByName(name As String) As KHFeature
Function getPointOnTerrainFromScreenCoords(screen_x As Double,
screen_y As Double) As Double()               
Sub LoadKml(kmlData As String)          导入KML字符串,不支持中文
Sub OpenFile(fileName As String)    打开地标文件
Sub QuitApplication()                退出程序
Sub SaveScreenShot(fileName As String, quality As Long)         
保存截图
Sub setFeatureView(feature As KHFeature, speed As Double)
Sub SetRenderWindowSize(width As Long, height As Long)
Sub setView(view As KHViewInfo, terrain As Long, speed As Double)   
用KHViewInfo设置视角范围
Sub setViewParams(lat As Double, lon As Double, range As Double, _
               tilt As Double, azimuth As Double, terrain As Long,
speed As Double)用数值设置视角范围
Property streamingProgressPercentage As Long          只读         
数据传输进度百分比

Class KHViewExtents
property east As Double    只读
Property north As Double    只读
Property south As Double    只读
Property west As Double    只读

Class KHViewInfo   
Property azimuth As Double    方位角
Property latitude As Double    纬度
Property longitude As Double    经度
Property range As Double    范围
Property tilt As Double    倾角


利用这些函数,可以对GE进行部分 控制,实现一些小的功能,比如在我的地标管理器中就利用了GoogleEarth API实现了地标的隐藏与显示。
Google公司已经将Google COM API开放,这样我们就可以通过开放的API来对GoogleEarth进行操作了,比如控制当前视图的高度、中心经纬度,保存当前图片等等。下面是Google COM API的网址:
http://earth.google.com/comapi/那么,VC程序员如何使用这些API来控制GoogleEarth呢?下面我们编写一个简单的程序来说明对Google COM API的使用。
源代码下载   点击下载此文件  
首先用VC建立一个基于Dialog的工程(这个不用教了吧?),工程名为ControlGe,工程建好后,下面就是把Google提供的类添加到工程里边来。

Ctrl+W,打开类向导页面,点击“Add Class”按键,选择“From a type
library”,然后到安装GoogleEarth的目录下,找到googleearth.exe文件,点击“打开”按键。

这时会弹出一个框来确认产生Google的类,直接点击“OK”键,这是会生成两个文件加入的工程中:googleearth.h和googleearth.cpp,里面就是我们想要的类了。


GoogleEarth的类已经生成了,那我们如何来用它们呢?各位看客不用着急,我们一步步来。

首先,我们得调用一下::CoInitialize(NULL);初始化一下COM库了,这个函数可以在ControlGe.cpp文件中的InitInstance()函数里面调用。

然后呢,我们再在ControlGeDlg.h中定义一个类成员变量:
IApplicationGE m_geApplication;
顺便说一下,IApplicationGE可是Google COM
API最主要的一个接口了,从它提供的操作数量就可以看得出来。

好了,离成功不远了,控制的变量也定义了,下面就开始用它来控制GE吧。


那么我们如何将刚定义的变量取得对GE的控制权呢?费话少说,首先在ControlGeDlg.cpp文件中定义一个变量:
static const CLSID CLSID_ApplicationGE = {0x8097D7E9,0xDB9E,0x4AEF,
{0x9B,0x28,0x61,0xD8,0x2A,0x1D,0xF7,0x84}};

然后在OnInitDialog()中加入以下代码:
m_geApplication.CreateDispatch(CLSID_ApplicationGE);
呵呵,现在GE就归你操控了!

我们试着做个简单的操作吧,添加一个按键,然后添加按键的点击处理函数,在函数中加入以下代码:
CString strFileName;
static char BASED_CODE szFilter[] = "jpg Files (*.jpg)|All Files
(*.*)|*.*||";
CFileDialog dlgFile(FALSE, "jpg", NULL, OFN_HIDEREADONLY |
OFN_OVERWRITEPROMPT, szFilter, this);

if (dlgFile.DoModal() == IDOK)
{
CWaitCursor wait;
strFileName = dlgFile.GetPathName();
m_geApplication.SaveScreenShot(strFileName, 100);
}

试试看,这是将当前GE的地图给保存成一个jpg格式的图片,只可惜只能保存成黑白图片,google还是给自己留了一手的。


可能上面的代码运行会有些问题,也许是你的GE版本太低了,也许是你的Google
COM未注册,注册一下就可以了,Google对注册的说明:
If, for some reason, the Google Earth COM API needs to be registered
again, you can execute GoogleEarth.exe with "/RegServer" as a command
line argument.
For instance, assuming GoogleEarth.exe is located in C:\Program
Files\Google\Google Earth, the following command line would register Google
Earth's COM API:

"C:\Program Files\Google\Google Earth\googleearth.exe" /RegServer

To unregister Google Earth's COM API, execute the following command:

"C:\Program Files\Google\Google Earth\googleearth.exe" /UnregServer

好了,我们下面就可以对照Google COM
API的文档来试一试对GE的控制操作了。下面我再来演示一下如何把视图切换到指定地方,添加如下代码:
ICameraInfoGE geCamera;

geCamera.AttachDispatch(m_geApplication.GetCamera(TRUE));
geCamera.SetRange(800);
geCamera.SetFocusPointLongitude(113.972522);
geCamera.SetFocusPointLatitude(22.561294);

m_geApplication.SetCamera(geCamera, 1.5);

执行以上代码后,GE就会将视图切换到。。。嘿嘿,到俺家了。。。

OK,我要下班回家了,就写到这儿吧,其它功能大家对照着google的文档再试试,要是谁知道上传附件的方法,麻烦告诉我一下,我把上面示例的代码上传上来。


去年,水手版主给大家介绍过GE的API,详贴见这里,本贴对 KHInterface 就不做过多说明了:
http://bbs./Announce/Announce.asp?BoardID=100&ID=21506
从GE API的官网上看,现在这些API已经更新了,原来大家使用的 KHInterface 这个主类,现在已经基本被 ApplicationGE 这个主类给取代了。GE API的官网:
http://earth.google.com/comapi/index.html以VB.Net为例(下同),使用GE的API还是很简单的,在你打开的项目中,选择 项目--添加引用,然后找到 GoogleEarth.exe 选择添加,就会在你的 Debug 目录下生成一个 Interop.EARTHLib.dll 。你还可以通过 视图--对象浏览器 来查看它的组成情况。
主要有以下五个类:
ApplicationGE 主类,基本操作都在这里,比 KHInterface 更非丰富,但少了两个重要的函数,CurrentView(当前的视角),SetView(设置视角,比如打开GE时可以定位到指定的视角)
FeatureGE KML的标签类

FeatureCollectionGE 标签集类,是 FeatureGE 集合。

ViewExtentsGE (只读)边界集类,可以获得当前屏幕内四个边的经纬度值。

CaremaInfoGE 拷屏类,但目前没啥大用,黑白照片。

此外还有几个比较重要的类:

AnimationControllerGE 针对TimeStamp时间轴的,可以播放、暂停等。

PointOnTerrainGE
根据屏幕的点获得的经纬高度值就放在这个类里,可以看作一个数组。

SearchControllerGE 查询GE内置地址库的查询类(不是查KML文件的)


其他的还有,大家可以一起研究一下。介绍失误的地方,请大家及时指正。


程序调用:

1、Imports EARTHLib

需要在 Public Class Form 之前声明引入。

2、Public khapp As EARTHLib.ApplicationGE

在 Form 内定义,本人一般定义为全局,方便使用。

3、khapp = New ApplicationGE

在按钮事件内首先要赋值为
New,每次都需要,否则容易出问题。如果找不到,返回值是 IsNothing()=True,其他的类也相同,为防止程序出错,找不到时可用

IsNothin进行判断处理。

4、为防止出现错误,可以用 Try 进行错误截取,使用 ex.tostring
获得错误信息,然后在 Catch 后面 return 。



下面开始介绍 FeatureGE 类的函数、方法或者值:

Function GetChildren() As EARTHLib.FeatureCollectionGE
标签的包含的子标签,返回值定义到 FeatureCollectionGE 中(多个)

Function GetParent() As EARTHLib.FeatureGE 标签的父标签(单个)

ReadOnly Property HasView() As Integer 终于搞清楚这是什么了,其实就是
<LookAt> ,如果没有这个属性,HasView
=0,有就是1。没有时GE是不会自动导航到你指定的地标,即使你已经找到了它,在这种情况下,至今没找到好方法通过API导航到已找到的地标。这是本人觉得Google最可恶的地方,其实在GE中,不管你有没有
<LookAt> ,无论你是 目录 还是
地标,它都会以最合理的方式包含其中的所有地标。大家大概没多少人习惯加上这个
<LookAt>,所以在调用时就会出现有时成功,有时不成功,让人恼火不已。

ReadOnly Property Highlighted() As Integer 和 Highlight 加亮

ReadOnly Property Name() As String 标签的Name值

ReadOnly Property TimeInterval() As EARTHLib.TimeIntervalGE
没仔细研究,大概跟定时有关系

Property Visibility() As Integer 比较有用的值,对应于KML中的
<Visibility>,0不显示,1显示。



ApplicationGE 主类:

Property AutoPilotSpeed() As Double
从一个地标转到另一个地标时的速度,从0--5,默认只有 0.119

Property ElevationExaggeration() As Double
和GetPointOnTerrainFromScreenCoords有关

Function GetFeatureByHref(ByVal href As String) As EARTHLib.FeatureGE
就是 <Placemark id="test">,这个id的值test就是Href,String=
包含路径的文件名#test(跟网页里查tag的方法相同),具有唯一性,但估计没多少人喜欢写这个id,所以还是好看不好用。也没测试出来没有的情况下GE是如何保证"唯一"的。

Function GetFeatureByName(ByVal Name As String) As EARTHLib.FeatureGE
目前只能用这个,但这个又不具有唯一性,如果两个名称相同,永远只能找到第一个。这是GE的第二个可恶之处,这么方便的功能,如果放到
FeatureCollectionGE 里,那该多好啊,就可以继续查询"下一个"了。

Function GetHighlightedFeature() As EARTHLib.FeatureGE 没发现什么用途

Function GetLayersDatabases() As EARTHLib.FeatureCollectionGE
获得GE左下角的数据库,这次总算放到标签集里去了

Function GetMainHwnd() As Integer 和 Function GetRenderHwnd() As
Integer ,前一个是主程序的句柄号,后一个是 GE视窗
的句柄号。Google挺好玩的,连这个都老老实实地告诉大家了,连Spy++都省了,呵呵。

Function GetTemporaryPlaces() As EARTHLib.FeatureGE
GE临时目录,可以通过 GetChildren() 继续查找打开文件的名字等。

Function GetMyPlaces() As EARTHLib.FeatureGE GE里我的目录,用途同上。

Function GetPointOnTerrainFromScreenCoords(ByVal screen_x As Double,
ByVal screen_y As Double) As EARTHLib.PointOnTerrainGE
给出屏幕的点X,Y坐标,转成经纬高三个坐标值,ElevationExaggeration为0时高度为0,为1时高度为实际值。

更正计算公式,终于可以得到准确的X、Y点坐标了,跟地图下面标的一模一样了:

X、Y代表装GE的控件的本地坐标(相对坐标),不是屏幕的绝对坐标,可以通过
PointToClint
函数获得装GE控件的X、Y坐标,然后转换成GE要求的平面坐标系的坐标值,和屏幕坐标值相比,Y轴的算法是相反的,也就是说,GE的坐标系,是以GE地球界面的中间点为原点(0,0),X轴从-1到+1,Y轴从-1到+1,公式转换如下:

( X - Width/2 ) / Width * 2

( Hight/2 - Y ) / Hight * 2

注:X、Y均是从0开始计算,然后到Width或者Hight -1 为最大值。

(原来是从以前地方借来的,发现是错误的:-1到1计算公式大概是:
(X-Width/2)/Width (Y-Hight/2)/Hight)

Sub HideDescriptionBalloons() 和 Sub ShowDescriptionBalloon(ByVal
feature As EARTHLib.FeatureGE) 打开/隐藏地标描述,一般和下面的
SetFeatureView 配合使用。

Function IsInitialized() As Integer 是否初始化

Function IsOnline() As Integer 是否连上GE

Sub Logout() 和 Sub Login()
登陆或者退出,不会提示关闭前存盘临时文件(好象其他地方有参数可以设置,忘了)。GE的第三个可恶之处:临时文件没办法清除,只能设置Visibility=0,但如果有名称重叠的话,那你就只能找到第一个地标。如果你要彻底清除,就只能先采用个土方法,先退出再登陆。

Sub LoadKmlData(ByRef kmlData As String)
比较有用的功能,导入完整的KML字符串,必须包含从 <?xml
开始的所有东东,而不能只是一个Placemark什么的。

Sub OpenKmlFile(ByVal fileName As String, ByVal suppressMessages As
Integer) 最有用的功能了,导入KML/KMZ文件。后面的参数含义是:1 指不提示,0
提示。就是说如果这个文件已经导入的话,0的时候就会弹出个对话框,问你是否重新导入。

Sub SaveScreenShot(ByVal fileName As String, ByVal quality As Integer) 给个文件名,存黑白照片

ReadOnly Property SearchController() As EARTHLib.SearchControllerGE 查GE内置数据库用的

Sub SetFeatureView(ByVal feature As EARTHLib.FeatureGE, ByVal speed As Double) 将前面用 GetFeatureByName/Href
找到的地址进行导航,转到这个地标。前面已经介绍了,需要两个判断,一个是 Isnothing,True就不要转;一个是HasView,0就不要转,否则会出错。

ReadOnly Property StreamingProgressPercentage() As Integer   程序运转的百分比,一般得到的时候都是100%了。

ReadOnly Property TourController() As EARTHLib.TourControllerGE 大概跟 Tour 有关的控制

ReadOnly Property VersionAppType() As EARTHLib.AppTypeGE   GE版本:EnterpriseClientGE = 0, ProGE = 1, PlusGE = 2, FreeGE = 5, UnknownGE = 0xFF
,咱们都是5

ReadOnly Property VersionBuild() As Integer 版本号4.0.2693中的2693,和下面两个一起可以拼成一个完整的版本号。
ReadOnly Property VersionMajor() As Integer 和 ReadOnly Property VersionMinor() As Integer 比如4.0.2693前一个指版本号的 4,后一个指 0

ReadOnly Property ViewExtents() As EARTHLib.ViewExtentsGE 比较有用的一个功能,获得四个边的经纬度值。a coarse approximation of what is visible in the 3D view of a Google Earth application(原话),比较粗糙,比当前的边框要大一点点,不知为何。主要就这些了。当然,进入每个功能后,还有许多详细的功能,有待于大家继续发掘了。
纠正一下: CameraInfoGE 这个类很有用,第一贴重大失误啊。
继续介绍 CameraInfoGE 如下(均可以 获得值 和 设定值 ):
1、FocusPointLongitude、FocusPointLatitude、FocusPointAltitude, 记录经度、纬度、高度数据

2、FocusPointAltitudeMode,目前只有 1 (默认)和 2 两种取值,分别对应 KML 格式介绍中的 relativeToGround 和 absolute ,KML 格式中的默认 clampToGround 似乎没有值对应,曾试过0 或者3,均出现错误。
3、Range 高度 (0---8万公里)
4、Tilt 倾斜度,以垂直为 0,最大为90度,即地面的切线为最大值。
5、Azimuth 方位角 (-180---180)
#如何获得当前视角:
ApplicationGE.GetCamera(B) B取值True/False或者 1/0也可以,True 更精确。

#如何定义视角:
根据自己的需要,分别定义 1、2、3、4、5,一般其他不变,只变高度就可以实现高度的自由转换。#如何定位到确定的视角(或者恢复到 已储存的视角)
ApplicationGE.SetCamera(CameraInfoGE,速度) 将前面获得的当前视角或者经过定义的视角赋值给 CameraInfoGE ,即可驱动GE转移到该视角。速度取值
0--5,GE默认0.119。*高级应用:

1、结合 GetCamera 、和 SetCamera
,定义好几个转换地点,并合理调整其中的角度、高度、速度等相应值,再加上时间延迟功能,完全可以做出符合自己要求的
Tour 效果,这时候再结合屏幕拷贝软件,就可以制作出相当棒的演示效果。

用C#控制GE的源程序

GE API C#开发的源码,发贴共享,供高手开发参考
网址http://tropicalwatch./svn/trunk/GoogleEarthCOMWrapper/
发一段,其它自己下载吧
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

using GoogleEarthCOMWrapper;
using EARTHLib;

namespace TestGoogleEarthCOMWrapper
{
class Program
{
   static void Main(string[] args)
   {
      try
      {
            // Create the API Wrapper...this also inits it.
            GoogleEarthAPI geAPI = new GoogleEarthAPI();

            // Run some examples

            // Get Version info about your GoogleEarth Client
            int major = geAPI.VersionMajor;
            int minor = geAPI.VersionMinor;
            int build = geAPI.VersionBuild;
            string appType = geAPI.VersionAppType.ToString();
            Console.WriteLine("Version = " + major + "." + minor +
"." + build + " " + appType);

            // Open a local Kml File
            string fileName = AppDomain.CurrentDomain.BaseDirectory
+ "\\test.kmz";
            Console.WriteLine("\nCalling OpenKmlFile(" + fileName +
", true)...");
            geAPI.OpenKmlFile(fileName, true);
           
            // Get the Camera info
            CameraInfoGEClass cam = geAPI.GetCamera(false);
            Console.WriteLine("\nCamera Info:");
            Console.WriteLine("\tAzimuth " + cam.Azimuth);
            Console.WriteLine("\tFocusPointAltitude " +
cam.FocusPointAltitude);
            Console.WriteLine("\tFocusPointAltitudeMode " +
cam.FocusPointAltitudeMode);
            Console.WriteLine("\tFocusPointLatitude " +
cam.FocusPointLatitude);
            Console.WriteLine("\tFocusPointLongitude " +
cam.FocusPointLongitude);

            // Get the ViewExtents
            ViewExtentsGEClass ve = geAPI.ViewExtents;
            Console.WriteLine("\nView Extents");
            Console.WriteLine("\tNorth " + ve.North);
            Console.WriteLine("\tSouth " + ve.South);
            Console.WriteLine("\tEast " + ve.East);
            Console.WriteLine("\tWest " + ve.West);

            // Get the lat/lon/alt at screen coord (100, 100)
            GeoPoint gp =
geAPI.GetPointOnTerrainFromScreenCoords(100, 100);
           
Console.WriteLine("\nGetPointOnTerrainFromScreenCoords(100, 100) = ");
            Console.WriteLine("\t(" + gp.Lat + ", " + gp.Lon + ", "
+ gp.AltMeters + ")");

            // Get the My Places Feature
            FeatureGEClass fc = geAPI.GetMyPlaces();
            if (fc != null)
            {
               foreach (FeatureGE fcge in fc.GetChildren())
               {
                  fcge.Highlight();
                  Console.WriteLine("Feature " + fcge.Name + "
highlighted");
                  if (fcge.Name.Equals("Sage"))
                  {
                        fcge.Visibility = 1;
                  }
               }
            }

            // Load some kml via a string
            //FeatureGE sage = geAPI.GetFeatureByName("Sage");
            //sage.Highlight();
            //sage.Visibility = 1;
            string doc = ReadKml("test1.kml");
            geAPI.LoadKmlData(doc);
      }
      catch (Exception e)
      {
            // If you close the GE Client before one of the API
methods executes, you would get
            // an ApplicationUninitializedException for example.
There are other exceptions as well.
            Console.WriteLine(e.Message + "\n" + e.StackTrace);
      }
      Console.WriteLine("Press any key to exit...");
      Console.ReadLine();
   }

   static string ReadKml(string fileName)
   {
      StreamReader sr = new StreamReader(fileName);
      string doc = sr.ReadToEnd();
      return doc;
   }
}
}

GetPointOnTerrainFromScreenCoords(100, 100);

这个命令错了,我在介绍GE
API的贴子里专门有介绍,它的取值范围是从-1到1,屏幕坐标-->GE坐标
的转换公式我也提供了,目前可获得的坐标与GE的一模一样,证明公式是正确的。

LoadKmlData能不用尽量不要用,每次生成一个文件,无法清除,宁愿用重载同一个临时文件的方法。

GetCamera 最好用 True 参数(或者1也行),按照GE
API的说明,获得的地址更精确。

其他无意见,挺好的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多