using System; using System.Collections.Generic; using System.IO; using System.Xml; using HeuristicLab.Problems.RoutePlanning.Data.Core; using HeuristicLab.Problems.RoutePlanning.Data.Osm.Core; using HeuristicLab.Problems.RoutePlanning.Interfaces; using HeuristicLab.Problems.RoutePlanning.RoutingGraph; namespace HeuristicLab.Problems.RoutePlanning.Data.Osm { public class OsmDataSource : IDataSource { private FileInfo file; private ICostCalculator costCalculator; private IGraph graph; private Dictionary vertices; public OsmDataSource(string filename) : this(filename, new TravelTimeCostCalculator()) { } public OsmDataSource(string filename, ICostCalculator costCalc) { file = new FileInfo(filename); costCalculator = costCalc; graph = new Graph(); vertices = new Dictionary(); ReadData(); } #region IDataSource Members public IGraph GetRoutingGraph() { return graph; } public IGraph GetRoutingGraph(VehicleType vehicle) { throw new NotImplementedException(); } #endregion private Vertex GetVertex(long Id) { Vertex v; if (vertices.TryGetValue(Id, out v)) { return v; } else { return null; } } private void ReadData() { XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreComments = true; settings.IgnoreWhitespace = true; using (XmlReader reader = XmlReader.Create(file.FullName, settings)) { reader.ReadStartElement("osm"); //reader.ReadStartElement("bounds"); reader.Read(); while (reader.LocalName.Equals("node")) { double lat = XmlConvert.ToDouble(reader.GetAttribute("lat")); double lon = XmlConvert.ToDouble(reader.GetAttribute("lon")); long id = XmlConvert.ToInt64(reader.GetAttribute("id")); Vertex v = new Vertex(id, lon, lat); vertices.Add(v.Id, v); reader.Read(); if (reader.LocalName.Equals("tag")) { reader.ReadToFollowing("node"); } } while (reader.LocalName.Equals("way")) { List way = new List(); bool missingNodes = false; HighwayType category = HighwayType.null_type; bool oneWayRoad = false; reader.Read(); while (reader.LocalName.Equals("nd") || reader.LocalName.Equals("tag")) { if (reader.LocalName.Equals("nd")) { long refNodeId = XmlConvert.ToInt64(reader.GetAttribute("ref")); Vertex vertex = GetVertex(refNodeId); if (vertex != null) { way.Add(vertex); } else { missingNodes = true; } } else if (reader.LocalName.Equals("tag")) { string key = reader.GetAttribute("k"); string value = reader.GetAttribute("v"); if (key == TagConstants.HighwayTagKey) { if (Enum.IsDefined(typeof(HighwayType), value)) { HighwayType ht = (HighwayType)Enum.Parse(typeof(HighwayType), value, true); category = ht; } else { category = HighwayType.null_type; } } else if (key == TagConstants.OneWayTag) { oneWayRoad = value.Equals(TagConstants.YesValue); } } reader.Read(); } if (missingNodes) { // TODO: Error/Trace output // if Way xxx has incomplete nodes. At least one node was missing in the data. } for (int i = 0; i < way.Count - 1; i++) { Vertex v1 = way[i]; graph.AddVertex(v1); Vertex v2 = way[i + 1]; graph.AddVertex(v2); //short vertexCategory = (short)category; float weight = costCalculator.CalculateCosts(v1, v2, category); if (oneWayRoad) { Edge edge = new Edge(v1, v2, weight); graph.AddEdge(edge); } else { Edge edgeForward = new Edge(v1, v2, weight); graph.AddEdge(edgeForward); Edge edgeBackward = new Edge(v2, v1, weight); graph.AddEdge(edgeBackward); } } reader.Read(); } reader.Close(); } } private void ReadDataV2() { XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreComments = true; settings.IgnoreWhitespace = true; NameTable nt = new NameTable(); string osmName = nt.Add("osm"); object nodeName = nt.Add("node"); object tagName = nt.Add("tag"); object wayName = nt.Add("way"); string latName = nt.Add("lat"); string lonName = nt.Add("lon"); string idName = nt.Add("id"); object ndName = nt.Add("nd"); string refName = nt.Add("ref"); string kName = nt.Add("k"); string vName = nt.Add("v"); settings.NameTable = nt; string ns = ""; using (XmlReader reader = XmlReader.Create(file.FullName, settings)) { reader.ReadStartElement(osmName, ns); reader.Read(); while (reader.LocalName.Equals(nodeName)) { double lat = XmlConvert.ToDouble(reader.GetAttribute(latName, ns)); double lon = XmlConvert.ToDouble(reader.GetAttribute(lonName, ns)); long id = XmlConvert.ToInt64(reader.GetAttribute(idName, ns)); Vertex v = new Vertex(id, lon, lat); vertices.Add(v.Id, v); reader.Read(); //if (reader.LocalName.Equals(tagName)) { if (ReferenceEquals(tagName, reader.LocalName)) { reader.ReadToFollowing((string)nodeName, ns); } } //while (reader.LocalName.Equals(wayName)) { while (ReferenceEquals(wayName, reader.LocalName)) { List way = new List(); bool missingNodes = false; HighwayType category = HighwayType.null_type; bool oneWayRoad = false; reader.Read(); while (ReferenceEquals(ndName, reader.LocalName) || ReferenceEquals(tagName, reader.LocalName)) { if (reader.LocalName.Equals(ndName)) { long refNodeId = XmlConvert.ToInt64(reader.GetAttribute(refName, ns)); Vertex vertex = GetVertex(refNodeId); if (vertex != null) { way.Add(vertex); } else { missingNodes = true; } } else if (reader.LocalName.Equals(tagName)) { string key = reader.GetAttribute(kName, ns); string value = reader.GetAttribute(vName, ns); if (key == TagConstants.HighwayTagKey) { if (Enum.IsDefined(typeof(HighwayType), value)) { HighwayType ht = (HighwayType)Enum.Parse(typeof(HighwayType), value, true); category = ht; } else { category = HighwayType.null_type; } } else if (key == TagConstants.OneWayTag) { oneWayRoad = value.Equals(TagConstants.YesValue); } } reader.Read(); } if (missingNodes) { // TODO: Error/Trace output // if Way xxx has incomplete nodes. At least one node was missing in the data. } for (int i = 0; i < way.Count - 1; i++) { Vertex v1 = way[i]; graph.AddVertex(v1); Vertex v2 = way[i + 1]; graph.AddVertex(v2); //short vertexCategory = (short)category; float weight = costCalculator.CalculateCosts(v1, v2, category); if (oneWayRoad) { Edge edge = new Edge(v1, v2, weight); graph.AddEdge(edge); } else { Edge edgeForward = new Edge(v1, v2, weight); graph.AddEdge(edgeForward); Edge edgeBackward = new Edge(v2, v1, weight); graph.AddEdge(edgeBackward); } } reader.Read(); } reader.Close(); } } //private float CalculateWeight(Vertex s, Vertex t, HighwayType ht) { // double distanceKms = Utils.LocationDistance(s.Logitude, s.Latitude, t.Logitude, t.Latitude); // double weight = distanceKms; // return (float)weight; //} //private float CalculateWeight(Vertex s, Vertex t, HighwayType ht) { // double distanceKms = Utils.LocationDistance(s.Logitude, s.Latitude, t.Logitude, t.Latitude); // int speedKmH = GetMaxSpeed(ht); // double weight = (distanceKms / speedKmH) * 60; // return (float)weight; //} } }