+TrackPoint TrackPart::get_nearest_point(const Vector &p) const
+{
+ TrackPoint tp;
+ Transform dir_trans = Transform::rotation(dir, Vector(0, 0, 1));
+ if(radius)
+ {
+ Vector r = dir_trans.transform(Vector(0, -radius, 0));
+ Vector v = p-pos+r;
+ Angle a = Geometry::atan2(v.y, v.x)+Angle::quarter_turn()-dir;
+ if(radius<0)
+ a = Angle::half_turn()-a;
+ a.wrap_with_base(Angle::from_radians(length/2)-Angle::half_turn());
+ a = min(max(a, Angle::zero()), Angle::from_radians(length));
+ if(radius<0)
+ a = -a;
+ tp.pos = pos-r+Transform::rotation(a, Vector(0, 0, 1)).transform(r);
+ tp.dir = dir+a;
+ }
+ else
+ {
+ Vector v = p-pos;
+ Vector dir_vec = dir_trans.transform(Vector(1, 0, 0));
+ float d = min(max(dot(dir_vec, v), 0.0f), length);
+ tp.pos = pos+dir_vec*d;
+ tp.dir = dir;
+ }
+ return tp;
+}
+