您的位置:首页 > 编程语言 > C#

C# 程序自动批量生成 google maps 的KML文件

2011-12-05 12:59 741 查看
googlemaps的KML文件可以用于静态的地图标注,在某些应用中,我们手上往往有成百上千个地址,我们需要把这些地址和描述批量标注到googlemaps上去,如果手工来做,太耗时间,在这里我写了一个程序批量来生成这个KML文件。

首先看一下KML文件的格式:

<?xmlversion="1.0"encoding="UTF-8"?>
<kmlxmlns="http://www.google.com/earth/kml/2">
<Document>
<name>kml_sample2.kml</name>

<Styleid="red">
<IconStyle>
<Icon>
<href>http://www.google.com/intl/en_us/mapfiles/ms/icons/red-dot.png</href>
</Icon>
</IconStyle>
</Style>

<Styleid="green">
<IconStyle>
<Icon>
<href>http://www.google.com/intl/en_us/mapfiles/ms/icons/green-dot.png</href>
</Icon>
</IconStyle>
</Style>

<Styleid="blue">
<IconStyle>
<Icon>
<href>http://www.google.com/intl/en_us/mapfiles/ms/icons/blue-dot.png</href>
</Icon>
</IconStyle>
</Style>

<Placemark>
<name>GoogleInc.</name>
<description><![CDATA[
GoogleInc.<br/>
1600AmphitheatreParkway<br/>
MountainView,CA94043<br/>
Phone:+1650-253-0000<br/>
Fax:+1650-253-0001<br/>
<p>Homepage:<ahref="http://www.google.com">www.google.com</a></p>
]]>
</description>
<styleUrl>#red</styleUrl>
<Point>
<coordinates>-122.0841430,37.4219720,0</coordinates>
</Point>
</Placemark>

<Placemark>
<name>Yahoo!Inc.</name>
<description><![CDATA[
Yahoo!Inc.<br/>
701FirstAvenue<br/>
Sunnyvale,CA94089<br/>
Tel:(408)349-3300<br/>
Fax:(408)349-3301<br/>
<p>Homepage:<ahref="http://yahoo.com">http://yahoo.com</a></p>
]]>
</description>
<styleUrl>#green</styleUrl>
<Point>
<coordinates>-122.0250403,37.4163228</coordinates>
</Point>
</Placemark>

</Document>
</kml>


.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}

这个是一个典型的用于googlemaps的KML文件,(注意不同应用的KML格式会有所不同,比如googleearth的kml格式就复杂得多)

从这个kml文件格式来看,其实它就是一个xml文件,我们只要自动生成这个文件中各个元素的信息就可以得到这个xml文件。这里其实最大的问题是如何自动通过地址获取经纬度坐标。值得庆幸的是google提供了这方面的api函数。googleapi获取地理坐标的官方例子见:geocodingapi

我的实现稍微复杂一些,因为我需要在函数中为不同的位置自动分配颜色

///<summary>
///Generateplacemarkbyaddressdescription
///</summary>
///<paramname="addrDescription">addressanddescription</param>
///<returns>ifnomatched,returnfalse</returns>
publicboolGenerate(AddressDescriptionaddrDescription)
{
_LastErrorOrWarning=null;
Thread.Sleep(DelayInMs);
List<GeographicCoordinate>coordinates=Geocoding.Geocode(addrDescription.Address);
if(coordinates.Count==0)
{
_LastErrorOrWarning=string.Format("Address:{0},Description:{1}doesnotfindthecoordinates,pleasemakesuretheaddressiscorrectly.",
addrDescription.Address,addrDescription.Description);
returnfalse;
}
if(coordinates.Count>1)
{
_LastErrorOrWarning=string.Format("Address:{0},Description:{1}hasmorethanonecoordinates.",
addrDescription.Address,addrDescription.Description);
}
stringcolorId=Colors[_ColorIndex];
_ColorIndex++;
if(_ColorIndex>=Colors.Count)
{
_ColorIndex=0;
}
_Kml.Document.Add(newPlacemark(addrDescription.Address,addrDescription.Description,colorId,
coordinates[0].Latitude,coordinates[0].Longitude));
returntrue;
}


.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}

第32行有个bug,应该是>=,我原来写成>了,博客中我改过来了,源码我就不改了。

如上代码,第12行就是通过GeocodingApi获取指定地址的物理坐标,由于有时候获取不到坐标,有时候由于地址不确切,有多个坐标,所以我加了一个错误和警告的属性,用于调用者得到相关的信息。

_Kml这个对象是一个Kml类的实例,这个类用于生成KML文件结构,并可以保存到KML文件中。这个类在后面介绍。

下面的_Color部分是自动的顺序分配标注点的颜色,我为了省事,在代码中写死了4种颜色,你也可以修改代码增加颜色或其他图标。

标注颜色这里其实还有一个问题,就是如果让相邻的节点显示不同颜色,这个算法比较复杂了,我没有实现,各位如果有兴趣可以思考一下这个怎么做。

好了,最大的问题解决了,剩下就是写xml文件了,这个很简单,我就不深入讲了,直接把代码贴出来。

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Xml;
usingSystem.Xml.Serialization;
usingSystem.IO;

