private void walkToNextSegment(SegmentNodeConnection target, HashSet <SegmentNodeConnection> processed) { var node = target.Node; var trafficNode = node as TrafficNode; trafficNode.VisitedAsLine = true; if (node.Segments.Count() != 2) { return; // stop walking } var other = node.Segments.FirstOrDefault(s => s != target); walkToNextNode(other, processed); var incomingSegment = target.Segment.Description as TrafficSegmentDescription; var outgoingSegment = other.Segment.Description as TrafficSegmentDescription; if (TrafficSegmentDescription.CanMerge(incomingSegment, outgoingSegment)) { trafficNode.IsDeletionPossible = true; } var dot = fixTangents(target, other); if (dot < Math.Cos(Math.PI / 180 * 175)) { trafficNode.IsAlmostStraight = true; } }
private SegmentDescription getDescription(Way way) { var desc = new TrafficSegmentDescription(); string value; if (way.Tags.TryGetValue("highway", out value)) { desc.Type = value; } else if (way.Tags.TryGetValue("railway", out value)) { desc.Type = value; } if (way.Tags.TryGetValue("junction", out value)) { if (value == "roundabout") { desc.IsOneWay = true; desc.IsRoundabout = true; } else if (value == "circular") { desc.IsOneWay = true; desc.IsRoundabout = false; } else { } } if (way.Tags.TryGetValue("name", out value)) { desc.Name = value; } int laneCount = 1; int forwardLanes = 0; int backwardLanes = 0; if (way.Tags.TryGetValue("lanes", out value)) { laneCount = int.Parse(value); } if (way.Tags.TryGetValue("lanes:forward", out value)) { forwardLanes = int.Parse(value); } if (way.Tags.TryGetValue("lanes:backward", out value)) { backwardLanes = int.Parse(value); } if (way.Tags.TryGetValue("oneway", out value)) { desc.IsOneWay = value == "yes" || value == "-1"; if (!desc.IsOneWay && value != "no") { } } int minLanes = desc.IsOneWay ? 1 : 2; float laneWidth = 3.7f; float maxSpeed = 130; VehicleTypes vehicles = VehicleTypes.Vehicle; LaneType laneType = LaneType.Road; switch (desc.Type) { case "motorway": case "motorway_link": case "trunk": case "trunk_link": laneType = LaneType.Highway; break; case "primary": case "primary_link": laneWidth = 3.25f; maxSpeed = 90; laneType = LaneType.Road; break; case "secondary": case "secondary_link": laneWidth = 3f; maxSpeed = 90; laneType = LaneType.Road; break; case "tertiary": case "tertiary_link": case "unclassified": laneWidth = 2.8f; maxSpeed = 70; laneType = LaneType.Road; break; case "residential": laneWidth = 2.8f; maxSpeed = 50; laneType = LaneType.Road; break; case "service": laneWidth = 2.5f; maxSpeed = 30f; laneType = LaneType.Road; break; case "living_street": laneWidth = 2.8f; maxSpeed = 30; laneType = LaneType.Road; break; case "pedestrian": laneWidth = 2.5f; maxSpeed = 15; vehicles = VehicleTypes.Pedestrian | VehicleTypes.Bicycle; laneType = LaneType.Pedestrian; break; case "track": laneWidth = 3f; maxSpeed = 20; laneType = LaneType.DirtTrack; break; case "bus_guideway": laneWidth = 4f; maxSpeed = 70; vehicles = VehicleTypes.Bus; laneType = LaneType.Buslane; break; case "escape": //vehicles = VehicleTypes.Emergency; //laneType = LaneType.Emergency; //break; //return null; // don't need paths case "road": maxSpeed = 50; laneType = LaneType.Road; break; case "footway": //maxSpeed = 10; //vehicles = VehicleTypes.Pedestrian; //laneWidth = 1.25f; //laneType = LaneType.Path; //break; return(null); // don't need paths case "cycleway": //laneWidth = 1.25f; //maxSpeed = 15; //vehicles = VehicleTypes.Bicycle; //laneType = LaneType.Bicycle; //break; return(null); // don't need paths case "path": case "bridleway": case "steps": //laneWidth = 1.10f; //maxSpeed = 5; //vehicles = VehicleTypes.Pedestrian; //laneType = LaneType.Path; //break; return(null); // don't need paths case "tram": maxSpeed = 50; vehicles = VehicleTypes.Tram; laneWidth = 1; laneType = LaneType.Tram; minLanes = 1; desc.IsOneWay = true; break; case "rail": maxSpeed = 200; vehicles = VehicleTypes.Train; laneWidth = 1.45f; laneType = LaneType.Train; minLanes = 1; desc.IsOneWay = true; break; case "platform": case "vehicle_depot": return(null); default: break; } if (backwardLanes > 0 || forwardLanes > 0 && laneCount == 0) { desc.LaneCount = backwardLanes + forwardLanes; } else if (backwardLanes == 0 && forwardLanes == 0) { if (desc.IsOneWay) { forwardLanes = laneCount; backwardLanes = 0; } else { laneCount = Math.Max(minLanes, laneCount); forwardLanes = (1 + laneCount) / 2; backwardLanes = laneCount - forwardLanes; } } else { desc.LaneCount = laneCount; } if (forwardLanes > 0 && (laneCount - forwardLanes) != backwardLanes) { backwardLanes = laneCount - forwardLanes; } if (backwardLanes > 0 && (laneCount - backwardLanes) != forwardLanes) { forwardLanes = laneCount - backwardLanes; } if (laneCount - backwardLanes != forwardLanes) { // issue } if (laneCount == 0) { // issue } desc.LaneCount = laneCount; desc.OsmWay = way; desc.Lanes = new LaneDescription[laneCount]; for (int i = 0; i < desc.Lanes.Length; i++) { desc.Lanes[i] = new LaneDescription { Width = laneWidth, MaxSpeed = maxSpeed, Turn = Turn.None, VehicleTypes = vehicles, Reverse = i < backwardLanes, LaneType = laneType } } ; processTag <float>("gauge", way.Tags, desc.Lanes, float.TryParse, (d, i, v) => d.Width = v * 0.001f); // gauge is in mm processTag <float>("maxspeed", way.Tags, desc.Lanes, float.TryParse, (d, i, v) => d.MaxSpeed = v); processTag <turnValues>("turn", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => d.Turn |= getTurn(v)); processTag <float>("width", way.Tags, desc.Lanes, float.TryParse, (d, i, v) => d.Width = v / laneCount); for (int i = 0; i < desc.Lanes.Length; i++) { var l = desc.Lanes[i]; if (l.Turn == Turn.None) { if (i == 0) { l.Turn |= Turn.Left; } if (forwardLanes == 1 || (i > 0 && i < forwardLanes)) { l.Turn |= Turn.Through; } if (i == forwardLanes - 1) { l.Turn |= Turn.Right; } if (backwardLanes > 0) { if (i == forwardLanes) { l.Turn |= Turn.Right; } if (backwardLanes == 1 || (i > forwardLanes && i < laneCount)) { l.Turn |= Turn.Through; } if (i == laneCount - 1) { l.Turn |= Turn.Left; } } } } // todo: multiple designated values can be set: foot and bicycle for example, this should combine! var dicts = new bool[laneCount, 8, 3]; processTag <accessValues>("hgv", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Truck, dicts)); processTag <accessValues>("hazmat", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Hazmat, dicts)); processTag <accessValues>("bus", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Bus, dicts)); processTag <accessValues>("psv", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Bus, dicts)); processTag <accessValues>("taxi", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Taxi, dicts)); processTag <accessValues>("emergency", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Emergency, dicts)); processTag <accessValues>("bicycle", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Bicycle, dicts)); processTag <accessValues>("foot", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Pedestrian, dicts)); processTag <accessValues>("vehicle", way.Tags, desc.Lanes, Enum.TryParse, (d, i, v) => setVehicleType(d, i, v, VehicleTypes.Vehicle, dicts)); for (int i = 0; i < laneCount; i++) { var allowed = desc.Lanes[i].VehicleTypes; // get default value for (int t = 1; t < dicts.GetLength(1); t++) { if (dicts[i, t, (int)accessValues.designated]) { allowed = VehicleTypes.None; } } for (int t = 1; t < dicts.GetLength(1); t++) { var type = (VehicleTypes)(1 << t); if (dicts[i, t, (int)accessValues.yes] || dicts[i, t, (int)accessValues.designated]) { allowed |= type; } else if (dicts[i, t, (int)accessValues.no]) { allowed &= ~type; } } desc.Lanes[i].VehicleTypes = allowed; } return(desc); }