Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31924
  • 博文数量: 16
  • 博客积分: 416
  • 博客等级: 下士
  • 技术积分: 120
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 21:30
文章分类
文章存档

2011年(16)

我的朋友

分类: 系统运维

2011-06-14 22:11:40

   这里的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的应用也有很多比如 那么什么是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的网址:

  那么,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 就不做过多说明了:

   D=100&ID=21506

  从GE API的官网上看,现在这些API已经更新了,原来大家使用的 KHInterface 这个主类,现在已经基本被 ApplicationGE 这个主类给取代了。GE API的官网:

  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 终于搞清楚这是什么了,其实就是

   ,如果没有这个属性,HasView

  =0,有就是1。没有时GE是不会自动导航到你指定的地标,即使你已经找到了它,在这种情况下,至今没找到好方法通过API导航到已找到的地标。这是本人觉得Google最可恶的地方,其实在GE中,不管你有没有

   ,无论你是 目录 还是

  地标,它都会以最合理的方式包含其中的所有地标。大家大概没多少人习惯加上这个

  ,所以在调用时就会出现有时成功,有时不成功,让人恼火不已。

  ReadOnly Property Highlighted() As Integer 和 Highlight 加亮

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

  ReadOnly Property TimeInterval() As EARTHLib.TimeIntervalGE

  没仔细研究,大概跟定时有关系

  Property Visibility() As Integer 比较有用的值,对应于KML中的

  ,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

  就是 ,这个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字符串,必须包含从
  开始的所有东东,而不能只是一个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#开发的源码,发贴共享,供高手开发参考

  网址 leEarthCOMWrapper/

  发一段,其它自己下载吧

  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("\nGetPointOnTerrainFromScreenCo ords(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的说明,获得的地址更精确。

  其他无意见,挺好的。

阅读(1795) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~