Autor |
Beitrag |
flyhigh83
      
Beiträge: 67
Win 7
C# (VS2010)
|
Verfasst: Mo 03.01.11 15:52
Hallo ich bin gerade an einer Google Maps API welche die schnellste Route brechnen soll.
Ich weis es gibt schon einige wenige Internetseite welche das machen. Ich wollte aber auf meine eigene Datenbank zugreifen und diese Werte dort nutzten. Und nicht mit mehreren Fremden Internetseiten dann Rückgabewerte holen etc.
Allerdings ist mir XML noch etwas neu und ich habe damit nich so viel Erfahrung. Vielleicht kann mir jemand helfen.
Mein Problem ist noch die Struktur sauber darzustellen.
Hier erstmal mein bisheriger Code
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115:
| static class GoogleMaps { public struct GoogleMapsData { public string start_location; public string end_location; public string start_address; public string end_address; public string lat; public string lng; public string copyrigths; }
public static IEnumerable<GoogleMapsData> GetMapsRoute() { List<GoogleMapsData> ergebnis = new List<GoogleMapsData>();
WebClient web = new WebClient();
string url = "http://maps.google.com/maps/api/directions/xml?origin=Adelaide,SA&destination=Adelaide,SA&waypoints=optimize:true|Barossa+Valley,SA|Clare,SA|Connawarra,SA|McLaren+Vale,SA&sensor=false"; string xmlMapsRoute; try { using (StreamReader sr = new StreamReader(web.OpenRead(url))) { xmlMapsRoute = sr.ReadToEnd(); sr.Close(); } } catch (Exception) { return null; }
XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlMapsRoute); XmlElement root = doc.DocumentElement; if (root != null) { XmlNode xmlroute = root["route"]; if (xmlroute != null) { foreach (XmlNode leg in xmlroute) { if (leg.Name == "leg") { GoogleMapsData mapsdata = new GoogleMapsData(); XmlNode startaddressNode = leg["start_address"]; if (startaddressNode != null) mapsdata.start_address = leg["start_address"].GetInnerText(); XmlNode endaddressNode = leg["end_address"]; if (endaddressNode != null) mapsdata.end_address = leg["end_address"].GetInnerText();
XmlNode startlocation = leg["start_location"]; if (startlocation != null) { mapsdata.start_location = startlocation["lat"].GetInnerText(); mapsdata.start_location = startlocation["lng"].GetInnerText(); } XmlNode endlocation = leg["end_location"]; if (endlocation != null) { mapsdata.end_location = endlocation["lat"].GetInnerText(); mapsdata.end_location = endlocation["lng"].GetInnerText(); } ergebnis.Add(mapsdata); } } } }
return ergebnis; }
private static string GetInnerText(this XmlElement node) { if (node != null) return node.InnerText; return ""; } |
Also wo ich noch Probleme habe ist. Ich habe zwar die Daten jetzt in einem Struckt aber ist das so gut für die Rückgabe. Und ich kapiere noch nicht so richtig wie die GoogleMaps Daten aufgebaut sind.
Also die Route beinhaltet alle Orte aus meinem String welche ich nur mal testhalber an Google so schicke. Wird noch abgeändert. die "leg" sind die einzelnen Anfahrtsziele. Darunter gibt es Knoten welche "step" heisen. Also jeweils immer wie lange man auf einer Straße fährt. Dies benötige ich bisher mal noch nicht.
Mich interresiiert eigentlich nur die Reihenfolge der Anfahrstorte, welche die API mir ja berechnet so wie ich die Anfrage abschicke. Ich vermute mal das "start-Location" und "end_location" mit ihren Koordinaten "lat" und "lng" die jeweiligen Anfangs Punkte und Endpunkte jeder einzelnen Tour sind. Also das was ich brauch.
Denn wenn die Berechnung fertig ist, will ich dem User die Ziele anzeigen in welcher Reihenfolge er diese anfahren sollte. Der Genau Plan und weitere Punkte wie lange er auf welcher Straße bleibt folgt, wenn ich Zeit finde weiterzuprogrammieren.
Danke mal im vorraus für eure Hilfe
|
|
Trashkid2000
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: Mo 03.01.11 20:53
Hallo,
also wenn ich diese URL aufrufe
Quelltext 1:
| http://maps.google.com/maps/api/directions/xml?origin=Berlin,DE&destination=Hamburg,DE&waypoints=optimize:true|Bremen,DE&sensor=false | , dann bedeutet es, dass ich von Berlin über Bremen nach Hamburg fahren möchte. Als Antwort kommt also vom Server (gekürzt):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53:
| <?xml version="1.0" encoding="UTF-8"?> <DirectionsResponse> <status>OK</status> <route> <summary>A1</summary> <leg> <duration> <value>13399</value> <text>3 Stunden, 43 Minuten</text> </duration> <distance> <value>391770</value> <text>392 km</text> </distance> <start_location> <lat>52.5234000</lat> <lng>13.4114000</lng> </start_location> <end_location> <lat>53.0749800</lat> <lng>8.8070800</lng> </end_location> <start_address>Berlin, Bundesrepublik Deutschland</start_address> <end_address>Bremen, Bundesrepublik Deutschland</end_address> </leg> <leg> <duration> <value>4859</value> <text>1 Stunde, 21 Minuten</text> </duration> <distance> <value>123869</value> <text>124 km</text> </distance> <start_location> <lat>53.0749800</lat> <lng>8.8070800</lng> </start_location> <end_location> <lat>53.5538100</lat> <lng>9.9915800</lng> </end_location> <start_address>Bremen, Bundesrepublik Deutschland</start_address> <end_address>Hamburg, Bundesrepublik Deutschland</end_address> </leg> </route> </DirectionsResponse> | Also, die Daten in der XML sind schon in der Reihenfolge, in der man die Ziele anfahren möchte.
LG, Marko
|
|
Trashkid2000
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: Mo 03.01.11 21:38
Ups, ein wenig zu voreilig...
Also, habe gerade bei der google-api-Doku gelesen, dass wenn man
Quelltext 1:
| waypoints=optimize:true | mit angibt, die Zwischenstationen so sortiert werden, dass sie den kürzesten Weg ergeben.
Aber gut, in der XML sind sie dann ja wieder in der richtigen Reihenfolge - nur optimiert eben
Also, wenn Du willst, dass die Zwischenstationen wie in der angegebenen Reihenfolge abgefahren werden sollen, lasse einfach das optimize weg.
//edit: Darf man fragen, warum Du ein Struct verwendest? Nicht, dass es mich stören würde.
|
|
flyhigh83 
      