namespaceGenerateKML
{
publicclassPlacemark
{
publicclassKMLPoint
{
publicKMLPoint()
{
}

publicKMLPoint(doublelatitude,doublelongitude)
{
SetCoordinates(latitude,longitude);
}

privatestring_coordinates;

publicvoidSetCoordinates(doublelatitude,doublelongitude)
{
_coordinates=longitude.ToString()+","+latitude.ToString();
}

publicstringcoordinates
{
get
{
return_coordinates;
}

set
{
_coordinates=value;
}
}
}

[XmlElement("name")]
publicstringName{get;set;}

[XmlElement("description")]
publicstringDescription{get;set;}

[XmlElement("styleUrl")]
publicstringStyleUrl{get;set;}

publicKMLPointPoint{get;set;}

publicPlacemark()
{
}

publicPlacemark(stringname,stringdescription,stringstyleUrl,
doublelatitude,doublelongitude)
{
Name=name;
Description=description;
StyleUrl=styleUrl;

Point=newKMLPoint(latitude,longitude);
}

}

publicclasskml
{
[XmlIgnore]
stringName{get;set;}

List<Placemark>_Placemarks=newList<Placemark>();

[XmlArray()]
publicList<Placemark>Document
{
get
{
return_Placemarks;
}

set
{
_Placemarks=value;
}
}

publickml()
{
}

publickml(stringname)
{
Name=name;
}

privateXmlNodeGetColorStyle(XmlDocumentxmlDoc,stringcolor)
{
XmlNodestyle=xmlDoc.CreateNode(XmlNodeType.Element,"Style","");
XmlAttributeattr=style.OwnerDocument.CreateAttribute("id");
attr.Value=color;
style.Attributes.Append(attr);

XmlNodeiconStyle=xmlDoc.CreateNode(XmlNodeType.Element,"IconStyle","");
XmlNodeicon=xmlDoc.CreateNode(XmlNodeType.Element,"Icon","");
XmlNodehref=xmlDoc.CreateNode(XmlNodeType.Element,"href","");
href.InnerText=string.Format("http://www.google.com/intl/en_us/mapfiles/ms/icons/{0}-dot.png",
color);

style.AppendChild(iconStyle);
iconStyle.AppendChild(icon);
icon.AppendChild(href);

returnstyle;
}

publicvoidSaveToFile(stringxml)
{
using(FileStreamfs=newFileStream(xml,FileMode.Create,FileAccess.ReadWrite))
{
using(StreamWritersw=newStreamWriter(fs,System.Text.Encoding.UTF8))
{
XmlSerializerserializer=newXmlSerializer(this.GetType());
serializer.Serialize(sw,this);
}
}

XmlDocumentxmlDoc=newXmlDocument();
xmlDoc.Load(xml);
xmlDoc.CreateXmlDeclaration("1.0","utf-8",null);

XmlNodedocumentNode=xmlDoc.SelectSingleNode(@"/kml/Document");

XmlNodenameNode=xmlDoc.CreateNode(XmlNodeType.Element,"name","");
nameNode.InnerText=this.Name;

XmlNodeplaceMarkNode=documentNode.FirstChild;
documentNode.InsertBefore(nameNode,placeMarkNode);

documentNode.InsertBefore(GetColorStyle(xmlDoc,"red"),placeMarkNode);
documentNode.InsertBefore(GetColorStyle(xmlDoc,"green"),placeMarkNode);
documentNode.InsertBefore(GetColorStyle(xmlDoc,"blue"),placeMarkNode);
documentNode.InsertBefore(GetColorStyle(xmlDoc,"yellow"),placeMarkNode);

XmlNodekmlNode=xmlDoc.SelectSingleNode(@"/kml");

XmlAttributeattr=kmlNode.OwnerDocument.CreateAttribute("xmlns");
attr.Value="http://earth.google.com/kml/2.0";

kmlNode.Attributes.Append(attr);

xmlDoc.Save(xml);
}
}

}


.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}

下面看一下调用的方法,使用者如果不想仔细研究细节,那就关注这个就可以了,调用方法非常简单

staticvoidMain(string[]args)

{

GeneratorkmlGenerator=newGenerator("Test");


kmlGenerator.Generate(newAddressDescription("1600AmphitheatreParkway,MountainView,CA94043",

"Google"));


if(!string.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))

{

Console.WriteLine(kmlGenerator.LastErrorOrWarning);

}


kmlGenerator.Generate(newAddressDescription("1MicrosoftWay,Redmond,WA98052",

"Microsoft"));


if(!string.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))

{

Console.WriteLine(kmlGenerator.LastErrorOrWarning);

}


kmlGenerator.Generate(newAddressDescription("1601S.CaliforniaAve.,PaloAlto,CA95304",

"Facebook"));


if(!string.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))

{

Console.WriteLine(kmlGenerator.LastErrorOrWarning);

}


kmlGenerator.Generate(newAddressDescription("701FirstAve,Sunnyvale,CA94089",

"Yahoo"));


if(!string.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))

{

Console.WriteLine(kmlGenerator.LastErrorOrWarning);

}


kmlGenerator.Save("test.kml");

}

}


第三行,实例化KML生成器,并指定一个名字,这个名字对于kml文档中的name字段。

第五行,在kml文件中标注google总部的地址

第八行,判断是否有最新的错误,每次执行第五行的Generate方法,会将最新错误清空,所以这里永远是得到最近一次调用Generate方法的错误或警告。

后面以此类推了。

最后Save到一个kml文件中就OK了。


最后,我们可以把这个kml文件导入到我们自己创建的googlemap中。这个在googlemaps里面有相应的导入功能,这里就不介绍了。


完整源码下载


完整源码


注意源码中app.config文件中


<addkey="GeocodingApi.Key"value="googleapikey"/>
<addkey="GeocodingApi.Url"value="http://maps.google.com/maps/geo?"/>

GeocodingApi.key这里要填写你自己的googleapikey,你可以在google网站上获取,地址如下:

http://code.google.com/apis/maps/signup.html

.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}


.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: