230 lines
8.6 KiB
C#
230 lines
8.6 KiB
C#
namespace OSMDatastructure;
|
|
|
|
public static class ByteConverter
|
|
{
|
|
#region Node
|
|
/*
|
|
* Node Byteform:
|
|
* +-------------------------------+
|
|
* | Latitude | Longitude | ConnectionSize| connection |
|
|
* |---------------+---------------+---------------+---------------+
|
|
* | 4 bytes | 4 bytes | 4 bytes | ConnectionSize|
|
|
* | float | float | int | Connection |
|
|
* +---------------+---------------+
|
|
*/
|
|
|
|
public static byte[] GetBytes(Node node)
|
|
{
|
|
byte[] latitudeBytes = BitConverter.GetBytes(node.lat);
|
|
byte[] longitudeBytes = BitConverter.GetBytes(node.lon);
|
|
|
|
Connection[] connections = node.GetConnections();
|
|
Dictionary<byte[], byte[]> connectionsBytes = new ();
|
|
int byteArraySize = latitudeBytes.Length + longitudeBytes.Length;
|
|
|
|
foreach (Connection connection in connections)
|
|
{
|
|
byte[] connectionBytes = ByteConverter.GetBytes(connection);
|
|
byte[] connectionSizeBytes = BitConverter.GetBytes(connectionBytes.Length);
|
|
connectionsBytes.Add(connectionSizeBytes, connectionBytes);
|
|
byteArraySize += connectionSizeBytes.Length + connectionBytes.Length;
|
|
}
|
|
|
|
byte[] retByteArray = new byte[byteArraySize];
|
|
int offset = 0;
|
|
|
|
Array.Copy(latitudeBytes, 0, retByteArray, offset, latitudeBytes.Length);
|
|
offset += latitudeBytes.Length;
|
|
|
|
Array.Copy(longitudeBytes, 0, retByteArray, offset, longitudeBytes.Length);
|
|
offset += longitudeBytes.Length;
|
|
|
|
foreach (KeyValuePair<byte[], byte[]> connectionBytes in connectionsBytes)
|
|
{
|
|
Array.Copy(connectionBytes.Key, 0, retByteArray, offset, connectionBytes.Key.Length);
|
|
offset += connectionBytes.Key.Length;
|
|
|
|
Array.Copy(connectionBytes.Value, 0, retByteArray, offset, connectionBytes.Value.Length);
|
|
offset += connectionBytes.Value.Length;
|
|
}
|
|
|
|
return retByteArray;
|
|
}
|
|
|
|
public static Node ToNode(byte[] bytes)
|
|
{
|
|
int offset = 0;
|
|
float lat = BitConverter.ToSingle(bytes, offset);
|
|
offset += sizeof(float);
|
|
|
|
float lon = BitConverter.ToSingle(bytes, offset);
|
|
offset += sizeof(float);
|
|
|
|
Node retNode = new Node(lat, lon);
|
|
Console.WriteLine("Node Lat: {0} Lon: {1}", lat, lon);
|
|
|
|
while (offset < bytes.Length)
|
|
{
|
|
int size = BitConverter.ToInt32(bytes, offset);
|
|
offset += sizeof(int);
|
|
|
|
byte[] connectionBytes = new byte[size];
|
|
Array.Copy(bytes, offset, connectionBytes, 0, size);
|
|
retNode.AddConnection(ByteConverter.ToConnection(connectionBytes));
|
|
offset += connectionBytes.Length;
|
|
}
|
|
|
|
return retNode;
|
|
}
|
|
#endregion
|
|
|
|
#region Connection
|
|
/*
|
|
* Connection Byteform:
|
|
* +---------------+---------------+
|
|
* | endId | endLatitude | endLongitude | tagBytes | tag | value |
|
|
* |---------------+---------------+---------------+---------------+---------------+---------------+
|
|
* | 8 bytes | 4 bytes | 4 bytes | 4 bytes | 1 byte | 1 byte |
|
|
* | ulong | float | float | int | | |
|
|
* +---------------+---------------+
|
|
*/
|
|
|
|
public static byte[] GetBytes(Connection connection)
|
|
{
|
|
byte[] endIdBytes = BitConverter.GetBytes(connection.endNodeId);
|
|
byte[] endLatBytes = BitConverter.GetBytes(connection.endNodeCoordinates.lat);
|
|
byte[] endLonBytes = BitConverter.GetBytes(connection.endNodeCoordinates.lon);
|
|
|
|
Dictionary<Connection.tagType, object> connectionTags = connection.GetTags();
|
|
byte[] tagBytes = BitConverter.GetBytes(connectionTags.Count * 2);
|
|
|
|
int byteArraySize = endIdBytes.Length + endLatBytes.Length + endLonBytes.Length + tagBytes.Length + connectionTags.Count * 2;
|
|
byte[] retBytes = new byte[byteArraySize];
|
|
int offset = 0;
|
|
|
|
Array.Copy(endIdBytes, 0, retBytes, offset, endIdBytes.Length);
|
|
offset += endIdBytes.Length;
|
|
|
|
Array.Copy(endLatBytes, 0, retBytes, offset, endLatBytes.Length);
|
|
offset += endLatBytes.Length;
|
|
|
|
Array.Copy(endLonBytes, 0 , retBytes, offset, endLonBytes.Length);
|
|
offset += endLonBytes.Length;
|
|
|
|
Array.Copy(tagBytes, 0, retBytes, offset, tagBytes.Length);
|
|
offset += tagBytes.Length;
|
|
|
|
foreach (KeyValuePair<Connection.tagType, object> tagKv in connectionTags)
|
|
{
|
|
retBytes[offset] = (byte)tagKv.Key;
|
|
offset++;
|
|
retBytes[offset] = (byte)tagKv.Value;
|
|
offset++;
|
|
}
|
|
|
|
return retBytes;
|
|
}
|
|
|
|
public static Connection ToConnection(byte[] bytes)
|
|
{
|
|
int offset = 0;
|
|
ulong endId = BitConverter.ToUInt64(bytes, offset);
|
|
offset += sizeof(ulong);
|
|
|
|
float endLat = BitConverter.ToSingle(bytes, offset);
|
|
offset += sizeof(float);
|
|
|
|
float endLon = BitConverter.ToSingle(bytes, offset);
|
|
offset += sizeof(float);
|
|
|
|
Connection retConnection = new Connection(endId, new Coordinates(endLat, endLon));
|
|
|
|
int tagBytes = BitConverter.ToInt32(bytes, offset);
|
|
Console.WriteLine("Connection EndId: {0} Lat: {1} Lon: {2} Tags: {3}", endId, endLat, endLon, tagBytes / 2);
|
|
offset += sizeof(int);
|
|
while (offset < bytes.Length)
|
|
{
|
|
byte key = bytes[offset];
|
|
byte value = bytes[offset + 1];
|
|
retConnection.AddTag(key, value);
|
|
offset += 2;
|
|
}
|
|
|
|
return retConnection;
|
|
}
|
|
#endregion
|
|
|
|
#region Region
|
|
/*
|
|
* Region Byteform:
|
|
* +---------------+---------------+---------------+
|
|
* | regionHash | nodeBytes | nodeId | node |
|
|
* |---------------+---------------+---------------+---------------+
|
|
* | 8 bytes | 4 bytes | 8 bytes | nodeBytes |
|
|
* | ulong | int | ulong | Node |
|
|
* +---------------+---------------+---------------+
|
|
*/
|
|
|
|
public static byte[] GetBytes(Region region)
|
|
{
|
|
byte[] regionHashBytes = BitConverter.GetBytes(region.regionHash);
|
|
int byteArraySize = regionHashBytes.Length;
|
|
|
|
Dictionary<byte[], byte[]> nodesBytes = new();
|
|
foreach(KeyValuePair<ulong, Node> nodeKv in region.GetNodes())
|
|
{
|
|
byte[] nodeIdBytes = BitConverter.GetBytes(nodeKv.Key);
|
|
byte[] nodeBytes = GetBytes(nodeKv.Value);
|
|
nodesBytes.Add(nodeIdBytes, nodeBytes);
|
|
byteArraySize += sizeof(int) + nodeIdBytes.Length + nodeBytes.Length;
|
|
}
|
|
|
|
byte[] retBytes = new byte[byteArraySize];
|
|
int offset = 0;
|
|
|
|
Array.Copy(regionHashBytes, 0, retBytes, offset, regionHashBytes.Length);
|
|
offset += regionHashBytes.Length;
|
|
|
|
foreach (KeyValuePair<byte[], byte[]> nodeByteKv in nodesBytes)
|
|
{
|
|
Array.Copy(BitConverter.GetBytes(nodeByteKv.Value.Length), 0, retBytes, offset, sizeof(int));
|
|
offset += sizeof(int);
|
|
|
|
Array.Copy(nodeByteKv.Key, 0, retBytes, offset, nodeByteKv.Key.Length);
|
|
offset += nodeByteKv.Key.Length;
|
|
|
|
Array.Copy(nodeByteKv.Value, 0, retBytes, offset, nodeByteKv.Value.Length);
|
|
offset += nodeByteKv.Value.Length;
|
|
}
|
|
|
|
return retBytes;
|
|
}
|
|
|
|
public static Region ToRegion(byte[] bytes)
|
|
{
|
|
int offset = 0;
|
|
ulong regionHash = BitConverter.ToUInt64(bytes, offset);
|
|
offset += sizeof(ulong);
|
|
|
|
Console.WriteLine("Region: {0}", regionHash);
|
|
|
|
Region retRegion = new Region(regionHash);
|
|
|
|
while (offset < bytes.Length)
|
|
{
|
|
int nodeBytesAmount = BitConverter.ToInt32(bytes, offset);
|
|
offset += sizeof(int);
|
|
|
|
ulong nodeId = BitConverter.ToUInt64(bytes, offset);
|
|
offset += sizeof(ulong);
|
|
|
|
byte[] nodeBytes = new byte[nodeBytesAmount];
|
|
Array.Copy(bytes, offset, nodeBytes, 0, nodeBytesAmount);
|
|
retRegion.AddNode(nodeId, ByteConverter.ToNode(nodeBytes));
|
|
offset += nodeBytes.Length;
|
|
}
|
|
|
|
return retRegion;
|
|
}
|
|
#endregion
|
|
} |