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 Point Track::get_endpoint_position(const Endpoint &ep) const
66 return Point(pos.x+c*ep.pos.x-s*ep.pos.y, pos.y+s*ep.pos.x+c*ep.pos.y, pos.z+ep.pos.z);
69 float Track::get_length() const
71 float len=parts.front().length;
72 if(parts.front().radius)
73 len*=parts.front().radius;
77 float Track::get_total_length() const
80 for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
90 unsigned Track::get_n_routes() const
93 for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
99 bool Track::snap_to(Track &other, bool link)
101 float limit=(link && !flex) ? 1e-6 : 1e-4;
102 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
104 Point epp=get_endpoint_position(*i);
105 for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
110 Point epp2=other.get_endpoint_position(*j);
111 float dx=epp2.x-epp.x;
112 float dy=epp2.y-epp.y;
113 if(dx*dx+dy*dy<limit)
115 set_rotation(other.rot+j->rot-i->rot+M_PI);
116 set_position(Point(epp2.x-(i->pos.x*cos(rot)-i->pos.y*sin(rot)), epp2.y-(i->pos.y*cos(rot)+i->pos.x*sin(rot)), other.pos.z+j->pos.z-i->pos.z));
120 break_link(*i->link);
132 bool Track::snap(Point &pt, float &d) const
134 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
136 Point epp=get_endpoint_position(*i);
150 void Track::break_link(Track &trk)
152 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
156 trk.break_link(*this);
161 void Track::break_links()
163 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
168 trk->break_link(*this);
172 void Track::check_slope()
174 if(endpoints.size()!=2)
177 Track *link1=endpoints.front().link;
178 Track *link2=endpoints.back().link;
181 const Endpoint *ep1=link1->get_endpoint_by_link(this);
182 const Endpoint *ep2=link2->get_endpoint_by_link(this);
183 pos.z=link1->pos.z+ep1->pos.z;
184 slope=(link2->pos.z+ep2->pos.z)-pos.z;
191 const Endpoint *ep=link1->get_endpoint_by_link(this);
192 pos.z=link1->pos.z+ep->pos.z;
196 const Endpoint *ep=link2->get_endpoint_by_link(this);
197 pos.z=link2->pos.z+ep->pos.z;
201 endpoints.back().pos.z=slope;
204 const Track::Endpoint *Track::traverse(const Endpoint *ep, unsigned route) const
206 if(ep->routes&(1<<route))
208 // Find the other endpoint for this route
209 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
210 if((i->routes&(1<<route)) && &*i!=ep)
215 // Find an endpoint that's connected to this one and has the requested route
216 for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
217 if((i->routes&(1<<route)) && (i->routes&ep->routes))
224 Track *Track::copy() const
226 Track *trk=new Track(*this);
227 for(EndpointSeq::iterator i=trk->endpoints.begin(); i!=trk->endpoints.end(); ++i)
237 void Track::collect_endpoints()
241 for(PartSeq::iterator i=parts.begin(); i!=parts.end(); ++i)
242 i->collect_endpoints(endpoints);
243 endpoints.back().pos.z=slope;
245 for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end();)
248 for(EndpointSeq::iterator j=i; j!=endpoints.end();)
255 float dx=i->pos.x-j->pos.x;
256 float dy=i->pos.y-j->pos.y;
257 if(dx*dx+dy*dy<0.0001)
259 float da=i->rot-j->rot;
266 i->routes|=j->routes;
267 j=endpoints.erase(j);
273 i=endpoints.erase(i);
283 Track::Loader::Loader(Track &t):
286 add("description", &Track::description);
287 add("part", &Loader::part);
288 add("position", &Loader::position);
289 add("rotation", &Track::rot);
290 add("slope", &Track::slope);
291 add("turnout_id", &Track::turnout_id);
292 add("sensor_id", &Track::sensor_id);
293 add("flex", &Track::flex);
296 Track::Loader::~Loader()
298 track.collect_endpoints();
301 void Track::Loader::part()
305 track.parts.push_back(p);
308 void Track::Loader::position(float x, float y, float z)
310 track.pos=Point(x, y, z);
327 void Track::Part::collect_endpoints(EndpointSeq &epl)
329 epl.push_back(Endpoint(Point(x, y, 0), dir+M_PI, 1<<route));
334 float a=(radius<0)?-length:length;
337 float rx=radius*sin(dir);
338 float ry=-radius*cos(dir);
339 epl.push_back(Endpoint(Point(x+c*rx-s*ry-rx, y+c*ry+s*rx-ry, 0), dir+a, 1<<route));
342 epl.push_back(Endpoint(Point(x+cos(dir)*length, y+sin(dir)*length, 0), dir, 1<<route));
345 Track::Part::Loader::Loader(Part &p):
348 add("start", &Loader::start);
349 add("length", &Part::length);
350 add("radius", &Part::radius);
351 add("route", &Part::route);
352 add("dead_end", &Part::dead_end);
355 Track::Part::Loader::~Loader()
359 part.length*=M_PI/180;
370 void Track::Part::Loader::start(float x, float y, float d)
377 } // namespace Marklin