using System.Text.Json; using System.Text.Json.Serialization; namespace OSMDatastructure; [Serializable] public class Tag { public TagType key { get; } public dynamic value { get; } [JsonConstructor] public Tag(TagType key, dynamic value) { this.key = key; if (value is JsonElement) { switch (key) { case TagType.highway: this.value = (WayType)value.GetByte(); break; case TagType.maxspeed: this.value = value.GetByte(); break; case TagType.forward: case TagType.oneway: this.value = value.GetBoolean(); break; case TagType.id: this.value = value.GetUInt64(); break; case TagType.name: case TagType.tagref: this.value = value.GetString(); break; default: this.value = value; break; } } else { this.value = value; } } public static HashSet ConvertToTags(string key, string value) { HashSet ret = new HashSet(); switch (key) { case "highway": try { ret.Add(new Tag(TagType.highway, (WayType)Enum.Parse(typeof(WayType), value, true))); } catch (ArgumentException) { ret.Add(new Tag(TagType.highway, WayType.unclassified)); } break; case "maxspeed": case "maxspeed:max": try { byte speed = Convert.ToByte(value); if (speed != 255) ret.Add(new Tag(TagType.maxspeed, speed)); } catch (Exception) { ret.Add(new Tag(TagType.maxspeed, byte.MinValue)); } break; case "oneway": switch (value) { case "yes": ret.Add(new Tag(TagType.oneway, true)); break; case "-1": ret.Add(new Tag(TagType.forward, false)); ret.Add(new Tag(TagType.oneway, true)); break; case "no": ret.Add(new Tag(TagType.oneway, false)); break; } break; case "name": ret.Add(new Tag(TagType.name, value)); break; case "ref": ret.Add(new Tag(TagType.tagref, value)); break; } return ret; } public override string ToString() { return $"TAG {key.ToString()} {value.ToString()}"; } public enum TagType : byte { highway, oneway, footway, sidewalk, cycleway, busway, forward, maxspeed, name, surface, lanes, access, tracktype, id, tagref } public static readonly Dictionary defaultSpeedCar = new() { { WayType.NONE, 0 }, { WayType.motorway, 130 }, { WayType.motorroad, 100 }, { WayType.trunk, 85 }, { WayType.primary, 65 }, { WayType.secondary, 60 }, { WayType.tertiary, 50 }, { WayType.unclassified, 30 }, { WayType.residential, 20 }, { WayType.motorway_link, 60 }, { WayType.trunk_link, 50 }, { WayType.primary_link, 50 }, { WayType.secondary_link, 50 }, { WayType.tertiary_link, 30 }, { 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, 20 }, { WayType.busway, 0 }, { WayType.footway, 0 }, { WayType.bridleway, 0 }, { WayType.steps, 0 }, { WayType.corridor, 0 }, { WayType.path, 0 }, { WayType.cycleway, 0 }, { WayType.construction, 0 } }; public static readonly Dictionary defaultSpeedPedestrian = new() { { WayType.NONE, 0 }, { WayType.motorway, 0 }, { WayType.trunk, 0 }, { WayType.primary, 0 }, { WayType.secondary, 0 }, { WayType.tertiary, 2 }, { WayType.unclassified, 1 }, { WayType.residential, 4 }, { 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, 1 }, { WayType.bus_guideway, 0 }, { WayType.escape, 1 }, { WayType.raceway, 0 }, { WayType.road, 2 }, { WayType.busway, 0 }, { WayType.footway, 4 }, { WayType.bridleway, 1 }, { WayType.steps, 2 }, { WayType.corridor, 3 }, { WayType.path, 4 }, { WayType.cycleway, 1 }, { WayType.construction, 0 } }; // ReSharper disable InconsistentNaming public enum WayType : byte { NONE, motorway, motorroad, 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 } // ReSharper restore InconsistentNaming public enum SpeedType { pedestrian, car, any } }