using System.Xml; using Newtonsoft.Json; namespace OSMServer; public class Importer { public const float regionSize = 0.01f; public static void Split(string xmlFilePath, string outputFolderPath) { if (!File.Exists(xmlFilePath)) throw new FileNotFoundException(); FileStream xmlFileStream = File.OpenRead(xmlFilePath); HashSet nodesToImport = ReturnGraphNodes(XmlReader.Create(xmlFileStream)); xmlFileStream.Position = 0; XmlReader xmlReader = XmlReader.Create(xmlFileStream); Dictionary nodes = new Dictionary(); RegionManager regionManager = new RegionManager(); while (xmlReader.ReadToFollowing("node")) { ulong id = Convert.ToUInt64(xmlReader.GetAttribute("id")); if (nodesToImport.Contains(id)) { float lat = Convert.ToSingle(xmlReader.GetAttribute("lat")!.Replace('.', ',')); float lon = Convert.ToSingle(xmlReader.GetAttribute("lon")!.Replace('.', ',')); Node newNode = new Node(lat, lon); nodes.Add(id, newNode); regionManager.GetRegion(newNode).AddNode(id, newNode); } } xmlReader.Close(); xmlFileStream.Position = 0; xmlReader = XmlReader.Create(xmlFileStream); while (xmlReader.ReadToFollowing("way")) { XmlReader wayReader = xmlReader.ReadSubtree(); HashSet nodesInWay = new HashSet(); Dictionary tags = new Dictionary(); while (wayReader.Read()) { if (wayReader.IsStartElement() && wayReader.Name.Equals("nd")) { nodesInWay.Add(Convert.ToUInt64(wayReader.GetAttribute("ref"))); } else if (wayReader.IsStartElement() && wayReader.Name.Equals("tag")) { tags.Add(wayReader.GetAttribute("k")!, wayReader.GetAttribute("v")!); } } if (tags.ContainsKey("highway")) { AddConnections(nodes, nodesInWay.ToArray(), tags); } } foreach(Region region in regionManager.GetAllRegions()) WriteRegion(region, outputFolderPath); } private static HashSet ReturnGraphNodes(XmlReader xmlReader) { HashSet retSet = new HashSet(); while (xmlReader.ReadToFollowing("way")) { XmlReader wayReader = xmlReader.ReadSubtree(); HashSet tmpList = new HashSet(); bool addNodes = false; while (wayReader.Read()) { if (wayReader.IsStartElement()) { if (wayReader.Name.Equals("nd")) { tmpList.Add(Convert.ToUInt64(wayReader.GetAttribute("ref"))); } else if (wayReader.Name.Equals("tag")) { if (wayReader.GetAttribute("v")!.Equals("highway")) addNodes = true; } } } if(addNodes) retSet.UnionWith(tmpList); } return retSet; } private static void AddConnections(Dictionary nodes, ulong[] nodeIds, Dictionary tags) { string oneWayString = tags.ContainsKey("oneway") ? tags["oneway"] : "no"; bool oneWay = false; bool forward = true; switch (oneWayString) { case "yes": oneWay = true; break; case "-1": forward = false; break; } for (int i = 0; i < nodeIds.Length - 1; i++) { if (oneWay) { nodes[nodeIds[i]].AddConnection(new Connection(nodes[nodeIds[i + 1]], tags)); nodes[nodeIds[i + 1]].AddConnection(new Connection(nodes[nodeIds[i]], tags)); } else if (forward) { nodes[nodeIds[i]].AddConnection(new Connection(nodes[nodeIds[i + 1]], tags)); } else { nodes[nodeIds[i + 1]].AddConnection(new Connection(nodes[nodeIds[i]], tags)); } } } private static void WriteRegion(Region region, string outputFolderPath) { if (!Directory.Exists(outputFolderPath)) Directory.CreateDirectory(outputFolderPath); string jsonString = JsonConvert.SerializeObject(region); string fileName = region.regionHash.ToString(); File.WriteAllText(Path.Combine(outputFolderPath, fileName), jsonString); } }