65.9K
CodeProject 正在变化。 阅读更多。
Home

如何创建自己的谷歌地图

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (9投票s)

2012年5月21日

CPOL

3分钟阅读

viewsIcon

44606

downloadIcon

1539

从多个位置创建您自己的 Google 地图的简单方法。

引言

几天前,我收到了一个任务,需要用几个点创建我自己的 Google 地图。逐个创建点很容易,但我很懒。 我认为最简单的方法是创建一个包含 POI(兴趣点)的 Excel 表格,然后创建一个程序来获取 POI 的 LAT-LON 坐标。这项任务并不难。 Google API 提供了从邮政地址获取 LAT-LON 坐标的可能性,这正是我所需要的。

此解决方案解决了什么问题?

该程序有助于使用 .kml 文件创建您自己的 Google 地图。无需逐点创建自己的地图,您可以创建一个简单的 Excel 文件,其中包含 POI 和邮政地址,只需点击几下,您的自定义地图就准备好了。

背景

首先,在这里学习 Google Maps API 非常有用:https://developers.google.com/maps/documentation/geocoding/

但我希望从我的代码中可以理解基本知识和主要内容。然后,对操作 Microsoft Excel 表格有一些经验,并且对 xml 文件和 Linq 有一些经验,这很有帮助。

简单的 Excel 文件包含此格式的 POI:名称、邮编、城市、街道、门牌号、国家/地区。

在这个例子中,我创建了一个 Excel 文件进行尝试,并查看这个过程的源文件格式。下载示例,编译并试用。加载我的示例 (ownmap.xls) 导出 .kml 文件,然后查看结果。现在您可以将此 kml 文件导入 Google Maps。

重要提示!您每天可以从 Google Api 读取 2500 个地址,无需许可证。如果您需要更多,则必须购买 Google 的商业许可证。

有什么教育意义?

在此简单代码中,我演示了 C# 中的 Web 请求和 Web 响应。您可以查看一个在 Linq 中解析 xml 文件的示例。 POI 位于 Excel 文件中,因此这是一个通过 Office Interop 读取和写入 Excel 文件的非常简单的示例。最后但并非最不重要的一点是,此程序创建一个 .kml 文件,它实际上是一个 xml 文件,因此这里有一个如何创建简单 xml 文件(如文本文件)的示例。

关键词

  • 通过 Office Interop 读取和写入 Microsoft Excel 表格
  • 简单的 Web 请求和响应
  • 用于解析 xml 的简单 Linq。

使用代码

首先,我制作了一个结构体mylocatinon,作为位置的容器。 GPS 坐标将采用十进制格式,例如 47.197484。因此,LAT 和 LON 坐标将是double 数字。

   
/// <summary>
/// Location container for LAT-LON coordinates. They are doubles
/// </summary>  
public struct mylocation
       {
/// <summary>
/// Holds the latitude information
/// </summary>
public double latitude;
/// <summary>
/// Holds the longitude information
/// </summary>
public double longitude;
 }

根据我的经验,Google API 可以使用我们的(匈牙利)国家字符,例如 á、é,但有时不行。除此之外,我必须从邮政地址创建一个标准 URL,即把空格更改为 %20 等。 因此,convuri 方法将任何文本转换为 URL 格式,而无需国家字符。

/// <summary>    

/// This routine converts the national characters to standard.
/// Goolgle api can parse the national characters, but my experinece is better change to standard chars.
/// This method is especially converts hungarian national chars.
/// If You use another national chars, please overwrite this methos.
/// </summary>
/// <param name="be">Input parameter for convert</param>
/// <returns>
/// string
/// </returns>

public string convuri(string be) 
{
    if (be == "")
    {
        return null;
public string convuri(string be)
        {
if (be == "")
            {

return null;
            }
// Output will be the input in default case
string ret = be;
// Old, national chars to be changed
string[] oldchars = { "á", "í", "ű", "ő", "ü", 
  "ö", "ú", "ó", "é", " ", "Á", "Í", 
  "Ű", "Ő", "Ü", "Ö", "Ú", "Ó", "É", "." };
// New chars to change for
string[] newchars = { "a", "i", "u", "o", "u", "o", 
  "u", "o", "e", " ", "A", "I", "U", 
  "O", "U", "O", "U", "O", "E", "." };
// Changing cycle
for (int i = 0; i < oldchars.Length - 1; i++)
            {
                ret = ret.Replace(oldchars[i], newchars[i]);
            }
//converts the space to hex 20 (32) that means the space in URL
            ret = ret.Replace(
" ", "%20");
 return ret;
        }
    }
    string ret = be;
    string[] oldchars = { "á", "í", "ű", "ő", "ü", "ö", 
      "ú", "ó", "é", " ", "Á", "Í", "Ű", 
      "Ő", "Ü", "Ö", "Ú", "Ó", "É", "." };
    string[] newchars = { "a", "i", "u", "o", "u", "o", 
      "u", "o", "e", " ", "A", "I", "U", 
      "O", "U", "O", "U", "O", "E", "." };
    for (int i = 0; i < oldchars.Length - 1; i++)
    {
        ret = ret.Replace(oldchars[i], newchars[i]);
    }
    //converts the space to hex 20 (32) that means the space in URL
    ret = ret.Replace(" ", "%20");
    return ret;
}