Beiträge: 67
Win 7
C# (VS2010)
|
Verfasst: Di 04.01.11 10:04
Morgen,
ich habe ein "Struct" verwendet, da es eigentlich ja mit das richtige für kleine Datenmengen und Wertetypen ist.
Ob es genau das richtige für meine Anwendung ist, hatte ich mir gedachte werde ich eh früher oder später noch merken, da ich mir bisher keinen plan gemacht habe was ich wie implementiere. Das soll eher ein kleines erweiterungsprojekt werden, wo man immer wieder mal etwas dazu einbindet. Wie ich auch geschrieben habe. Erstmal möchte ich die Routenberechnung hinbekommen.
Mein größtes Problem bei derm ersten Teil kommt noch. Da die API von Google nur 8 bzw 23 Ziele als Pro Client zulässt. Ich es aber möglich machen will, auch mehrere Ziele anfahren zu können. Also unter umständen auch mal bis zu 50 oder so.
Aktuell hänge ich aber noch daran, wie ich die XML Datei jetzt wieder ordentlich in eine Liste Pakte. Diese würde ich dann als Rückgabewert für die Methode angeben, um sozusagen mal ein kleines Modul zu haben, welches einen Teil der Google Maps API abbildet.
Wie gesagt, mir fällt gerade nichts wirklich ein, wie ich das sauber strukturieren kann, da mir auch noch etwas der Überblick fehlt, welche Werte was genau sind.
Vielleicht für die die mir mit Helfen wollen hier mal kurz die Übersicht welche ich bisher verstanden habe.
Knoten: route = soll die komplette Route darstellen
|-> leg = soll jeweils eine Zwischenstation sein
|-> step = sind die einzelnen angaben zu den Straßen und wie lange man da fahren muss etc.
|-> travel_mode = ist die einstellung welche man schon vorher beim
link setzen kann, ob man mit dem Auto zu Fuß etc. fährt
|-> start_location = Angaben Startpunkt
|-> lat = GPS Koordinaten
|-> lng = GPS Koordinaten
|-> end_location = Angaben Endpunkt
|-> polyline = ?
|-> duration = Dauer
|-> html_instructions = Textangaben, wo abbiegen etc.
|-> distance = Streckenlänge
|-> copyrights = Rechte
|-> waypoint_index = Wegpunkte Zahl ist der Index, in der es dem Link übergeben wurde.
Alle Daten habe ich jetzt mal nicht aufgeliste, da die weiteren Angaben, zumindest erstmal unwichtig sind.
Ich weis jetzt nicht genau wie ich diese Daten am besten Abbilde. Wie macht man das am geschicktesten?
Ich verstehe noch nicht wie ich das mit dem Knoten und dem Unterknoten mache. Wie packe ich dies am besten in eine Liste oder irgend sowas. die für mich wichtigsten Daten sind eigentlich erstmals mit die "legs" davon die Start und End Location, da ich die GPS Koordinaten brauche um diese dann später über eine andere Methode in eine TomTom Routenplaner Datei einzubetten. Schön wäre aber wenn ich alle Koordinaten und HTML etc. Angaben hätte, da ich so dann auch eine Seite zum Ausdrucken erstellen könnte.
Zuletzt bearbeitet von flyhigh83 am Di 04.01.11 10:09, insgesamt 1-mal bearbeitet
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Di 04.01.11 12:03
flyhigh83 hat folgendes geschrieben : | ich habe ein "Struct" verwendet, da es eigentlich ja mit das richtige für kleine Datenmengen und Wertetypen ist. |
Naja, du verstößt gegen mindestens drei der vier Richtlinien  .
_________________ >λ=
Für diesen Beitrag haben gedankt: flyhigh83
|
|
Trashkid2000
      
