From 15baefe05221697d987dbb26b7b2a61e1da841de Mon Sep 17 00:00:00 2001 From: Paris DOUADY Date: Sun, 13 Aug 2023 15:57:23 +0200 Subject: [PATCH] relax roundabout a bit --- egregoria/src/map/objects/turn.rs | 28 ++++++++++++------- geom/src/angle.rs | 6 ++-- geom/src/v2.rs | 4 +-- native_app/src/gui/roadeditor.rs | 2 +- .../src/rendering/map_rendering/map_mesh.rs | 5 +++- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/egregoria/src/map/objects/turn.rs b/egregoria/src/map/objects/turn.rs index 3d77f9e0..7b0ae0f3 100644 --- a/egregoria/src/map/objects/turn.rs +++ b/egregoria/src/map/objects/turn.rs @@ -121,10 +121,10 @@ impl Turn { let ang_b = b.angle_cossin(); if ang_a > ang_b { - ang_a -= TAU; + ang_a -= Radians::TAU; } - let mut turn_radius = rp.radius * (1.0 - 0.5 * (ang_b - ang_a) / TAU); + let mut turn_radius = rp.radius * (1.0 - 0.5 * (ang_b.0 - ang_a.0) / TAU); if matches!(self.kind, TurnKind::WalkingCorner) { turn_radius = rp.radius + 3.0; @@ -173,12 +173,20 @@ impl Turn { let b = (pos_dst.xy() - center) .normalize() .rotated_by_angle(Radians::from_deg(-20.0)); - let ang_b = b.angle_cossin(); + let mut ang_b = b.angle_cossin(); if ang_a > ang_b { - ang_a -= TAU; + ang_a -= Radians::TAU; } + let diff = (ang_b - ang_a).min(Radians::from_deg(50.0)); + + ang_a += diff * 0.4; + ang_b -= diff * 0.4; + + let a = ang_a.vec2(); + let b = ang_b.vec2(); + let sp1 = Self::spline( pos_src.xy(), center + a * radius, @@ -201,19 +209,19 @@ impl Turn { /// Return points of a circular arc in counter-clockwise order from ang_a to ang_b, assuming ang_a < ang_b pub fn circular_arc( center: Vec2, - ang_a: f32, - ang_b: f32, + ang_a: Radians, + ang_b: Radians, radius: f32, ) -> impl Iterator { const PRECISION: f32 = 1.0 / 0.1; // denominator is angular step in radians let ang = ang_b - ang_a; - let n = (ang.abs() * PRECISION).ceil() as usize; - let ang_step = ang / n as f32; + let n = (ang.0.abs() * PRECISION).ceil() as usize; + let ang_step = Radians(ang.0 / n as f32); (0..=n).map(move |i| { - let ang = ang_a + ang_step * i as f32; - center + Vec2::new(ang.cos(), ang.sin()) * radius + let ang = ang_a + Radians(ang_step.0 * i as f32); + center + ang.vec2() * radius }) } diff --git a/geom/src/angle.rs b/geom/src/angle.rs index e81015b6..30982b46 100644 --- a/geom/src/angle.rs +++ b/geom/src/angle.rs @@ -1,6 +1,6 @@ use crate::Vec2; use serde::{Deserialize, Serialize}; -use std::f32::consts::PI; +use std::f32::consts::{PI, TAU}; use std::ops::{Add, AddAssign, Mul, Sub, SubAssign}; #[derive(Serialize, Deserialize, Copy, Clone, PartialOrd, PartialEq, Default)] @@ -15,6 +15,8 @@ pub struct Radians(pub f32); impl Radians { pub const HALFPI: Self = Radians(std::f32::consts::FRAC_PI_2); + pub const PI: Self = Radians(PI); + pub const TAU: Self = Radians(TAU); pub fn vec2(self) -> Vec2 { Vec2 { @@ -28,7 +30,7 @@ impl Radians { } pub fn normalize(&mut self) { - self.0 %= std::f32::consts::TAU; + self.0 %= TAU; } pub fn cos(self) -> f32 { diff --git a/geom/src/v2.rs b/geom/src/v2.rs index 86be273b..115a3f02 100644 --- a/geom/src/v2.rs +++ b/geom/src/v2.rs @@ -231,8 +231,8 @@ impl Vec2 { /// Returns the angle in range [-pi; pi] such that if v is unitary /// v == (angle.cos(), angle.sin()) #[inline] - pub fn angle_cossin(self) -> f32 { - f32::atan2(self.y, self.x) + pub fn angle_cossin(self) -> Radians { + Radians(f32::atan2(self.y, self.x)) } #[inline] diff --git a/native_app/src/gui/roadeditor.rs b/native_app/src/gui/roadeditor.rs index dca02e62..58ee17e1 100644 --- a/native_app/src/gui/roadeditor.rs +++ b/native_app/src/gui/roadeditor.rs @@ -87,7 +87,7 @@ pub fn roadeditor(goria: &Egregoria, uiworld: &mut UiWorld) { } } - imm_draw.circle(proj_pos, 10.0).color(proj_col); + imm_draw.circle(proj_pos.up(0.1), 10.0).color(proj_col); if state.dirty { if let Some(interc) = &state.inspect { diff --git a/native_app/src/rendering/map_rendering/map_mesh.rs b/native_app/src/rendering/map_rendering/map_mesh.rs index 983be1fa..23d5df5d 100644 --- a/native_app/src/rendering/map_rendering/map_mesh.rs +++ b/native_app/src/rendering/map_rendering/map_mesh.rs @@ -906,7 +906,10 @@ fn intersection_mesh( if let Some(rp) = inter.turn_policy.roundabout { let center = inter.pos.xy(); - let ang = (-src_orient).angle(dst_orient).abs(); + let ang = (left - center) + .normalize() + .angle((next_right - center).normalize()) + .abs(); if ang >= Radians::from_deg(41.0).0 { polygon.extend(Turn::gen_roundabout( left.z(0.0),