2023-03-14 17:00:59 +01:00
|
|
|
namespace OSMDatastructure.Graph;
|
2023-02-06 17:32:55 +01:00
|
|
|
|
|
|
|
public class OsmEdge
|
|
|
|
{
|
|
|
|
public Coordinates neighborCoordinates { get; }
|
2023-02-08 18:08:42 +01:00
|
|
|
public readonly Dictionary<tagType, object> tags = new();
|
2023-02-06 17:32:55 +01:00
|
|
|
|
|
|
|
public OsmEdge(float lat, float lon)
|
|
|
|
{
|
|
|
|
this.neighborCoordinates = new Coordinates(lat, lon);
|
|
|
|
this.tags = new();
|
|
|
|
}
|
|
|
|
|
|
|
|
public OsmEdge(Coordinates neighborCoordinates)
|
|
|
|
{
|
|
|
|
this.neighborCoordinates = neighborCoordinates;
|
|
|
|
this.tags = new();
|
2023-02-07 23:52:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public OsmEdge(float lat, float lon, Dictionary<tagType, object> tags)
|
|
|
|
{
|
|
|
|
this.neighborCoordinates = new Coordinates(lat, lon);
|
2023-02-08 18:08:42 +01:00
|
|
|
//To prevent "EMPTY" tags
|
|
|
|
foreach (KeyValuePair<tagType, object> tag in tags)
|
|
|
|
{
|
|
|
|
if(tag.Key != tagType.EMPTY)
|
|
|
|
this.tags.Add(tag.Key, tag.Value);
|
|
|
|
}
|
2023-02-07 23:52:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public OsmEdge(Coordinates neighborCoordinates, Dictionary<tagType, object> tags)
|
|
|
|
{
|
|
|
|
this.neighborCoordinates = neighborCoordinates;
|
2023-02-08 18:08:42 +01:00
|
|
|
//To prevent "EMPTY" tags
|
|
|
|
foreach (KeyValuePair<tagType, object> tag in tags)
|
|
|
|
{
|
|
|
|
if(tag.Key != tagType.EMPTY)
|
|
|
|
this.tags.Add(tag.Key, tag.Value);
|
|
|
|
}
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public enum tagType : byte
|
|
|
|
{
|
2023-02-08 18:08:42 +01:00
|
|
|
highway, oneway, footway, sidewalk, cycleway, busway, forward, maxspeed, name, surface, lanes, access, tracktype, id, EMPTY
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
|
2023-02-08 19:05:13 +01:00
|
|
|
private static readonly Dictionary<wayType, byte> defaultSpeedCar = new() {
|
2023-02-06 17:32:55 +01:00
|
|
|
{ wayType.NONE, 0 },
|
|
|
|
{ wayType.motorway, 110 },
|
|
|
|
{ wayType.trunk, 100 },
|
|
|
|
{ wayType.primary, 80 },
|
|
|
|
{ wayType.secondary, 80 },
|
|
|
|
{ wayType.tertiary, 70 },
|
|
|
|
{ wayType.unclassified, 20 },
|
|
|
|
{ wayType.residential, 10 },
|
|
|
|
{ wayType.motorway_link, 50 },
|
2023-02-08 18:08:42 +01:00
|
|
|
{ wayType.trunk_link, 50 },
|
|
|
|
{ wayType.primary_link, 30 },
|
2023-02-06 17:32:55 +01:00
|
|
|
{ wayType.secondary_link, 25 },
|
|
|
|
{ wayType.tertiary_link, 25 },
|
|
|
|
{ wayType.living_street, 10 },
|
|
|
|
{ wayType.service, 0 },
|
|
|
|
{ wayType.pedestrian, 0 },
|
|
|
|
{ wayType.track, 0 },
|
|
|
|
{ wayType.bus_guideway, 0 },
|
|
|
|
{ wayType.escape, 0 },
|
|
|
|
{ wayType.raceway, 0 },
|
|
|
|
{ wayType.road, 25 },
|
|
|
|
{ wayType.busway, 0 },
|
|
|
|
{ wayType.footway, 0 },
|
|
|
|
{ wayType.bridleway, 0 },
|
|
|
|
{ wayType.steps, 0 },
|
|
|
|
{ wayType.corridor, 0 },
|
|
|
|
{ wayType.path, 0 },
|
|
|
|
{ wayType.cycleway, 0 },
|
|
|
|
{ wayType.construction, 0 }
|
|
|
|
};
|
|
|
|
|
2023-02-08 19:05:13 +01:00
|
|
|
private static readonly Dictionary<wayType, byte> defaultSpeedPedestrian = new() {
|
2023-02-06 17:32:55 +01:00
|
|
|
{ wayType.NONE, 0 },
|
|
|
|
{ wayType.motorway, 0 },
|
|
|
|
{ wayType.trunk, 0 },
|
|
|
|
{ wayType.primary, 0 },
|
|
|
|
{ wayType.secondary, 0 },
|
|
|
|
{ wayType.tertiary, 0 },
|
|
|
|
{ wayType.unclassified, 1 },
|
|
|
|
{ wayType.residential, 3 },
|
|
|
|
{ wayType.motorway_link, 0 },
|
|
|
|
{ wayType.trunk_link, 0 },
|
|
|
|
{ wayType.primary_link, 0 },
|
|
|
|
{ wayType.secondary_link, 0 },
|
|
|
|
{ wayType.tertiary_link, 0 },
|
|
|
|
{ wayType.living_street, 5 },
|
|
|
|
{ wayType.service, 2 },
|
|
|
|
{ wayType.pedestrian, 5 },
|
|
|
|
{ wayType.track, 0 },
|
|
|
|
{ wayType.bus_guideway, 0 },
|
|
|
|
{ wayType.escape, 0 },
|
|
|
|
{ wayType.raceway, 0 },
|
|
|
|
{ wayType.road, 3 },
|
|
|
|
{ wayType.busway, 0 },
|
|
|
|
{ wayType.footway, 4 },
|
|
|
|
{ wayType.bridleway, 1 },
|
|
|
|
{ wayType.steps, 2 },
|
|
|
|
{ wayType.corridor, 3 },
|
|
|
|
{ wayType.path, 4 },
|
|
|
|
{ wayType.cycleway, 2 },
|
|
|
|
{ wayType.construction, 0 }
|
|
|
|
};
|
2023-02-08 18:08:42 +01:00
|
|
|
public enum wayType : byte { NONE, motorway, trunk, primary, secondary, tertiary, unclassified, residential, motorway_link, trunk_link, primary_link, secondary_link, tertiary_link, living_street, service, pedestrian, track, bus_guideway, escape, raceway, road, busway, footway, bridleway, steps, corridor, path, cycleway, construction }
|
2023-02-06 17:32:55 +01:00
|
|
|
|
|
|
|
public enum speedType { pedestrian, car, road }
|
|
|
|
|
|
|
|
public void AddTag(string key, string value)
|
2023-02-07 23:52:57 +01:00
|
|
|
{
|
|
|
|
KeyValuePair<tagType, object> tag = ConvertToTag(key, value);
|
2023-02-08 18:08:42 +01:00
|
|
|
if(tag.Key != tagType.EMPTY)
|
2023-02-08 19:05:13 +01:00
|
|
|
tags.Add(tag.Key, tag.Value);
|
2023-02-07 23:52:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public static KeyValuePair<tagType, object> ConvertToTag(string key, string value)
|
2023-02-06 17:32:55 +01:00
|
|
|
{
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case "highway":
|
|
|
|
try
|
|
|
|
{
|
2023-02-07 23:52:57 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.highway, (wayType)Enum.Parse(typeof(wayType), value, true));
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
catch (ArgumentException)
|
2023-02-07 23:52:57 +01:00
|
|
|
{
|
|
|
|
return new KeyValuePair<tagType, object>(tagType.highway, wayType.unclassified);
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
case "maxspeed":
|
|
|
|
try
|
2023-02-08 18:49:21 +01:00
|
|
|
{
|
|
|
|
byte speed = Convert.ToByte(value);
|
|
|
|
if(speed == 255)
|
|
|
|
return new KeyValuePair<tagType, object>(tagType.EMPTY, 0);
|
|
|
|
else
|
|
|
|
return new KeyValuePair<tagType, object>(tagType.maxspeed, speed);
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
2023-02-08 18:08:42 +01:00
|
|
|
catch (Exception)
|
2023-02-06 17:32:55 +01:00
|
|
|
{
|
2023-02-08 18:08:42 +01:00
|
|
|
//Console.WriteLine(e);
|
|
|
|
//Console.WriteLine("Continuing...");
|
2023-02-07 23:52:57 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.maxspeed, byte.MaxValue);
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
case "oneway":
|
|
|
|
switch (value)
|
|
|
|
{
|
|
|
|
case "yes":
|
2023-02-07 23:52:57 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.oneway, true);
|
2023-02-06 17:32:55 +01:00
|
|
|
case "-1":
|
2023-02-07 23:52:57 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.forward, false);
|
2023-02-06 17:32:55 +01:00
|
|
|
case "no":
|
2023-02-07 23:52:57 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.oneway, false);
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "id":
|
2023-02-07 23:52:57 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.id, Convert.ToUInt64(value));
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
2023-02-08 18:08:42 +01:00
|
|
|
return new KeyValuePair<tagType, object>(tagType.EMPTY, 0);
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public ulong GetId()
|
|
|
|
{
|
2023-02-08 19:05:13 +01:00
|
|
|
return tags.ContainsKey(tagType.id) ? (ulong)tags[tagType.id] : 0;
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public wayType GetHighwayType()
|
2023-02-08 19:05:13 +01:00
|
|
|
{
|
|
|
|
if (!tags.ContainsKey(tagType.highway))
|
|
|
|
throw new Exception("Not a road?");
|
|
|
|
return (wayType)tags[tagType.highway];
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsOneWay()
|
|
|
|
{
|
2023-02-08 19:05:13 +01:00
|
|
|
return tags.ContainsKey(tagType.oneway) && (bool)tags[tagType.oneway];
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
|
2023-02-08 19:05:13 +01:00
|
|
|
public byte GetMaxSpeed(speedType type)
|
2023-02-06 17:32:55 +01:00
|
|
|
{
|
2023-02-08 19:05:13 +01:00
|
|
|
switch (type)
|
2023-02-06 17:32:55 +01:00
|
|
|
{
|
2023-02-08 19:05:13 +01:00
|
|
|
case speedType.road:
|
|
|
|
return tags.ContainsKey(tagType.maxspeed) ? (byte)tags[tagType.maxspeed] : (byte)0;
|
|
|
|
case speedType.car:
|
|
|
|
return tags.ContainsKey(tagType.maxspeed) ? (byte)tags[tagType.maxspeed] : defaultSpeedCar[GetHighwayType()];
|
|
|
|
case speedType.pedestrian:
|
|
|
|
return defaultSpeedPedestrian[GetHighwayType()];
|
|
|
|
default:
|
|
|
|
return 0;
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsForward()
|
|
|
|
{
|
|
|
|
return this.tags.ContainsKey(tagType.forward) && (bool)this.tags[tagType.forward];
|
|
|
|
}
|
2023-02-08 18:49:21 +01:00
|
|
|
|
|
|
|
public double GetWeight(OsmNode parentNode, speedType vehicle)
|
|
|
|
{
|
|
|
|
double distance = Utils.DistanceBetween(parentNode, neighborCoordinates);
|
2023-02-08 19:05:13 +01:00
|
|
|
byte speedByte = GetMaxSpeed(vehicle);
|
|
|
|
if (speedByte > 0)
|
2023-02-08 18:49:21 +01:00
|
|
|
{
|
|
|
|
double speed = Convert.ToDouble(speedByte);
|
2023-02-08 19:05:13 +01:00
|
|
|
return distance / speed;
|
2023-02-08 18:49:21 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return double.MaxValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
{
|
|
|
|
string tagsString = "";
|
|
|
|
foreach (KeyValuePair<tagType, object> tag in tags)
|
|
|
|
{
|
|
|
|
tagsString += string.Format("\n\t{0}: {1}", tag.Key, tag.Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return string.Format("EDGE neighborCoordinates: {0} {1}", neighborCoordinates.ToString(), tagsString);
|
|
|
|
}
|
2023-02-06 17:32:55 +01:00
|
|
|
}
|