一、准备
在开发之前,必须先安装Google Earth客户端,版本不限。在安装客户端后,需要进行注册,只有注册后才能调用相关的API。
GE的注册方法为:使用管理员运行CMD,切换到安装盘符,执行命令googleearth.exe /regserver,没有出现错误即为注册成功。
GoogleEarth COM API参考文档可以在这里找到:http://earth.google.com/comapi/index.html
二、嵌入GE
新建一个WinForm工程,添加Google Earth 1.0 Type Library的COM引用后就可以使用GE的API,目前API为1.0版本,提供了很少的接口方法。
下面示例代码为将GE嵌入到WinForm窗体:
static readonly Int32 WM_QUIT = 0x0012;
private IntPtr _gehMainWnd = (IntPtr)0;
private IntPtr _gehRenderWnd = (IntPtr)0;
private ApplicationGE GEApp;
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//启动GoogleEarth实例
GEApp = new ApplicationGE();
_gehMainWnd = (IntPtr)GEApp.GetMainHwnd();
//隐藏GoogleEarth主窗口
NativeMethods.SetWindowPos(_gehMainWnd, NativeMethods.HWND_BOTTOM, 0, 0, 0, 0, NativeMethods.SWP_NOSIZE | NativeMethods.SWP_HIDEWINDOW);
_gehRenderWnd = (IntPtr)GEApp.GetRenderHwnd();
//将渲染窗口嵌入到主窗体
NativeMethods.MoveWindow(_gehRenderWnd, 0, 50, this.Width, this.Height - 50, true);
NativeMethods.SetParent(_gehRenderWnd, this.Handle);
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
//关闭窗口
NativeMethods.PostMessage((int)_gehMainWnd, WM_QUIT, 0, 0);
}
三、绘制路径
COM API提供了方法OpenKmlFile(string fileName, int suppressMessages)和LoadKmlData(ref string kmlData)方法来加载轨迹数据,这两个方法都可以加载数据,但不同的是OpenKmlFile方法会清空原有路径,而LoadKmlData则不会。
KML数据是有GE规定的一种数据格式,其中可以包含点、线等多种数据。KML的生成方式将在第四点介绍。
下面示例代码用来绘制轨迹:
if (GEApp != null)
{
var kmlpath = AppDomain.CurrentDomain.BaseDirectory + "test.kml";
GEApp.OpenKmlFile(kmlpath, 1);
}
四、KML文件生成
生成KML文件需要添加相关的元素类,首先是根元素
using System.IO;
using System.Xml.Serialization;
namespace GeDemo.Kml
{
[XmlRoot("kml", Namespace = "http://www.opengis.net/kml/2.2")]
public class KmlRoot
{
[XmlElement("Document")]
public KmlDocument Document { get; set; }
public KmlRoot()
{
}
public KmlRoot(KmlDocument doc)
{
this.Document = doc;
}
public void GenerateKmlFile(string kmlFileName)
{
using (var fs = new FileStream(kmlFileName, FileMode.Create, FileAccess.ReadWrite))
{
using (var sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
{
XmlSerializer serializer = new XmlSerializer(GetType());
serializer.Serialize(sw, this);
}
}
}
}
}
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
namespace GeDemo.Kml
{
public class KmlDocument
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("Style")]
public List<KmlStyle> Styles { get; set; }
[XmlElement("StyleMap")]
public KmlStyleMap StyleMap { get; set; }
[XmlElement("Placemark")]
public List<KmlPlacemark> PlaceMarkers { get; set; }
public KmlDocument()
{
}
public KmlDocument(string name, List<KmlPlacemark> folderList, string mapId)
{
Name = name;
PlaceMarkers = folderList;
Styles = KmlStyle.GetStyleList();
StyleMap = new KmlStyleMap(mapId);
}
}
}
using System.Collections.Generic;
using System.Xml.Serialization;
namespace GeDemo.Kml
{
public class KmlStyle
{
private static readonly string[,] styleTable =
{
{"green", "FF006400", "4"},
{"red", "FF006400", "4"}
};
[XmlAttribute("id")]
public string ID { get; set; }
[XmlElement("LineStyle")]
public KmlLineStyle lineStyle { get; set; }
public KmlStyle()
{
}
public KmlStyle(string id, string color, string width)
{
ID = id;
lineStyle = new KmlLineStyle(color, width);
}
public static List<KmlStyle> GetStyleList()
{
List<KmlStyle> rtn = new List<KmlStyle>();
for (int i = 0; i < styleTable.GetLength(0); i++)
{
KmlStyle style = new KmlStyle(styleTable[i, 0], styleTable[i, 1], styleTable[i, 2]);
rtn.Add(style);
}
return rtn;
}
public class KmlLineStyle
{
[XmlElement("color")]
public string Color { get; set; }
[XmlElement("width")]
public string Width { get; set; }
public KmlLineStyle()
{
}
public KmlLineStyle(string color, string width)
{
Color = color;
Width = width;
}
}
}
}
using System.Collections.Generic;
using System.Xml.Serialization;
namespace GeDemo.Kml
{
public class KmlStyleMap
{
private static readonly string[,] styleTable =
{
{"normal", "#green"},
{"highlight", "#red"}
};
[XmlAttribute("id")]
public string ID { get; set; }
[XmlElement("Pair")]
public List<Pair> pairs { get; set; }
public KmlStyleMap()
{
}
public KmlStyleMap(string id)
{
ID = id;
pairs = GetPairList();
}
public static List<Pair> GetPairList()
{
List<Pair> rtn = new List<Pair>();
for (int i = 0; i < styleTable.GetLength(0); i++)
{
Pair pair = new Pair(styleTable[i, 0], styleTable[i, 1]);
rtn.Add(pair);
}
return rtn;
}
public class Pair
{
[XmlElement("key")]
public string Key { get; set; }
[XmlElement("styleUrl")]
public string StyleUrl { get; set; }
public Pair()
{
}
public Pair(string key, string url)
{
Key = key;
StyleUrl = url;
}
}
}
}
using System.Xml;
using System.Xml.Serialization;
namespace GeDemo.Kml
{
public class KmlPlacemark
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("styleUrl")]
public string StyleUrl { get; set; }
[XmlElement("LineString")]
public KmlLineString LineString { get; set; }
public KmlPlacemark()
{
}
public KmlPlacemark(string name, string des, string style, KmlLineString lineString)
{
this.Name = name;
this.Description = des;
this.StyleUrl = style;
this.LineString = lineString;
}
}
}
using System.Xml.Serialization;
namespace GeDemo.Kml
{
public class KmlLineString
{
[XmlElement("altitudeMode")]
public string AltitudeMode { get; set; }
[XmlElement("coordinates")]
public string Coordinates { get; set; }
public KmlLineString()
{
}
public KmlLineString(KmlLine line)
{
AltitudeMode = "clampToGround";
Coordinates = line.ToString();
}
public KmlLineString(string tessel, KmlLine line)
{
AltitudeMode = "clampToGround";
Coordinates = line.ToString();
}
}
}
using System.Collections.Generic;
using System.Linq;
namespace GeDemo.Kml
{
public class KmlLine
{
private List<KmlPoint> _pointList;
public KmlLine()
{
_pointList = new List<KmlPoint>();
}
public void Add(KmlPoint point)
{
_pointList.Add(point);
}
public override string ToString()
{
return _pointList.Aggregate(string.Empty, (current, point) => current + (point + " "));
}
}
}
namespace GeDemo.Kml
{
public class KmlPoint
{
private double B;
private double L;
private double H;
public KmlPoint()
{
}
public KmlPoint(double b, double l, double h)
{
B = b;
L = l;
H = h;
}
public override string ToString()
{
return L.ToString("F6") + "," + B.ToString("F6") + "," + H.ToString("F2");
}
}
}
最终生成的KML文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Style id="line_color1">
<LineStyle>
<color>FFFFFF00</color>
<width>1.0</width>
</LineStyle>
</Style>
<Style id="line_color2">
<LineStyle>
<color>FFFFFF00</color>
<width>3.0</width>
</LineStyle>
</Style>
<name>ship_路径</name>
<Placemark>
<name>Line1</name>
<description>0</description>
<styleUrl>#line_num1</styleUrl>
<LineString>
<altitudeMode>clampToGround</altitudeMode>
<coordinates>
122.246005555556,34.8119416666667,0 122.246875,34.8112555555556,0
</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>Line2</name>
<description>1</description>
<styleUrl>#line_num1</styleUrl>
<LineString>
<altitudeMode>clampToGround</altitudeMode>
<coordinates>
122.246005555556,34.8119416666667,0 122.246875,34.8112555555556,0
</coordinates>
</LineString>
</Placemark>
</Document>
</kml>