网友投稿 | 设为首页 | 加入收藏
1/2页12 跳转到查看:9700
回复该主题 发新话题
键盘左右键可以进行前后翻页操作
帮助

[求助]关于KML和API的问题

[求助]关于KML和API的问题

问题如下:

什么是KML?如何使用KML?

什么是API?如何使用API?

TOP

 

re:这里的GoogleEarth API...



这里的GoogleEarth API不同于GoogleMAP API:

大家可能对于GoogleMAP API有一些印象了

而且网上对于GoogleMAP API的应用也有很多比如http://www.flashearth.com/

那么什么是GoogleEarth API呢?GoogleEarth API能作什么呢?

下面我就结合我编的一些东西讲讲GoogleEarth API



GoogleEarth 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的使用。







源代码下载  http://bbs.godeyes.cn/upload/2007/03/06/134908.rar







首先用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.godeyes.cn/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.googlecode.com/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的说明,获得的地址更精确。



其他无意见,挺好的。

TOP

 

re:非常感谢您详尽的解答!我当下来慢慢研究。...

非常感谢您详尽的解答!我当下来慢慢研究。呵呵。

TOP

 

re:太感谢了

太感谢了

TOP

 

re:够详细

够详细

TOP

 

re:很强啊

很强啊

TOP

 

re:谢谢很好很好

谢谢



很好很好

TOP

 

re:怎么好的贴,怎么没人顶!

怎么好的贴,怎么没人顶!

TOP

 

re:很好很好

很好很好

TOP

 

re:看看!

该用户帖子内容已被屏蔽

TOP

 

re:h

h

TOP

 

re:一个字:强

一个字:强

TOP

 

作个记号

TOP

 

太感谢了,这两天憋死我了。

TOP

 

有delphi的例子么?在delphi中做始终无法通过编译。

TOP

 
1/2页12 跳转到
回复该主题 发表新主题
  <<上一主题 | 下一主题>>