refactoring turn angle stuff

This commit is contained in:
Dustin Carlino 2018-12-01 14:38:42 -08:00
parent 503c3c2ca9
commit 1542e3118e
6 changed files with 68 additions and 62 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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]));
}
};
}
}
}

View File

@ -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);

View File

@ -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 {

View File

@ -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
}
}
}