Complete rewrite of XmlImporter.cs
This commit is contained in:
parent
d7b084659a
commit
aceecee07e
171
Server/XmlImporter.cs
Normal file
171
Server/XmlImporter.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using System.Globalization;
|
||||
using System.Xml;
|
||||
using OSMDatastructure;
|
||||
using OSMImporter;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public static class XmlImporter
|
||||
{
|
||||
private static readonly XmlReaderSettings readerSettings = new()
|
||||
{
|
||||
IgnoreWhitespace = true,
|
||||
IgnoreComments = true
|
||||
};
|
||||
|
||||
public static HashSet<OsmNode> ImportXml(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException();
|
||||
|
||||
Console.WriteLine(string.Format("[{0}] Getting highwayNodeIds...", DateTime.Now.ToLocalTime()));
|
||||
FileStream xmlFileStream = new FileStream(filePath, FileMode.Open);
|
||||
HashSet<ulong> requiredNodeIds = GetHighwayNodeIds(XmlReader.Create(xmlFileStream, readerSettings));
|
||||
xmlFileStream.Position = 0;
|
||||
|
||||
Console.WriteLine(string.Format("[{0}] Importing Nodes...", DateTime.Now.ToLocalTime()));
|
||||
Dictionary<ulong, OsmNode> nodes =
|
||||
GetHighwayNodesFromIds(XmlReader.Create(xmlFileStream, readerSettings), requiredNodeIds);
|
||||
requiredNodeIds.Clear();
|
||||
xmlFileStream.Position = 0;
|
||||
|
||||
Console.WriteLine(string.Format("[{0}] Importing Ways...", DateTime.Now.ToLocalTime()));
|
||||
HashSet<OsmNode> retNodes = ConnectNodes(XmlReader.Create(xmlFileStream, readerSettings), nodes);
|
||||
nodes.Clear();
|
||||
|
||||
return retNodes;
|
||||
}
|
||||
|
||||
public static HashSet<Region> SplitIntoRegions(HashSet<OsmNode> nodes)
|
||||
{
|
||||
Console.WriteLine(string.Format("[{0}] Splitting into Regions...", DateTime.Now.ToLocalTime()));
|
||||
Dictionary<ulong, Region> retRegions = new();
|
||||
foreach (OsmNode node in nodes)
|
||||
{
|
||||
ulong regionHash = node.coordinates.GetRegionHash();
|
||||
if(retRegions.ContainsKey(regionHash))
|
||||
{
|
||||
retRegions[regionHash].nodes.Add(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
Region newRegion = new Region(regionHash);
|
||||
newRegion.nodes.Add(node);
|
||||
retRegions.Add(regionHash, newRegion);
|
||||
}
|
||||
}
|
||||
|
||||
return retRegions.Values.ToHashSet();
|
||||
}
|
||||
|
||||
private static readonly NumberFormatInfo decimalInfo = new()
|
||||
{
|
||||
NumberDecimalSeparator = "."
|
||||
};
|
||||
private static HashSet<ulong> GetHighwayNodeIds(XmlReader xmlReader)
|
||||
{
|
||||
HashSet<ulong> retSet = new();
|
||||
bool isHighway;
|
||||
HashSet<ulong> currentIds = new();
|
||||
while (xmlReader.ReadToFollowing("way"))
|
||||
{
|
||||
isHighway = false;
|
||||
currentIds.Clear();
|
||||
XmlReader wayReader = xmlReader.ReadSubtree();
|
||||
while (wayReader.Read())
|
||||
{
|
||||
if (xmlReader.Name == "tag" && xmlReader.GetAttribute("k")!.Equals("highway"))
|
||||
{
|
||||
isHighway = true;
|
||||
}
|
||||
else if (xmlReader.Name == "nd")
|
||||
{
|
||||
try
|
||||
{
|
||||
currentIds.Add(Convert.ToUInt64(xmlReader.GetAttribute("ref")));
|
||||
}
|
||||
catch (FormatException) { };
|
||||
}
|
||||
}
|
||||
if (isHighway)
|
||||
{
|
||||
retSet.UnionWith(currentIds);
|
||||
}
|
||||
wayReader.Close();
|
||||
}
|
||||
xmlReader.Close();
|
||||
|
||||
return retSet;
|
||||
}
|
||||
|
||||
private static Dictionary<ulong, OsmNode> GetHighwayNodesFromIds(XmlReader xmlReader, HashSet<ulong> ids)
|
||||
{
|
||||
Dictionary<ulong, OsmNode> retDict = new();
|
||||
|
||||
while (xmlReader.ReadToFollowing("node"))
|
||||
{
|
||||
ulong id = Convert.ToUInt64(xmlReader.GetAttribute("id"));
|
||||
if (ids.Contains(id))
|
||||
{
|
||||
float lat = Convert.ToSingle(xmlReader.GetAttribute("lat")!, decimalInfo);
|
||||
float lon = Convert.ToSingle(xmlReader.GetAttribute("lon")!, decimalInfo);
|
||||
retDict.Add(id, new OsmNode(lat, lon));
|
||||
}
|
||||
}
|
||||
xmlReader.Close();
|
||||
|
||||
return retDict;
|
||||
}
|
||||
|
||||
private static HashSet<OsmNode> ConnectNodes(XmlReader xmlReader, Dictionary<ulong, OsmNode> dict)
|
||||
{
|
||||
while (xmlReader.ReadToFollowing("way"))
|
||||
{
|
||||
Dictionary<OsmEdge.tagType, object> tags = new();
|
||||
List<ulong> wayNodeIds = new();
|
||||
XmlReader wayReader = xmlReader.ReadSubtree();
|
||||
while (wayReader.Read())
|
||||
{
|
||||
if (xmlReader.Name == "tag")
|
||||
{
|
||||
KeyValuePair<OsmEdge.tagType, object> tag =
|
||||
OsmEdge.ConvertToTag(wayReader.GetAttribute("k")!, wayReader.GetAttribute("v")!);
|
||||
tags.TryAdd(tag.Key, tag.Value);
|
||||
}
|
||||
else if (xmlReader.Name == "nd")
|
||||
{
|
||||
wayNodeIds.Add(Convert.ToUInt64(xmlReader.GetAttribute("ref")));
|
||||
}
|
||||
}
|
||||
if (tags.ContainsKey(OsmEdge.tagType.highway))
|
||||
{
|
||||
ulong[] ids = wayNodeIds.Where(dict.ContainsKey).ToArray();
|
||||
for (int i = 0; i < ids.Length - 1; i++)
|
||||
{
|
||||
OsmNode n1 = dict[ids[i]];
|
||||
OsmNode n2 = dict[ids[i + 1]];
|
||||
if (tags.ContainsKey(OsmEdge.tagType.oneway) && (bool)tags[OsmEdge.tagType.oneway])
|
||||
{
|
||||
if (tags.ContainsKey(OsmEdge.tagType.forward) && !(bool)tags[OsmEdge.tagType.forward])
|
||||
{
|
||||
n2.edges.Add(new OsmEdge(n1.coordinates, tags));
|
||||
}
|
||||
else
|
||||
{
|
||||
n1.edges.Add(new OsmEdge(n2.coordinates, tags));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n1.edges.Add(new OsmEdge(n2.coordinates, tags));
|
||||
n2.edges.Add(new OsmEdge(n1.coordinates, tags));
|
||||
}
|
||||
}
|
||||
}
|
||||
wayReader.Close();
|
||||
}
|
||||
xmlReader.Close();
|
||||
|
||||
return dict.Values.ToHashSet();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user