12 Track::Track(const TrackType &t):
19 links(t.get_endpoints().size())
27 void Track::set_position(const Point &p)
32 void Track::set_rotation(float r)
41 void Track::set_slope(float s)
43 if(links.size()!=2) return;
48 void Track::set_flex(bool f)
53 void Track::set_turnout_id(unsigned i)
58 void Track::set_sensor_id(unsigned i)
63 int Track::get_endpoint_by_link(const Track &other) const
65 for(unsigned i=0; i<links.size(); ++i)
72 Point Track::get_endpoint_position(unsigned epi) const
74 const vector<Endpoint> &eps=type.get_endpoints();
76 throw InvalidParameterValue("Endpoint index out of range");
78 const Endpoint &ep=eps[epi];
83 Point p(pos.x+c*ep.x-s*ep.y, pos.y+s*ep.x+c*ep.y, pos.z);
84 if(eps.size()==2 && epi==1)
89 float Track::get_endpoint_direction(unsigned epi) const
91 const vector<Endpoint> &eps=type.get_endpoints();
93 throw InvalidParameterValue("Endpoint index out of range");
95 const Endpoint &ep=eps[epi];
100 bool Track::snap_to(Track &other, bool link)
102 float limit=(link && !flex) ? 1e-6 : 1e-4;
103 const vector<Endpoint> &eps=type.get_endpoints();
104 const vector<Endpoint> &other_eps=other.get_type().get_endpoints();
106 for(unsigned i=0; i<eps.size(); ++i)
108 Point epp=get_endpoint_position(i);
110 for(unsigned j=0; j<other_eps.size(); ++j)
112 if(other.get_link(j))
115 Point epp2=other.get_endpoint_position(j);
116 float dx=epp2.x-epp.x;
117 float dy=epp2.y-epp.y;
118 if(dx*dx+dy*dy<limit)
120 set_rotation(other.rot+other_eps[j].dir-eps[i].dir+M_PI);
121 set_position(Point(epp2.x-(eps[i].x*cos(rot)-eps[i].y*sin(rot)), epp2.y-(eps[i].y*cos(rot)+eps[i].x*sin(rot)), epp2.z));
126 break_link(*links[i]);
139 bool Track::snap(Point &pt, float &d) const
141 const vector<Endpoint> &eps=type.get_endpoints();
143 for(unsigned i=0; i<eps.size(); ++i)
145 Point epp=get_endpoint_position(i);
159 void Track::break_link(Track &trk)
161 for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
165 trk.break_link(*this);
170 void Track::break_links()
172 for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
176 trk->break_link(*this);
180 Track *Track::get_link(unsigned i) const
183 throw InvalidParameterValue("Link index out of range");
188 void Track::check_slope()
193 if(links[0] && links[1])
195 Point epp0=links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
196 Point epp1=links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
205 Point epp=links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
210 Point epp=links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
216 int Track::traverse(unsigned i, unsigned route) const
218 const vector<Endpoint> &eps=type.get_endpoints();
220 throw InvalidParameterValue("Endpoint index out of range");
222 const Endpoint &ep=eps[i];
224 if(ep.routes&(1<<route))
226 // Find the other endpoint for this route
227 for(unsigned j=0; j<eps.size(); ++j)
228 if((eps[j].routes&(1<<route)) && j!=i)
233 // Find an endpoint that's connected to this one and has the requested route
234 for(unsigned j=0; j<eps.size(); ++j)
235 if((eps[j].routes&(1<<route)) && (eps[j].routes&ep.routes))
242 Track *Track::copy() const
244 Track *trk=new Track(type);
245 trk->set_position(pos);
246 trk->set_rotation(rot);
247 trk->set_slope(slope);
257 Track::Loader::Loader(Track &t):
260 add("position", &Loader::position);
261 add("rotation", &Track::rot);
262 add("slope", &Track::slope);
263 add("turnout_id", &Track::turnout_id);
264 add("sensor_id", &Track::sensor_id);
265 add("flex", &Track::flex);
268 void Track::Loader::position(float x, float y, float z)
270 track.pos=Point(x, y, z);
273 } // namespace Marklin