接下来要强调的是 Web 请求。我编写了一个名为Getloc 的方法。此方法返回邮政地址的 LAT LON 坐标。如果发生错误,getloc 方法将返回 -1,-1 坐标。

在此示例中,myuri 变量包含转换后的(见下文)带有邮政地址的 URL。地址必须采用以下格式:门牌号 街道 邮编 城市 国家/地区。 空格将被转换为 URL 格式:%20

//Define wbrequest, and webresponse. Response will be an xml document.

System.Net.HttpWebRequest webRequest;
System.Net.HttpWebResponse webResponse;

//create address from excel                  
string cim = hsz.Trim() + " " + utca.Trim() + " " + zip.Trim() + 
             " " + varos.Trim() + " " + orszag.Trim();

//convert and clean url  
  cim = convuri(cim);
  Uri myuri = new Uri("http://maps.googleapis.com/maps/api/geocode/xml?address=" + 
                      cim + "&sensor=true");

 webRequest = (HttpWebRequest)(WebRequest.Create(myuri));
 webRequest.Credentials = CredentialCache.DefaultCredentials;

 // Companies mostly uses proxy servers. If You use it from home, proxy is not necessary
 WebProxy p = new WebProxy(textBox2.Text, Convert.ToInt32(textBox3.Text));
 //You can use default (login) credentials, or some else credential, like this
 // p.Credentials = new NetworkCredential("user","password","domain")

p.Credentials = CredentialCache.DefaultCredentials;
if (checkBox1.Checked)
{
    webRequest.Proxy = p;
}

webRequest.Proxy = p;
webRequest.Method = "GET";
webRequest.ContentType = "text/xml";
                   
//Call a normal WEB request. Response will be a standard xml file.
webResponse = (System.Net.HttpWebResponse)(webRequest.GetResponse());
webResponse.GetResponseStream();
StreamReader sr = new StreamReader(webResponse.GetResponseStream());

Web 请求的答案将是一个 XML。 此示例演示了如何使用 linq 解析 xml。 在此示例中,ret 是一个类型为 mylocation 的局部变量(见下文)

 
//Create a new xml document named  resxml
XmlDocument resxml = new XmlDocument();
//Load stream content into resxml variable
                resxml.LoadXml(sr.ReadToEnd());
//Closes the stream.
               sr.Close();
//Converts xml content into a string
string sss = resxml.InnerXml.ToString();
//Not needed
               resxml = null;
//Parsing the xml contetnt with linq.
// xml nodes result - geometry - location and values what we needed is lat, and lon. 
//There are NOT attributes.
//<result>
//....
//    <geometry>
//...
//        <location>
//             <lat> 47,19745464</lat>
//             <lon> 19,15678664</lon>
//         </location>
//etc                
// </summary>
XDocument xdoc = XDocument.Parse(sss);
//Linq question. Result will be a LAT-LON struct, like mylocatin struct
var aaas = from aaa in xdoc.Descendants("result").Descendants("geometry").Descendants("location")
select new
 {
    lat = aaa.Element("lat").Value,
    lon = aaa.Element("lng").Value
  };
//Cycle for get linq query's values, and put into a mylocation typed struct.
foreach (var aaa in aaas)
{
    ret.latitude = Convert.ToDouble(aaa.lat);
    ret.longitude = Convert.ToDouble(aaa.lon);
}

最后,但并非最不重要的一点是,如何使用 interop 模块操作 MS Excel 文件

//Call Excel interop. The excel application represents oApp variable
Microsoft.Office.Interop.Excel.Application oApp = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = null;
Worksheet ws = null;

// Excel will NOT visible is this routine
oApp.Visible = false;
// Its maybe necessary when use excel from a program.
oApp.UserControl = false;

