From f31b1b577b0476abe7924b857b7ba39098974df8 Mon Sep 17 00:00:00 2001 From: C9Glax <13404778+C9Glax@users.noreply.github.com> Date: Fri, 3 Feb 2023 00:02:04 +0100 Subject: [PATCH] Import and Export of Regions --- OSMImporter/Connection.cs | 66 +++++++++++++++++++++++++++------ OSMImporter/Importer.cs | 75 +++++++++++++++++++++++++++++++++++++- OSMImporter/Node.cs | 34 +++++++++++++---- OSMImporter/Region.cs | 4 +- OSMImporter/highwayType.cs | 10 ++--- Server/Server.cs | 5 ++- 6 files changed, 165 insertions(+), 29 deletions(-) diff --git a/OSMImporter/Connection.cs b/OSMImporter/Connection.cs index c9ab581..bd78c8b 100644 --- a/OSMImporter/Connection.cs +++ b/OSMImporter/Connection.cs @@ -6,7 +6,7 @@ namespace OSMImporter private readonly Dictionary _tags = new Dictionary(); - public enum tagType + public enum tagType : byte { highway, oneway, footway, sidewalk, cycleway, busway, forward, maxspeed, unknown } @@ -37,16 +37,16 @@ namespace OSMImporter case "oneway": if (value.Equals("yes", StringComparison.CurrentCultureIgnoreCase)) { - this._tags.Add(tagType.oneway, true); + this._tags.Add(tagType.oneway, (byte)1); } else if (value.Equals("no", StringComparison.CurrentCultureIgnoreCase)) { - this._tags.Add(tagType.oneway, false); + this._tags.Add(tagType.oneway, (byte)0); } else if (value.Equals("reversible", StringComparison.CurrentCultureIgnoreCase)) { - this._tags.Add(tagType.oneway, true); - this._tags.Add(tagType.forward, false); + this._tags.Add(tagType.oneway, (byte)1); + this._tags.Add(tagType.forward, (byte)0); } break; case "sidewalk": @@ -65,7 +65,35 @@ namespace OSMImporter this._tags.Add(tagType.maxspeed, Convert.ToByte(value)); break; default: - this._tags.Add(tagType.unknown, value); + Console.WriteLine("Unknown Tag: {0} Value: {1}", key, value); + break; + } + } + + public void AddTag(byte tag, byte value) + { + switch ((tagType)tag) + { + case tagType.highway: + this._tags.Add(tagType.highway, (highwayType)value); + break; + case tagType.footway: + this._tags.Add(tagType.footway, (footwayType)value); + break; + case tagType.oneway: + this._tags.Add(tagType.oneway, value); + break; + case tagType.sidewalk: + this._tags.Add(tagType.sidewalk, (sidewalkSide)value); + break; + case tagType.cycleway: + this._tags.Add(tagType.cycleway, (cyclewayType)value); + break; + case tagType.busway: + this._tags.Add(tagType.busway, (buswayType)value); + break; + case tagType.maxspeed: + this._tags.Add(tagType.maxspeed, value); break; } } @@ -89,12 +117,28 @@ namespace OSMImporter return null; } } - - public byte[] ToByte() //TODO Current Size sizeof(ulong) + + /* + * Value 1: endId (4bytes) + * Value 2: tagsCount (1byte) + * Value x: tag + value (2bytes) + */ + public byte[] ToByte() { - //TODO Tags - byte[] ret = new byte[sizeof(ulong)]; - Buffer.BlockCopy(new []{ this.endNodeId }, 0, ret, 0, ret.Length ); + byte[] ret = new byte[sizeof(ulong) + 1 + this._tags.Count * 2]; + + int offset = 0; + Buffer.BlockCopy(new []{ this.endNodeId }, 0, ret, offset, sizeof(ulong) ); + offset += sizeof(ulong); + + byte tagsAmount = Convert.ToByte(this._tags.Count); + Buffer.SetByte(ret, offset++, tagsAmount); + + foreach (KeyValuePair tag in this._tags) + { + Buffer.BlockCopy(new byte[]{(byte)tag.Key, (byte)tag.Value}, 0, ret,offset, 2); + offset += 2; + } return ret; } } diff --git a/OSMImporter/Importer.cs b/OSMImporter/Importer.cs index f3c5f67..9aa5b60 100644 --- a/OSMImporter/Importer.cs +++ b/OSMImporter/Importer.cs @@ -19,6 +19,68 @@ namespace OSMImporter NumberDecimalSeparator = "." }; + public static Region ImportRegion(string folderPath, Coordinates coordinates) + { + string fullPath = Path.Combine(folderPath, coordinates.GetRegionHash().ToString()); + Console.WriteLine(fullPath); + Region retRegion = new Region(coordinates); + if (!File.Exists(fullPath)) + return retRegion; + + FileStream fileStream = new FileStream(fullPath, FileMode.Open); + + while (fileStream.Position < fileStream.Length) + { + byte[] nodeIdBytes = new byte[sizeof(ulong)]; + fileStream.ReadExactly(nodeIdBytes,0,nodeIdBytes.Length); + ulong[] nodeId = new ulong[1]; + Buffer.BlockCopy(nodeIdBytes,0,nodeId,0,nodeIdBytes.Length); + byte[] latBytes = new byte[sizeof(float)]; + fileStream.ReadExactly(latBytes, 0, latBytes.Length); + byte[] lonBytes = new byte[sizeof(float)]; + fileStream.ReadExactly(lonBytes, 0, latBytes.Length); + + Node newNode = NodeFromBytes(latBytes, lonBytes); + retRegion.AddNode(nodeId[0], newNode); + + byte connectionsAmount = Convert.ToByte(fileStream.ReadByte()); + for (byte connectionInt = 0; connectionInt < connectionsAmount; connectionInt++) + { + byte[] endIdBytes = new byte[sizeof(ulong)]; + fileStream.ReadExactly(endIdBytes, 0, endIdBytes.Length); + Connection connection = ConnectionFromByte(endIdBytes); + newNode.AddConnection(connection); + + byte tagsAmount = Convert.ToByte(fileStream.ReadByte()); + for (byte tagInt = 0; tagInt < tagsAmount; tagInt++) + { + byte keyByte = Convert.ToByte(fileStream.ReadByte()); + byte valueByte = Convert.ToByte(fileStream.ReadByte()); + connection.AddTag(keyByte, valueByte); + } + } + + } + fileStream.Close(); + return retRegion; + } + + private static Node NodeFromBytes(byte[] latByte, byte[] lonByte) + { + float[] lat = new float[1]; + float[] lon = new float[1]; + Buffer.BlockCopy(latByte, 0, lat, 0, latByte.Length); + Buffer.BlockCopy(lonByte, 0, lon, 0, lonByte.Length); + return new Node(lat[0], lon[0]); + } + + private static Connection ConnectionFromByte(byte[] endIdByte) + { + ulong[] endId = new ulong[1]; + Buffer.BlockCopy(endIdByte, 0, endId, 0, endIdByte.Length); + return new Connection(endId[0]); + } + public static void Split(string xmlFilePath, string outputFolderPath) { if (!File.Exists(xmlFilePath)) @@ -168,6 +230,10 @@ namespace OSMImporter } } + /* + * Value x: nodeId (4bytes) + * Value x+1: Node (xbytes) + */ private static void WriteRegion(Region region, string outputFolderPath) { if (!Directory.Exists(outputFolderPath)) @@ -177,9 +243,14 @@ namespace OSMImporter if (!File.Exists(fullPath)) File.Create(fullPath).Close(); FileStream fileStream = new FileStream(fullPath, FileMode.Append); - foreach (Node node in region.GetNodes()) + foreach (KeyValuePair nodeKeyValuePair in region.GetNodes()) { - byte[] nodeByte = node.ToByte(); + byte[] nodeByte = nodeKeyValuePair.Value.ToByte(); + byte[] nodeIdByte = new byte[sizeof(long)]; + ulong[] nodeId = new ulong[]{nodeKeyValuePair.Key}; + Buffer.BlockCopy(nodeId,0,nodeIdByte,0,nodeIdByte.Length); + + fileStream.Write(nodeIdByte); fileStream.Write(nodeByte, 0, nodeByte.Length ); } fileStream.Close(); diff --git a/OSMImporter/Node.cs b/OSMImporter/Node.cs index b63ef74..f56b129 100644 --- a/OSMImporter/Node.cs +++ b/OSMImporter/Node.cs @@ -24,19 +24,37 @@ namespace OSMImporter * Value 1: Latitude (4bytes) * Value 2: Longitude (4bytes) * Value 3: Connections-Count (1 byte) - * Value x: Connection (8bytes) //TODO + * Value x: Connection */ public byte[] ToByte() { + long countBytes = 0; float[] coords = { this.lat, this.lon }; - byte[] ret = new byte[sizeof(float) * coords.Length + 1 + _connections.Count * sizeof(ulong)]; - Buffer.BlockCopy(coords, 0, ret, 0, sizeof(float) * coords.Length ); - byte countConnections = Convert.ToByte(_connections.Count); - Connection[] conns = this._connections.ToArray(); - for (int i = 0; i < conns.Length; i++) + countBytes += sizeof(float) * 2; + + HashSet byteConnections = new(); + foreach (Connection connection in this._connections) { - byte[] connection = conns[i].ToByte(); - Buffer.BlockCopy(connection, 0, ret, sizeof(float) * coords.Length + 1 + i * connection.Length, connection.Length); + byte[] connectionBytes = connection.ToByte(); + byteConnections.Add(connectionBytes); + countBytes += connectionBytes.Length; + } + + byte connectionsAmount = Convert.ToByte(byteConnections.Count); + countBytes++; + + int offset = 0; + byte[] ret = new byte[countBytes]; + Buffer.BlockCopy(coords, 0, ret, offset, sizeof(float) * 2); + offset += sizeof(float) * 2; + + Buffer.SetByte(ret, offset, connectionsAmount); + offset++; + + foreach (byte[] connection in byteConnections) + { + Buffer.BlockCopy(connection, 0, ret, offset, connection.Length); + offset += connection.Length; } return ret; } diff --git a/OSMImporter/Region.cs b/OSMImporter/Region.cs index 66bd70d..8b227d0 100644 --- a/OSMImporter/Region.cs +++ b/OSMImporter/Region.cs @@ -21,9 +21,9 @@ namespace OSMImporter this._nodesInRegion.Add(nodeId, value: node); } - public Node[] GetNodes() + public Dictionary GetNodes() { - return this._nodesInRegion.Values.ToArray(); + return this._nodesInRegion; } } } \ No newline at end of file diff --git a/OSMImporter/highwayType.cs b/OSMImporter/highwayType.cs index cd6a315..58f56d9 100644 --- a/OSMImporter/highwayType.cs +++ b/OSMImporter/highwayType.cs @@ -1,6 +1,6 @@ namespace OSMImporter { - public enum highwayType + public enum highwayType : byte { motorway, trunk, @@ -34,13 +34,13 @@ namespace OSMImporter construction } - public enum footwayType + public enum footwayType : byte { sidewalk, crossing } - public enum cyclewayType + public enum cyclewayType : byte { lane, opposite, @@ -52,7 +52,7 @@ namespace OSMImporter shared_lane } - public enum sidewalkSide + public enum sidewalkSide : byte { both, left, @@ -60,7 +60,7 @@ namespace OSMImporter no } - public enum buswayType + public enum buswayType : byte { lane } diff --git a/Server/Server.cs b/Server/Server.cs index 5ead8ce..93373e9 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -8,6 +8,9 @@ public class Server public static void Main(string[] args) { - Importer.Split("/home/glax/Downloads/oberbayern-latest.osm", "/home/glax/Downloads/split"); + Importer.Split("/home/glax/Downloads/bayern-latest.osm", "/home/glax/Downloads/bayern-latest"); + Region r = Importer.ImportRegion("/home/glax/Downloads/bayern-latest", new Coordinates(47.890f,12.56f)); + foreach(KeyValuePair nodes in r.GetNodes()) + Console.WriteLine(nodes.Key); } } \ No newline at end of file