Beiträge: 561
Erhaltene Danke: 137
|
Verfasst: Di 04.01.11 21:21
Hi,
flyhigh83 hat folgendes geschrieben : | Mein größtes Problem bei derm ersten Teil kommt noch. Da die API von Google nur 8 bzw 23 Ziele als Pro Client zulässt. Ich es aber möglich machen will, auch mehrere Ziele anfahren zu können. Also unter umständen auch mal bis zu 50 oder so. |
Nun ja, da würde es höchsten die Möglichkeit geben, mehrere Abfragen zu starten und die Ergebnisse zu sammeln. Was es natürlich schwierig macht, wenn die Zwischenstationen von Google noch optimiert werrden sollen...
Das mit dem sauber strukturieren: Also, Du hast eine Klasse, die alle Daten aufnimmt, die Du denn benötigst. In Deiner Prozedur liest Du aus der von Google zurückgegebenen xml die Daten aus und gibst sie dann zurück. Ich sehe da keinen wirklichen Probleme. Das Auslesen könnte wie folgt aussehen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| XDocument route = XDocument.Parse(File.ReadAllText("c:\\temp\\google.xml")); foreach (XElement station in route.Descendants("leg")) { var s = station.Elements("start_address").FirstOrDefault(); if (s != null && !string.IsNullOrEmpty(s.Value)) { string startAddress = s.Value; } var e = station.Elements("end_address").FirstOrDefault(); if (e != null && !string.IsNullOrEmpty(e.Value)) { string endAddress = e.Value; } var d = station.Elements("distance").FirstOrDefault(); if (d != null) { var dist = d.Elements("value").FirstOrDefault(); if (dist != null && !string.IsNullOrEmpty(dist.Value)) { int distance = int.Parse(dist.Value); } } } | Die Daten musst Du doch nur noch in Deine Klasse packen, und der Liste hinzufügen. Und mit der Fehlerbehandlung: bei fremd-angebotenen xml (gerade auf einem Webserver) kann es ja immer sein, dass sich an der Struktur was ändert...also sollte dabei viel Sorgfalt herrschen. Oder Du erstellst Dir ein Schema, gegen das Du die xml prüfst. So kannst Du sicher sein, dass das Schema, gegen das Du programmiert hast, noch aktuell ist.
Marko
|
|
flyhigh83 
      
Beiträge: 67
Win 7
C# (VS2010)
|
Verfasst: Di 11.01.11 17:16
Hallo zusammen,
ich wollte mal einige Ausschnitte aus meinem Code hier Poste, falls jemand auch TomTom (*.itn) Dateien erstellen will und dazu die GoogleMaps API benutzen will, um die Routenplanung zu optimieren.
Ich hoffe es ist so ok in diesem Beitrag, sonst verschiebt ihn oder ...
Klasse TomTom
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| class TomTom { private string _geoData1; private string _geoData2; private string _bezeichnung; public string GeoData1 { get { return this._geoData1; } set { this._geoData1 = value; } }
public string GeoData2 { get { return this._geoData2; } set { this._geoData2 = value; } }
public string Bezeichnung { get { return this._bezeichnung; } set { this._bezeichnung = value; } }
public static void createTomTomitn(List<TomTom> Routenliste, string Pfad, int ZielortPoint) { StreamWriter myWriter = File.CreateText(@Pfad); foreach (TomTom GeoElement in Routenliste) { string GeoData1 = GoogleMaps.ConvertDegToDec(GeoElement.GeoData1).Split(',')[0] + GoogleMaps.ConvertDegToDec(GeoElement.GeoData1).Split(',')[1].Substring(0, 5); string GeoData2 = GoogleMaps.ConvertDegToDec(GeoElement.GeoData2).Split(',')[0] + GoogleMaps.ConvertDegToDec(GeoElement.GeoData2).Split(',')[1].Substring(0, 5);
myWriter.WriteLine(String.Format("{0}|{1}|{2}|{3}|", GeoData2, GeoData1, GeoElement.Bezeichnung, ZielortPoint)); } myWriter.Close(); } } |
Klasse GoogleMaps
Diese ist noch am Anfang die Methoden müssen noch ausgebaut werden.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140:
| class GoogleMaps { private string _lat; private string _lng; private string _startAddress; private string _endAddress; private string _distance;
public string Lat { get { return _lat; } set { _lat = value; } }
public string Lng { get { return _lng; } set { _lng = value; } }
public string StartAddresse { get { return _startAddress; } set { _startAddress = value; } }
public string EndAddresse { get { return _endAddress; } set { _endAddress = value; } }
public string Distance { get { return _distance; } set { _distance = value; } }
public static List<int> GoogleMapsRoutenreihenfolge(string startRoute, string endRoute, List<TomTom> routenZiele) { List<int> ergebnis = new List<int>();
WebClient web = new WebClient();
string url = string.Format("http://maps.google.com/maps/api/directions/xml?origin={0}&destination={1}&waypoints=optimize:true", startRoute, endRoute);
foreach (TomTom ziel in routenZiele) { url += string.Format("|{0},{1}", ConvertDegToDec(ziel.GeoData1).Replace(',', '.'), ConvertDegToDec(ziel.GeoData2).Replace(',', '.')); }
url += "&sensor=false";
string xmlMapsRoute; try { using (StreamReader sr = new StreamReader(web.OpenRead(url))) { xmlMapsRoute = sr.ReadToEnd(); sr.Close(); } } catch (Exception) { return null; }
XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlMapsRoute); XmlElement root = doc.DocumentElement; if (root != null) { XmlNode xmlroute = root["route"]; if (xmlroute != null) { foreach (XmlNode waypoint in xmlroute) { if (waypoint.Name == "waypoint_index") { string _distance = waypoint.InnerText; ergebnis.Add(Convert.ToInt32(waypoint.InnerText)); } } } } return ergebnis; }
public static string ConvertDecimalDegreesToSexagesimal(double decimalValueToConvert) { int degrees = (int)decimalValueToConvert; int minutes = (int)((decimalValueToConvert - degrees) * 60); int seconds = (int)((decimalValueToConvert - degrees - (minutes / 60)) * 3600);
return String.Format("{0}° {1}' {2}''", degrees, minutes, seconds); }
public static string ConvertDegToDec(string GeoData) { double geokoordinaten = Convert.ToDouble(GeoData.Substring(4, 6)) / 60; return String.Format("{0:##.000000}", Convert.ToDouble(GeoData.Substring(1, 2) + ',' + geokoordinaten.ToString().Replace(",", ""))); } } |
Wer also Änderungen oder weitere Vorschläge hat gerne her damit. Aktuell bin ich noch am probieren wie man am besten die Routenpunkte berechnet da Google ja nur 8 bzw. 23 für die Pro user zulässt.
|
|
|