mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 12:43:38 +03:00
refactoring turn angle stuff
This commit is contained in:
parent
503c3c2ca9
commit
1542e3118e
@ -116,8 +116,9 @@ fn tooltip_lines(obj: ID, map: &Map, sim: &Sim, draw_map: &DrawMap) -> Text {
|
||||
txt.add_line(format!("Roads: {:?}", map.get_i(id).roads));
|
||||
}
|
||||
ID::Turn(id) => {
|
||||
let t = map.get_t(id);
|
||||
txt.add_line(format!("{}", id));
|
||||
txt.add_line(format!("Angle {}", map.get_t(id).turn_angle(map)));
|
||||
txt.add_line(format!("{:?} / {:?}", t.turn_type, t.turn_angle(map)));
|
||||
}
|
||||
ID::Building(id) => {
|
||||
let b = map.get_b(id);
|
||||
|
@ -51,7 +51,7 @@ pub use road::{Road, RoadID};
|
||||
pub use stop_signs::ControlStopSign;
|
||||
pub use traffic_signals::ControlTrafficSignal;
|
||||
pub use traversable::{Position, Traversable};
|
||||
pub use turn::{Turn, TurnID, TurnPriority, TurnType};
|
||||
pub use turn::{Turn, TurnAngle, TurnID, TurnPriority, TurnType};
|
||||
|
||||
pub const LANE_THICKNESS: f64 = 2.5;
|
||||
|
||||
|
@ -4,7 +4,7 @@ use std::collections::{BTreeSet, HashSet};
|
||||
use std::iter;
|
||||
use {
|
||||
Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, Map, Road, RoadID,
|
||||
Turn, TurnID, TurnType,
|
||||
Turn, TurnAngle, TurnID, TurnType,
|
||||
};
|
||||
|
||||
pub fn make_all_turns(i: &Intersection, map: &Map) -> Vec<Turn> {
|
||||
@ -108,25 +108,23 @@ fn make_vehicle_turns(i: &Intersection, map: &Map) -> Vec<Turn> {
|
||||
// Use an arbitrary lane from each road to get the angle between r1 and r2.
|
||||
let angle1 = map.get_l(incoming[0]).last_line().angle();
|
||||
let angle2 = map.get_l(outgoing[0]).first_line().angle();
|
||||
let diff = angle1
|
||||
.shortest_rotation_towards(angle2)
|
||||
.normalized_degrees();
|
||||
|
||||
if diff < 10.0 || diff > 350.0 {
|
||||
// Straight. Match up based on the relative number of lanes.
|
||||
result.extend(match_up_lanes(map, i.id, &incoming, &outgoing));
|
||||
} else if diff > 180.0 {
|
||||
// Clockwise rotation means a right turn?
|
||||
result.push(make_vehicle_turn(
|
||||
map,
|
||||
i.id,
|
||||
*incoming.last().unwrap(),
|
||||
*outgoing.last().unwrap(),
|
||||
));
|
||||
} else {
|
||||
// Counter-clockwise rotation means a left turn
|
||||
result.push(make_vehicle_turn(map, i.id, incoming[0], outgoing[0]));
|
||||
}
|
||||
match TurnAngle::new(angle1, angle2) {
|
||||
TurnAngle::Straight => {
|
||||
// Match up based on the relative number of lanes.
|
||||
result.extend(match_up_lanes(map, i.id, &incoming, &outgoing));
|
||||
}
|
||||
TurnAngle::Right => {
|
||||
result.push(make_vehicle_turn(
|
||||
map,
|
||||
i.id,
|
||||
*incoming.last().unwrap(),
|
||||
*outgoing.last().unwrap(),
|
||||
));
|
||||
}
|
||||
TurnAngle::Left => {
|
||||
result.push(make_vehicle_turn(map, i.id, incoming[0], outgoing[0]));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Error};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use {IntersectionID, LaneID, Map, TurnID, TurnPriority, TurnType};
|
||||
use {IntersectionID, LaneID, Map, TurnAngle, TurnID, TurnPriority, TurnType};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ControlStopSign {
|
||||
@ -151,9 +151,7 @@ fn smart_assignment(map: &Map, id: IntersectionID) -> ControlStopSign {
|
||||
// If it's the highest rank road, make the straight and right turns priority (if
|
||||
// possible) and other turns yield.
|
||||
let turn = map.get_t(*t);
|
||||
if (turn.is_right_turn(map) || turn.is_straight_turn(map))
|
||||
&& ss.could_be_priority_turn(*t, map)
|
||||
{
|
||||
if turn.turn_angle(map) != TurnAngle::Left && ss.could_be_priority_turn(*t, map) {
|
||||
ss.turns.insert(*t, TurnPriority::Priority);
|
||||
} else {
|
||||
ss.turns.insert(*t, TurnPriority::Yield);
|
||||
|
@ -2,7 +2,7 @@ use abstutil::{note, Error};
|
||||
use dimensioned::si;
|
||||
use std;
|
||||
use std::collections::BTreeSet;
|
||||
use {IntersectionID, Map, RoadID, TurnID, TurnPriority, TurnType};
|
||||
use {IntersectionID, Map, RoadID, TurnAngle, TurnID, TurnPriority, TurnType};
|
||||
|
||||
const CYCLE_DURATION: si::Second<f64> = si::Second {
|
||||
value_unsafe: 15.0,
|
||||
@ -264,18 +264,20 @@ fn make_cycles(
|
||||
if turns != Turns::Crosswalk {
|
||||
continue;
|
||||
}
|
||||
} else if turn.is_straight_turn(map) {
|
||||
if turns != Turns::StraightAndRight {
|
||||
continue;
|
||||
}
|
||||
} else if turn.is_right_turn(map) {
|
||||
if turns != Turns::StraightAndRight && turns != Turns::Right {
|
||||
continue;
|
||||
}
|
||||
} else if turn.is_left_turn(map) {
|
||||
if turns != Turns::Left {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
match turn.turn_angle(map) {
|
||||
TurnAngle::Straight => if turns != Turns::StraightAndRight {
|
||||
continue;
|
||||
},
|
||||
TurnAngle::Right => {
|
||||
if turns != Turns::StraightAndRight && turns != Turns::Right {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
TurnAngle::Left => if turns != Turns::Left {
|
||||
continue;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if protected {
|
||||
|
@ -87,26 +87,14 @@ impl Turn {
|
||||
self.line.pt2()
|
||||
}
|
||||
|
||||
// TODO all the stuff based on turn angle is a bit... wrong, especially for sidewalks. :\
|
||||
// also, make sure right/left/straight are disjoint... and maybe cover all turns. return an enum from one method.
|
||||
pub fn turn_angle(&self, map: &Map) -> Angle {
|
||||
let lane_angle = map.get_l(self.id.src).end_line(self.id.parent).angle();
|
||||
// TODO Use shortest_rotation_towards, same logic from make/turns?
|
||||
self.line.angle() - lane_angle
|
||||
}
|
||||
|
||||
pub fn is_right_turn(&self, map: &Map) -> bool {
|
||||
let a = self.turn_angle(map).normalized_degrees();
|
||||
a < 95.0 && a > 20.0
|
||||
}
|
||||
|
||||
pub fn is_straight_turn(&self, map: &Map) -> bool {
|
||||
let a = self.turn_angle(map).normalized_degrees();
|
||||
a <= 20.0 || a >= 320.0
|
||||
}
|
||||
|
||||
pub fn is_left_turn(&self, map: &Map) -> bool {
|
||||
!self.is_right_turn(map) && !self.is_straight_turn(map)
|
||||
pub fn turn_angle(&self, map: &Map) -> TurnAngle {
|
||||
TurnAngle::new(
|
||||
map.get_l(self.id.src).end_line(self.id.parent).angle(),
|
||||
map.get_l(self.id.dst)
|
||||
.end_line(self.id.parent)
|
||||
.reverse()
|
||||
.angle(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn between_sidewalks(&self) -> bool {
|
||||
@ -115,8 +103,27 @@ impl Turn {
|
||||
|
||||
pub fn dump_debug(&self, map: &Map) {
|
||||
println!("{}", abstutil::to_json(self));
|
||||
println!("turn angle {}", self.turn_angle(map));
|
||||
println!("is right turn? {}", self.is_right_turn(map));
|
||||
println!("is straight turn? {}", self.is_straight_turn(map));
|
||||
println!("turn angle {:?}", self.turn_angle(map));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum TurnAngle {
|
||||
Straight,
|
||||
Right,
|
||||
Left,
|
||||
}
|
||||
|
||||
impl TurnAngle {
|
||||
pub fn new(from: Angle, to: Angle) -> TurnAngle {
|
||||
let diff = from.shortest_rotation_towards(to).normalized_degrees();
|
||||
if diff < 10.0 || diff > 350.0 {
|
||||
TurnAngle::Straight
|
||||
} else if diff > 180.0 {
|
||||
// Clockwise rotation
|
||||
TurnAngle::Right
|
||||
} else {
|
||||
TurnAngle::Left
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user