11 Track::Track(unsigned a):
22 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
27 trk->break_link(*this);
31 void Track::set_position(const Point &p)
36 void Track::set_rotation(float r)
45 void Track::set_slope(float s)
47 if(endpoints.size()!=2) return;
50 endpoints.back().pos.z=slope;
53 const Track::Endpoint *Track::get_endpoint_by_link(Track *other) const
55 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
62 float Track::get_length() const
64 float len=parts.front().length;
65 if(parts.front().radius)
66 len*=parts.front().radius;
70 float Track::get_total_length() const
73 for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
83 unsigned Track::get_n_routes() const
86 for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
92 bool Track::snap_to(Track &other, bool link)
94 float limit=(link && !flex) ? 1e-6 : 1e-4;
95 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
97 float x=pos.x+i->pos.x*cos(rot)-i->pos.y*sin(rot);
98 float y=pos.y+i->pos.y*cos(rot)+i->pos.x*sin(rot);
99 for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
104 float x2=other.pos.x+j->pos.x*cos(other.rot)-j->pos.y*sin(other.rot);
105 float y2=other.pos.y+j->pos.y*cos(other.rot)+j->pos.x*sin(other.rot);
108 if(dx*dx+dy*dy<limit)
110 set_rotation(other.rot+j->rot-i->rot+M_PI);
111 set_position(Point(x2-(i->pos.x*cos(rot)-i->pos.y*sin(rot)), y2-(i->pos.y*cos(rot)+i->pos.x*sin(rot)), other.pos.z+j->pos.z-i->pos.z));
115 break_link(*i->link);
127 bool Track::snap(Point &pt, float &d) const
129 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
131 float x=pos.x+i->pos.x*cos(rot)-i->pos.y*sin(rot);
132 float y=pos.y+i->pos.y*cos(rot)+i->pos.x*sin(rot);
147 void Track::break_link(Track &trk)
149 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
153 trk.break_link(*this);
158 void Track::break_links()
160 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
165 trk->break_link(*this);
169 void Track::check_slope()
171 if(endpoints.size()!=2)
174 Track *link1=endpoints.front().link;
175 Track *link2=endpoints.back().link;
178 const Endpoint *ep1=link1->get_endpoint_by_link(this);
179 const Endpoint *ep2=link2->get_endpoint_by_link(this);
180 pos.z=link1->pos.z+ep1->pos.z;
181 slope=(link2->pos.z+ep2->pos.z)-pos.z;
188 const Endpoint *ep=link1->get_endpoint_by_link(this);
189 pos.z=link1->pos.z+ep->pos.z;
193 const Endpoint *ep=link2->get_endpoint_by_link(this);
194 pos.z=link2->pos.z+ep->pos.z;
198 endpoints.back().pos.z=slope;
201 const Track::Endpoint *Track::traverse(const Endpoint *ep, unsigned route) const
203 if(ep->routes&(1<<route))
205 // Find the other endpoint for this route
206 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
207 if((i->routes&(1<<route)) && &*i!=ep)
212 // Find an endpoint that's connected to this one and has the requested route
213 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
214 if((i->routes&(1<<route)) && (i->routes&ep->routes))
221 Track *Track::copy() const
223 Track *trk=new Track(*this);
224 for(EndpointSeq::iterator i=trk->endpoints.begin(); i!=trk->endpoints.end(); ++i)
234 void Track::collect_endpoints()
238 for(PartSeq::iterator i=parts.begin(); i!=parts.end(); ++i)
239 i->collect_endpoints(endpoints);
240 endpoints.back().pos.z=slope;
242 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end();)
245 for(EndpointSeq::iterator j=i; j!=endpoints.end();)
252 float dx=i->pos.x-j->pos.x;
253 float dy=i->pos.y-j->pos.y;
254 if(dx*dx+dy*dy<0.0001)
256 float da=i->rot-j->rot;
263 i->routes|=j->routes;
264 j=endpoints.erase(j);
270 i=endpoints.erase(i);
280 Track::Loader::Loader(Track &t):
283 add("description", &Track::description);
284 add("part", &Loader::part);
285 add("position", &Loader::position);
286 add("rotation", &Track::rot);
287 add("slope", &Track::slope);
288 add("turnout_id", &Track::turnout_id);
289 add("sensor_id", &Track::sensor_id);
290 add("flex", &Track::flex);
293 Track::Loader::~Loader()
295 track.collect_endpoints();
298 void Track::Loader::part()
302 track.parts.push_back(p);
305 void Track::Loader::position(float x, float y, float z)
307 track.pos=Point(x, y, z);
324 void Track::Part::collect_endpoints(EndpointSeq &epl)
326 epl.push_back(Endpoint(Point(x, y, 0), dir+M_PI, 1<<route));
331 float a=(radius<0)?-length:length;
334 float rx=radius*sin(dir);
335 float ry=-radius*cos(dir);
336 epl.push_back(Endpoint(Point(x+c*rx-s*ry-rx, y+c*ry+s*rx-ry, 0), dir+a, 1<<route));
339 epl.push_back(Endpoint(Point(x+cos(dir)*length, y+sin(dir)*length, 0), dir, 1<<route));
342 Track::Part::Loader::Loader(Part &p):
345 add("start", &Loader::start);
346 add("length", &Part::length);
347 add("radius", &Part::radius);
348 add("route", &Part::route);
349 add("dead_end", &Part::dead_end);
352 Track::Part::Loader::~Loader()
356 part.length*=M_PI/180;
367 void Track::Part::Loader::start(float x, float y, float d)
374 } // namespace Marklin