OSMServer/Importer/Importer.cs
2023-02-02 19:03:00 +01:00

138 lines
4.8 KiB
C#

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<ulong> nodesToImport = ReturnGraphNodes(XmlReader.Create(xmlFileStream));
xmlFileStream.Position = 0;
XmlReader xmlReader = XmlReader.Create(xmlFileStream);
Dictionary<ulong, Node> nodes = new Dictionary<ulong, Node>();
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<ulong> nodesInWay = new HashSet<ulong>();
Dictionary<string, string> tags = new Dictionary<string, string>();
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<ulong> ReturnGraphNodes(XmlReader xmlReader)
{
HashSet<ulong> retSet = new HashSet<ulong>();
while (xmlReader.ReadToFollowing("way"))
{
XmlReader wayReader = xmlReader.ReadSubtree();
HashSet<ulong> tmpList = new HashSet<ulong>();
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<ulong, Node> nodes, ulong[] nodeIds,
Dictionary<string, string> 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);
}
}