// The best method to change the culture info to en-Us when using excel.
// I had problems with excel interoperation with another culture info.
System.Globalization.CultureInfo oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Globalization.CultureInfo Cli = new System.Globalization.CultureInfo("en-US");
System.Threading.Thread.CurrentThread.CurrentCulture = Cli;

// Creates a stringbuilder method. The result kml will be created into sb variable.
StringBuilder sb = new StringBuilder();
// Creates the kml file's header. In fact kml is a special xml.
// The own map's name can give in textbox5.text on form.

sb.AppendLine("");
sb.AppendLine("<kml xmlns="http://www.google.com/earth/kml/2">");
sb.AppendLine("<document>");
sb.AppendLine("<name>" + textBox5.Text + "</name>");

try
{
    // Opens an excel file, name given in textbox1.text
    wb = oApp.Workbooks.Open(textBox1.Text);
    // Sets worksheets object
    Sheets sheets = wb.Worksheets;
    // To set diplayalerts to fals is necessary. If you not set to false,
    // excel will ask to "Save document" before quiting.
    oApp.DisplayAlerts = false;
    // Sets the first worksheet to work on.
    ws = (Worksheet)sheets.get_Item(1);

    // Ask userd range of excel. 
    Range ur = ws.UsedRange;
    Range cell;
    // Declares some variables
    string orszag;
    string nev;
    string varos;
    string utca;
    string hsz;
    string zip;
    string lat;
    string lon;

    // Cycle to read excel row by row in used range

    for (int i = 1; i <= ur.Cells.Rows.Count; i++)
    {
        // First column is the name of POI. Writes into the form into label1
        cell = (Range)ws.Cells[i, 1];
        nev = cell.Value.ToString();
        label1.Text = nev;

        // Second column column is the ZIP of POI
        cell = (Range)ws.Cells[i, 2];
        zip = cell.Value.ToString();

        // Third column column is the varos of POI
        cell = (Range)ws.Cells[i, 3];
        varos = cell.Value.ToString();
        // Fourth column is the street of POI
        cell = (Range)ws.Cells[i, 4];
        utca = cell.Value.ToString();
        // Fifth column is the housenumber of POI
        cell = (Range)ws.Cells[i, 5];
        hsz = cell.Value.ToString();
        // Sixth column is the country of POI
        cell = (Range)ws.Cells[i, 6];
        orszag = cell.Value.ToString();
        // Seventh column is the LAT value of POI
        cell = (Range)ws.Cells[i, 7];
        lat = cell.Value.ToString();
        // Eighth column is the LAT value of POI
        cell = (Range)ws.Cells[i, 8];
        lon = cell.Value.ToString();

        // Appends parameters into sb stringbuilder in kml format
        sb.AppendLine("<placemark>");
        sb.AppendLine("<name>" + nev + "</name>");
        sb.AppendLine("<description>" + varos.Trim() + ", " + zip.Trim() + 
          " " + utca.Trim() + " " + hsz.Trim() + "</description>");
        sb.AppendLine("<point>");
        sb.AppendLine("<coordinates>" + lon + "," + lat + ",0</coordinates>");
        sb.AppendLine("</point>");
        sb.AppendLine("</placemark>");

    }
}
catch (Exception ex)
{
     // In case of any problem shows a message
     MessageBox.Show(ex.Message);
}
// Finally will do this with excel either everithing was good or not.
finally
{
    
    // Saves back the worksheet
    wb.Save();
    // Quits from excel
    oApp.Quit();
    
    // Sets back excelapp displayalerts property to true
     oApp.DisplayAlerts = true;

    // Sets back the original cultureinfo
    System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;


    // Releases COM objects,  the workbook, worksheet and excelapp objects
    Marshal.ReleaseComObject(ws);
    Marshal.ReleaseComObject(wb);
    Marshal.ReleaseComObject(oApp);

}

// Appends the end of kml into sb stringbuilder 

sb.AppendLine("</document>");
sb.AppendLine("</kml>");

如何从生成的 .kml 文件制作自己的 Google 地图?

在使用此程序后(从 excel 开始,然后将结果导出到 .kml),您可以制作自己的 Google 地图。 上传自己的地图需要一个 Google 帐户(gmail)。 转到 Google 地图 站点,选择自己的地点。 创建一个新地图。 命名并简短描述,然后导入新的 .kml 文件。 仅此而已。

历史

  • 版本 1.0。
© . All rights reserved.