9 TrackType::TrackType(const ArticleNumber &an):
15 float TrackType::get_total_length() const
17 return get_path_length(-1);
20 float TrackType::get_path_length(int p) const
23 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
24 if(p<0 || i->get_path()==static_cast<unsigned>(p))
25 len += i->get_length();
29 unsigned TrackType::get_paths() const
32 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
33 mask |= 1<<i->get_path();
37 unsigned TrackType::get_n_paths() const
40 for(unsigned mask = get_paths(); mask; ++n)
45 bool TrackType::is_turnout() const
47 return endpoints.size()>2;
50 bool TrackType::is_dead_end() const
52 return endpoints.size()<2;
55 const TrackType::Endpoint &TrackType::get_endpoint(unsigned i) const
57 if(i>=endpoints.size())
58 throw out_of_range("TrackType::get_endpoint");
63 TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const
65 if(epi>=endpoints.size())
66 throw out_of_range("TrackType::get_point");
68 const TrackPart *part = 0;
70 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
72 if(endpoints[epi].has_path(path) && i->get_path()!=path)
75 unsigned n_part_eps = (i->is_dead_end() ? 1 : 2);
76 for(unsigned j=0; j<n_part_eps; ++j)
78 TrackPoint p = i->get_point(j ? i->get_length() : 0);
79 float dx = p.pos.x-endpoints[epi].pos.x;
80 float dy = p.pos.y-endpoints[epi].pos.y;
90 throw logic_error("internal error (endpoint does not match any part)");
94 float plen = part->get_length();
99 TrackPoint p = part->get_point(d);
107 TrackPart *next = part->get_link(1-part_ep);
109 throw invalid_argument("TrackType::get_point");
110 part_ep = (next->get_link(0)==part ? 0 : 1);
116 TrackPoint TrackType::get_nearest_point(const Vector &p) const
121 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
123 TrackPoint n = i->get_nearest_point(p);
124 float d = distance(n.pos, p);
135 bool TrackType::collide_ray(const Vector &start, const Vector &dir, float width) const
137 for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
138 if(i->collide_ray(start, dir, width))
144 void TrackType::collect_endpoints()
148 for(vector<TrackPart>::iterator i=parts.begin(); i!=parts.end(); ++i)
150 for(vector<TrackPart>::iterator j=i; ++j!=parts.end();)
153 unsigned n_part_eps = (i->is_dead_end() ? 1 : 2);
154 for(unsigned j=0; j<n_part_eps; ++j)
157 TrackPoint p = i->get_point(j ? i->get_length() : 0);
162 for(vector<Endpoint>::iterator k=endpoints.begin(); k!=endpoints.end(); ++k)
164 float dx = k->pos.x-p.pos.x;
165 float dy = k->pos.y-p.pos.y;
167 float da = k->dir-p.dir;
173 if(dx*dx+dy*dy<1e-6 && da>-0.01 && da<0.01)
175 k->paths |= 1<<i->get_path();
182 endpoints.push_back(Endpoint(p.pos.x, p.pos.y, p.dir, 1<<i->get_path()));
187 TrackType::Endpoint::Endpoint(float x, float y, float d, unsigned p):
194 TrackType::Loader::Loader(TrackType &t):
195 Msp::DataFile::ObjectLoader<TrackType>(t),
196 state_bits_set(false)
198 add("autofit_preference", &TrackType::autofit_preference);
199 add("description", &TrackType::description);
200 add("object", &TrackType::object);
201 add("state_bits", &Loader::state_bits);
202 add("part", &Loader::part);
205 void TrackType::Loader::finish()
207 obj.collect_endpoints();
210 void TrackType::Loader::part()
214 obj.parts.push_back(p);
215 if(!state_bits_set && p.get_path())
216 while(p.get_path()>=(1U<<obj.state_bits))
220 void TrackType::Loader::state_bits(unsigned b)
223 state_bits_set = true;