1 #include <msp/core/maputils.h>
2 #include <msp/geometry/box.h>
3 #include <msp/geometry/transformedshape.h>
4 #include <msp/strings/regex.h>
5 #include <msp/strings/format.h>
6 #include "vehicletype.h"
13 VehicleType::VehicleType(const ArticleNumber &an):
16 swap_direction(false),
25 unsigned VehicleType::get_max_function() const
29 return (--functions.end())->first;
32 const VehicleType::Axle &VehicleType::get_axle(unsigned i) const
35 throw out_of_range("VehicleType::get_axle");
39 const VehicleType::Axle &VehicleType::get_fixed_axle(unsigned i) const
41 if(i>=fixed_axles.size())
42 throw out_of_range("VehicleType::get_fixed_axle");
43 return *fixed_axles[i];
46 const VehicleType::Bogie &VehicleType::get_bogie(unsigned i) const
49 throw out_of_range("VehicleType::get_bogie");
53 const VehicleType::Axle &VehicleType::get_bogie_axle(unsigned i, unsigned j) const
56 throw out_of_range("VehicleType::get_bogie_axle");
57 if(j>=bogies[i].axles.size())
58 throw out_of_range("VehicleType::get_bogie_axle");
59 return *bogies[i].axles[j];
62 const VehicleType::Rod &VehicleType::get_rod(unsigned i) const
65 throw out_of_range("VehicleType::get_rod");
69 float VehicleType::get_front_axle_offset() const
72 return axles.front().position;
76 float VehicleType::get_back_axle_offset() const
79 return axles.back().position;
84 VehicleType::Axle::Axle():
94 VehicleType::Bogie::Bogie():
100 VehicleType::Rod::Rod():
105 VehicleType::Loader::Loader(VehicleType &vt):
106 DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>(vt)
108 add("axle", &Loader::axle);
109 add("bogie", &Loader::bogie);
110 add("function", &Loader::function);
111 add("gauge", &Loader::gauge);
112 add("height", &Loader::height);
113 add("length", &Loader::length);
114 add("locomotive", &VehicleType::locomotive);
115 add("maximum_speed", &VehicleType::max_speed);
116 add("mirror_rods", &Loader::mirror_rods);
117 add("object", &VehicleType::object);
118 add("rod", &Loader::rod);
119 add("rotate_object", &VehicleType::rotate_object);
120 add("swap_direction", &VehicleType::swap_direction);
121 add("width", &Loader::width);
124 void VehicleType::Loader::finish()
126 for(unsigned i=0; i<obj.bogies.size(); ++i)
128 obj.bogies[i].index = i;
129 for(unsigned j=0; j<obj.bogies[i].axles.size(); ++j)
131 obj.bogies[i].axles[j] = &obj.axles[obj.bogies[i].first_axle+j];
132 obj.bogies[i].axles[j]->bogie = &obj.bogies[i];
133 obj.bogies[i].axles[j]->position += obj.bogies[i].position;
137 for(unsigned i=0; i<obj.axles.size(); ++i)
139 obj.axles[i].index = i;
140 if(!obj.axles[i].bogie)
141 obj.fixed_axles.push_back(&obj.axles[i]);
144 for(TagMap::const_iterator i=rod_tags.begin(); i!=rod_tags.end(); ++i)
145 if(i->second>=0x10000)
146 throw runtime_error(format("unresolved reference to %s\n", i->first));
148 obj.shape = new Geometry::TransformedShape<float, 3>(
149 Geometry::Box<float>(obj.length, obj.width, obj.height),
150 Transform::translation(Vector(0, 0, obj.height/2)));
153 void VehicleType::Loader::axle()
157 obj.axles.push_back(axl);
160 void VehicleType::Loader::bogie()
163 Bogie::Loader ldr(obj, bog);
165 obj.bogies.push_back(bog);
168 void VehicleType::Loader::function(unsigned i, const string &f)
170 obj.functions[i] = f;
173 void VehicleType::Loader::gauge(float g)
178 void VehicleType::Loader::height(float h)
183 void VehicleType::Loader::length(float l)
188 void VehicleType::Loader::mirror_rods()
190 MirrorParametersLoader params;
191 load_sub_with(params);
192 Regex r_filter(params.filter);
194 vector<unsigned> mirror_indices(obj.rods.size(), 0);
195 for(TagMap::const_iterator i=rod_tags.begin(); i!=rod_tags.end(); ++i)
196 if(i->second<0x10000 && r_filter.match(i->first))
197 mirror_indices[i->second] = 1;
199 for(unsigned i=0, j=obj.rods.size(); i<mirror_indices.size(); ++i)
200 if(mirror_indices[i])
201 mirror_indices[i] = j++;
203 Transform axle_trans = Transform::rotation(params.phase_offset, Vector(0, 1, 0));
205 for(unsigned i=0; i<mirror_indices.size(); ++i)
207 if(!mirror_indices[i])
210 Rod mr = obj.rods[i];
211 mr.initial_position.y = -mr.initial_position.y;
212 mr.mirror_object = !mr.mirror_object;
213 for(vector<RodConstraint>::iterator j=mr.constraints.begin(); j!=mr.constraints.end(); ++j)
215 j->target_position.y = -j->target_position.y;
216 j->local_position.y = -j->local_position.y;
217 j->axis.y = -j->axis.y;
218 if(j->target==RodConstraint::ROD && mirror_indices[j->target_index])
219 j->target_index = mirror_indices[j->target_index];
220 else if(j->target==RodConstraint::AXLE)
221 j->target_position = axle_trans.transform(j->target_position);
224 obj.rods.push_back(mr);
228 void VehicleType::Loader::rod(const string &t)
231 Rod::Loader ldr(rd, rod_tags);
234 unsigned n = obj.rods.size();
235 if(rod_tags.count(t))
237 unsigned p = rod_tags[t];
238 for(vector<Rod>::iterator i=obj.rods.begin(); i!=obj.rods.end(); ++i)
239 for(vector<RodConstraint>::iterator j=i->constraints.begin(); j!=i->constraints.end(); ++j)
240 if(j->target_index==p)
244 obj.rods.push_back(rd);
247 void VehicleType::Loader::width(float w)
253 VehicleType::Axle::Loader::Loader(Axle &a):
254 DataFile::ObjectLoader<Axle>(a)
256 add("object", &Axle::object);
257 add("position", &Loader::position);
258 add("powered", &Axle::powered);
259 add("wheel_diameter", &Loader::wheel_diameter);
262 void VehicleType::Axle::Loader::position(float p)
264 obj.local_position = p/1000;
265 obj.position = obj.local_position;
268 void VehicleType::Axle::Loader::wheel_diameter(float d)
270 obj.wheel_dia = d/1000;
274 VehicleType::Bogie::Loader::Loader(VehicleType &t, Bogie &b):
275 DataFile::ObjectLoader<Bogie>(b),
278 add("axle", &Loader::axle);
279 add("object", &Bogie::object);
280 add("position", &Loader::position);
281 add("rotate_object", &Bogie::rotate_object);
284 void VehicleType::Bogie::Loader::axle()
288 if(obj.axles.empty())
289 obj.first_axle = parent.axles.size();
290 parent.axles.push_back(axl);
291 // Actual pointers will be filled after everything is loaded
292 obj.axles.push_back(0);
295 void VehicleType::Bogie::Loader::position(float p)
297 obj.position = p/1000;
301 VehicleType::RodConstraint::RodConstraint():
308 VehicleType::RodConstraint::Loader::Loader(RodConstraint &c, TagMap &t):
309 DataFile::ObjectLoader<RodConstraint>(c),
312 add("axis", &Loader::axis);
313 add("local_position", &Loader::local_position);
314 add("target_axle", &Loader::target_axle);
315 add("target_position", &Loader::target_position);
316 add("target_rod", &Loader::target_rod);
319 void VehicleType::RodConstraint::Loader::axis(float x, float y, float z)
321 obj.axis = Vector(x, y, z);
322 obj.axis.normalize();
325 void VehicleType::RodConstraint::Loader::local_position(float x, float y, float z)
327 obj.local_position = Vector(x/1000, y/1000, z/1000);
330 void VehicleType::RodConstraint::Loader::target_axle(unsigned i)
333 obj.target_index = i;
337 void VehicleType::RodConstraint::Loader::target_position(float x, float y, float z)
339 obj.target_position = Vector(x/1000, y/1000, z/1000);
342 void VehicleType::RodConstraint::Loader::target_rod(const string &n)
345 TagMap::iterator i = tags.find(n);
347 obj.target_index = i->second;
350 obj.target_index = 0x10000+tags.size();
351 tags[n] = obj.target_index;
356 VehicleType::Rod::Loader::Loader(Rod &r, TagMap &t):
357 DataFile::ObjectLoader<Rod>(r),
360 add("initial_position", &Loader::initial_position);
361 add("mirror_object", &Rod::mirror_object);
362 add("move", &Loader::constraint<RodConstraint::MOVE>);
363 add("object", &Rod::object);
364 add("rotate", &Loader::constraint<RodConstraint::ROTATE>);
365 add("slide", &Loader::constraint<RodConstraint::SLIDE>);
368 template<VehicleType::RodConstraint::Type t>
369 void VehicleType::Rod::Loader::constraint()
374 obj.constraints.push_back(cns);
377 void VehicleType::Rod::Loader::initial_position(float x, float y, float z)
379 obj.initial_position = Vector(x/1000, y/1000, z/1000);
383 VehicleType::MirrorParametersLoader::MirrorParametersLoader()
385 add("filter", &MirrorParametersLoader::filt);
386 add("phase_offset", &MirrorParametersLoader::phase_offs);
389 void VehicleType::MirrorParametersLoader::filt(const string &f)
394 void VehicleType::MirrorParametersLoader::phase_offs(float o)
396 phase_offset = Angle::from_degrees(o);