9 TrackPart::TrackPart():
19 float TrackPart::get_length() const
22 return abs(radius)*length;
27 TrackPoint TrackPart::get_point(float d) const
31 Transform dir_trans = Transform::rotation(dir, Vector(0, 0, 1));
34 Angle a = Angle::from_radians(d/radius);
35 Vector r = dir_trans.transform(Vector(0, -radius, 0));
36 result.pos = pos-r+Transform::rotation(a, Vector(0, 0, 1)).transform(r);
41 result.pos = pos+dir_trans.transform(Vector(d, 0, 0));
48 TrackPoint TrackPart::get_nearest_point(const Vector &p) const
51 Transform dir_trans = Transform::rotation(dir, Vector(0, 0, 1));
54 Vector r = dir_trans.transform(Vector(0, -radius, 0));
56 Angle a = Geometry::atan2(v.y, v.x)+Angle::quarter_turn()-dir;
58 a = Angle::half_turn()-a;
59 a.wrap_with_base(Angle::from_radians(length/2)-Angle::half_turn());
60 a = min(max(a, Angle::zero()), Angle::from_radians(length));
63 tp.pos = pos-r+Transform::rotation(a, Vector(0, 0, 1)).transform(r);
69 Vector dir_vec = dir_trans.transform(Vector(1, 0, 0));
70 float d = min(max(dot(dir_vec, v), 0.0f), length);
71 tp.pos = pos+dir_vec*d;
77 void TrackPart::check_link(TrackPart &other)
79 unsigned n_eps = (dead_end ? 1 : 2);
80 unsigned n_other_eps = (other.is_dead_end() ? 1 : 2);
81 for(unsigned i=0; i<n_eps; ++i)
83 TrackPoint p1 = get_point(i ? get_length() : 0);
84 for(unsigned j=0; j<n_other_eps; ++j)
86 TrackPoint p2 = other.get_point(j ? other.get_length() : 0);
88 Vector span = p2.pos-p1.pos;
90 Angle da = wrap_balanced(p2.dir-p1.dir+Angle::half_turn()*float((i+j+1)%2));
92 if(dot(span, span)<1e-6 && abs(da).radians()<=0.01)
95 other.links[j] = this;
102 TrackPart *TrackPart::get_link(unsigned i) const
105 throw out_of_range("TrackPart::get_link");
109 bool TrackPart::collide_ray(const Vector &start, const Vector &ray, float width) const
111 Transform trans = Transform::rotation(dir, Vector(0, 0, -1));
112 Vector local_start = trans.transform(start);
113 Vector local_ray = trans.transform_linear(ray);
115 float d = -local_start.z/local_ray.z;
119 Vector base = local_start+d*local_ray;
126 float r = base.norm()-abs(radius);
127 float a = atan2(base.x, -base.y);
128 return (a>=0 && a<=length && r>=-width/2 && r<=width/2);
131 return (base.x>=0 && base.x<=length && base.y>=-width/2 && base.y<=width/2);
135 TrackPart::Loader::Loader(TrackPart &p):
136 Msp::DataFile::ObjectLoader<TrackPart>(p)
138 add("start", &Loader::start);
139 add("length", &TrackPart::length);
140 add("radius", &TrackPart::radius);
141 add("path", &TrackPart::path);
142 add("dead_end", &TrackPart::dead_end);
145 void TrackPart::Loader::finish()
149 obj.length *= M_PI/180;
158 void TrackPart::Loader::start(float x, float y, float d)
160 obj.pos = Vector(x, y, 0);
161 obj.dir = Angle::from_degrees(d);