138 lines
4.8 KiB
C#
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);
|
||
|
}
|
||
|
}
|