commit f7edc288c1349da85a1bb12589feaa8964396aa2 Author: C9Glax <13404778+C9Glax@users.noreply.github.com> Date: Thu Feb 2 19:03:00 2023 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.OSMServer/.idea/.gitignore b/.idea/.idea.OSMServer/.idea/.gitignore new file mode 100644 index 0000000..775c767 --- /dev/null +++ b/.idea/.idea.OSMServer/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/contentModel.xml +/modules.xml +/.idea.OSMServer.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.OSMServer/.idea/indexLayout.xml b/.idea/.idea.OSMServer/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.OSMServer/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.OSMServer/.idea/vcs.xml b/.idea/.idea.OSMServer/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.OSMServer/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Importer/Connection.cs b/Importer/Connection.cs new file mode 100644 index 0000000..3f1ed01 --- /dev/null +++ b/Importer/Connection.cs @@ -0,0 +1,42 @@ +namespace OSMServer; + +public class Connection +{ + public Coordinates end { get; } + + private Dictionary tags; + + + public Connection(Coordinates end) + { + this.end = end; + this.tags = new Dictionary(); + } + + public Connection(Coordinates end, Dictionary tags) + { + this.end = end; + this.tags = tags; + } + + public bool AddTag(string key, string value) + { + return this.tags.TryAdd(key, value); + } + + public string? TryGetTagValue(string key) + { + return this.tags.ContainsKey(key) ? this.tags[key] : null; + } + + public bool ContainsTag(string key) + { + return this.tags.ContainsKey(key); + } + + public void UpdateTag(string key, string value) + { + if(!this.AddTag(key, value)) + this.tags[key] = value; + } +} \ No newline at end of file diff --git a/Importer/Coordinates.cs b/Importer/Coordinates.cs new file mode 100644 index 0000000..e752f55 --- /dev/null +++ b/Importer/Coordinates.cs @@ -0,0 +1,27 @@ +using System.Diagnostics; + +namespace OSMServer; + +public class Coordinates +{ + public float lat { get; } + public float lon { get; } + + public Coordinates(float lat, float lon) + { + this.lat = lat; + this.lon = lon; + } + + public uint GetHash() + { + return Convert.ToUInt32((this.lat * 10000f + this.lon) * 10000f); + } + + public uint GetRegionHash() + { + float latRegion = this.lat % Importer.regionSize; + float lonRegion = this.lon % Importer.regionSize; + return new Coordinates(latRegion, lonRegion).GetHash(); + } +} \ No newline at end of file diff --git a/Importer/Importer.cs b/Importer/Importer.cs new file mode 100644 index 0000000..4060797 --- /dev/null +++ b/Importer/Importer.cs @@ -0,0 +1,138 @@ +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); + } +} \ No newline at end of file diff --git a/Importer/Importer.csproj b/Importer/Importer.csproj new file mode 100644 index 0000000..7a4eeea --- /dev/null +++ b/Importer/Importer.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + OSMServer + + + + + + + diff --git a/Importer/Node.cs b/Importer/Node.cs new file mode 100644 index 0000000..9a91eed --- /dev/null +++ b/Importer/Node.cs @@ -0,0 +1,21 @@ +namespace OSMServer; + +public class Node : Coordinates +{ + private HashSet connections = new HashSet(); + + public Node(float lat, float lon) : base(lat, lon) + { + + } + + public void AddConnection(Connection connection) + { + this.connections.Add(connection); + } + + public Connection[] GetConnections() + { + return this.connections.ToArray(); + } +} \ No newline at end of file diff --git a/Importer/Region.cs b/Importer/Region.cs new file mode 100644 index 0000000..baaf5fc --- /dev/null +++ b/Importer/Region.cs @@ -0,0 +1,33 @@ +namespace OSMServer; + +public class Region +{ + private Dictionary nodesInRegion = new Dictionary(); + public uint regionHash; + + public Region(uint regionHash) + { + this.regionHash = this.regionHash; + } + + public Region(Coordinates regionCoordinates) + { + this.regionHash = regionCoordinates.GetRegionHash(); + } + + public Region(ulong nodeId, Node firstNode) + { + this.regionHash = firstNode.GetRegionHash(); + this.nodesInRegion.Add(nodeId, firstNode); + } + + public void AddNode(ulong nodeId, Node node) + { + this.nodesInRegion.Add(nodeId, node); + } + + public Node[] GetNodes() + { + return this.nodesInRegion.Values.ToArray(); + } +} \ No newline at end of file diff --git a/Importer/RegionManager.cs b/Importer/RegionManager.cs new file mode 100644 index 0000000..9af454d --- /dev/null +++ b/Importer/RegionManager.cs @@ -0,0 +1,28 @@ +namespace OSMServer; + +public class RegionManager +{ + private Dictionary regions; + + public RegionManager() + { + this.regions = new Dictionary(); + } + + public Region GetRegion(Coordinates coordinates) + { + if(this.regions.ContainsKey(coordinates.GetRegionHash())) + return this.regions[coordinates.GetRegionHash()]; + else + { + Region newRegion = new Region(coordinates.GetRegionHash()); + this.regions.Add(newRegion.regionHash, newRegion); + return newRegion; + } + } + + public Region[] GetAllRegions() + { + return this.regions.Values.ToArray(); + } +} \ No newline at end of file diff --git a/OSMServer.sln b/OSMServer.sln new file mode 100644 index 0000000..7393a17 --- /dev/null +++ b/OSMServer.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSMServer", "OSMServer\OSMServer.csproj", "{BE5C111D-AD61-433A-AE7E-F02B78551347}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BE5C111D-AD61-433A-AE7E-F02B78551347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE5C111D-AD61-433A-AE7E-F02B78551347}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE5C111D-AD61-433A-AE7E-F02B78551347}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE5C111D-AD61-433A-AE7E-F02B78551347}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/OSMServer.sln.DotSettings.user b/OSMServer.sln.DotSettings.user new file mode 100644 index 0000000..8cf0f80 --- /dev/null +++ b/OSMServer.sln.DotSettings.user @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Server/Server.cs b/Server/Server.cs new file mode 100644 index 0000000..f657f4d --- /dev/null +++ b/Server/Server.cs @@ -0,0 +1,9 @@ +namespace OSMServer; + +public class Server +{ + public Server() + { + Importer.Split("/home/glax/Downloads/bayern-latest.osm.bz2", "/home/glax/Downloads/split"); + } +} \ No newline at end of file diff --git a/Server/Server.csproj b/Server/Server.csproj new file mode 100644 index 0000000..2b14c81 --- /dev/null +++ b/Server/Server.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + +