]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/vehicletype.cpp
Rewrite rod simulation code
[r2c2.git] / source / libr2c2 / vehicletype.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/geometry/box.h>
3 #include <msp/geometry/transformedshape.h>
4 #include <msp/strings/format.h>
5 #include "vehicletype.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 namespace R2C2 {
11
12 VehicleType::VehicleType(const ArticleNumber &an):
13         ObjectType(an),
14         locomotive(false),
15         swap_direction(false),
16         length(0),
17         width(0),
18         height(0),
19         rotate_object(false)
20 { }
21
22 unsigned VehicleType::get_max_function() const
23 {
24         if(functions.empty())
25                 return 0;
26         return (--functions.end())->first;
27 }
28
29 const VehicleType::Axle &VehicleType::get_axle(unsigned i) const
30 {
31         if(i>=axles.size())
32                 throw out_of_range("VehicleType::get_axle");
33         return axles[i];
34 }
35
36 const VehicleType::Axle &VehicleType::get_fixed_axle(unsigned i) const
37 {
38         if(i>=fixed_axles.size())
39                 throw out_of_range("VehicleType::get_fixed_axle");
40         return *fixed_axles[i];
41 }
42
43 const VehicleType::Bogie &VehicleType::get_bogie(unsigned i) const
44 {
45         if(i>=bogies.size())
46                 throw out_of_range("VehicleType::get_bogie");
47         return bogies[i];
48 }
49
50 const VehicleType::Axle &VehicleType::get_bogie_axle(unsigned i, unsigned j) const
51 {
52         if(i>=bogies.size())
53                 throw out_of_range("VehicleType::get_bogie_axle");
54         if(j>=bogies[i].axles.size())
55                 throw out_of_range("VehicleType::get_bogie_axle");
56         return *bogies[i].axles[j];
57 }
58
59 const VehicleType::Rod &VehicleType::get_rod(unsigned i) const
60 {
61         if(i>=rods.size())
62                 throw out_of_range("VehicleType::get_rod");
63         return rods[i];
64 }
65
66 float VehicleType::get_front_axle_offset() const
67 {
68         if(!axles.empty())
69                 return axles.front().position;
70         return length/2;
71 }
72
73 float VehicleType::get_back_axle_offset() const
74 {
75         if(!axles.empty())
76                 return axles.back().position;
77         return -length/2;
78 }
79
80
81 VehicleType::Axle::Axle():
82         index(0),
83         bogie(0),
84         local_position(0),
85         position(0),
86         wheel_dia(0),
87         powered(false)
88 { }
89
90
91 VehicleType::Bogie::Bogie():
92         position(0),
93         rotate_object(false)
94 { }
95
96
97 VehicleType::Rod::Rod():
98         mirror_object(false)
99 { }
100
101
102 VehicleType::Loader::Loader(VehicleType &vt):
103         DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>(vt)
104 {
105         add("axle",       &Loader::axle);
106         add("bogie",      &Loader::bogie);
107         add("function",   &Loader::function);
108         add("height",     &Loader::height);
109         add("length",     &Loader::length);
110         add("locomotive", &VehicleType::locomotive);
111         add("mirror_rods", &Loader::mirror_rods);
112         add("object",     &VehicleType::object);
113         add("rod",        &Loader::rod);
114         add("rotate_object", &VehicleType::rotate_object);
115         add("swap_direction", &VehicleType::swap_direction);
116         add("width",      &Loader::width);
117 }
118
119 void VehicleType::Loader::finish()
120 {
121         for(unsigned i=0; i<obj.bogies.size(); ++i)
122         {
123                 obj.bogies[i].index = i;
124                 for(unsigned j=0; j<obj.bogies[i].axles.size(); ++j)
125                 {
126                         obj.bogies[i].axles[j] = &obj.axles[obj.bogies[i].first_axle+j];
127                         obj.bogies[i].axles[j]->bogie = &obj.bogies[i];
128                         obj.bogies[i].axles[j]->position += obj.bogies[i].position;
129                 }
130         }
131
132         for(unsigned i=0; i<obj.axles.size(); ++i)
133         {
134                 obj.axles[i].index = i;
135                 if(!obj.axles[i].bogie)
136                         obj.fixed_axles.push_back(&obj.axles[i]);
137         }
138
139         for(TagMap::const_iterator i=rod_tags.begin(); i!=rod_tags.end(); ++i)
140                 if(i->second>=0x10000)
141                         throw runtime_error(format("unresolved reference to %s\n", i->first));
142
143         obj.shape = new Geometry::TransformedShape<float, 3>(
144                 Geometry::Box<float>(obj.length, obj.width, obj.height),
145                 Transform::translation(Vector(0, 0, obj.height/2)));
146 }
147
148 void VehicleType::Loader::axle()
149 {
150         Axle axl;
151         load_sub(axl);
152         obj.axles.push_back(axl);
153 }
154
155 void VehicleType::Loader::bogie()
156 {
157         Bogie bog;
158         Bogie::Loader ldr(obj, bog);
159         load_sub_with(ldr);
160         obj.bogies.push_back(bog);
161 }
162
163 void VehicleType::Loader::function(unsigned i, const string &f)
164 {
165         obj.functions[i] = f;
166 }
167
168 void VehicleType::Loader::height(float h)
169 {
170         obj.height = h/1000;
171 }
172
173 void VehicleType::Loader::length(float l)
174 {
175         obj.length = l/1000;
176 }
177
178 void VehicleType::Loader::mirror_rods()
179 {
180         MirrorParametersLoader params;
181         load_sub_with(params);
182
183         Transform axle_trans = Transform::rotation(params.phase_offset, Vector(0, 1, 0));
184
185         unsigned index_offset = obj.rods.size();
186         for(unsigned i=0; i<index_offset; ++i)
187         {
188                 Rod mr = obj.rods[i];
189                 mr.initial_position.y = -mr.initial_position.y;
190                 mr.mirror_object = !mr.mirror_object;
191                 for(vector<RodConstraint>::iterator j=mr.constraints.begin(); j!=mr.constraints.end(); ++j)
192                 {
193                         j->target_position.y = -j->target_position.y;
194                         j->local_position.y = -j->local_position.y;
195                         j->axis.y = -j->axis.y;
196                         if(j->target==RodConstraint::ROD)
197                                 j->target_index += index_offset;
198                         else if(j->target==RodConstraint::AXLE)
199                                 j->target_position = axle_trans.transform(j->target_position);
200                 }
201
202                 obj.rods.push_back(mr);
203         }
204 }
205
206 void VehicleType::Loader::rod(const string &t)
207 {
208         Rod rd;
209         Rod::Loader ldr(rd, rod_tags);
210         load_sub_with(ldr);
211
212         unsigned n = obj.rods.size();
213         if(rod_tags.count(t))
214         {
215                 unsigned p = rod_tags[t];
216                 for(vector<Rod>::iterator i=obj.rods.begin(); i!=obj.rods.end(); ++i)   
217                         for(vector<RodConstraint>::iterator j=i->constraints.begin(); j!=i->constraints.end(); ++j)
218                                 if(j->target_index==p)
219                                         j->target_index = n;
220         }
221         rod_tags[t] = n;
222         obj.rods.push_back(rd);
223 }
224
225 void VehicleType::Loader::width(float w)
226 {
227         obj.width = w/1000;
228 }
229
230
231 VehicleType::Axle::Loader::Loader(Axle &a):
232         DataFile::ObjectLoader<Axle>(a)
233 {
234         add("object",         &Axle::object);
235         add("position",       &Loader::position);
236         add("powered",        &Axle::powered);
237         add("wheel_diameter", &Loader::wheel_diameter);
238 }
239
240 void VehicleType::Axle::Loader::position(float p)
241 {
242         obj.local_position = p/1000;
243         obj.position = obj.local_position;
244 }
245
246 void VehicleType::Axle::Loader::wheel_diameter(float d)
247 {
248         obj.wheel_dia = d/1000;
249 }
250
251
252 VehicleType::Bogie::Loader::Loader(VehicleType &t, Bogie &b):
253         DataFile::ObjectLoader<Bogie>(b),
254         parent(t)
255 {
256         add("axle",          &Loader::axle);
257         add("object",        &Bogie::object);
258         add("position",      &Loader::position);
259         add("rotate_object", &Bogie::rotate_object);
260 }
261
262 void VehicleType::Bogie::Loader::axle()
263 {
264         Axle axl;
265         load_sub(axl);
266         if(obj.axles.empty())
267                 obj.first_axle = parent.axles.size();
268         parent.axles.push_back(axl);
269         // Actual pointers will be filled after everything is loaded
270         obj.axles.push_back(0);
271 }
272
273 void VehicleType::Bogie::Loader::position(float p)
274 {
275         obj.position = p/1000;
276 }
277
278
279 VehicleType::RodConstraint::RodConstraint():
280         type(MOVE),
281         target(BODY),
282         target_index(0)
283 { }
284
285
286 VehicleType::RodConstraint::Loader::Loader(RodConstraint &c, TagMap &t):
287         DataFile::ObjectLoader<RodConstraint>(c),
288         tags(t)
289 {
290         add("axis",            &Loader::axis);
291         add("local_position",  &Loader::local_position);
292         add("target_axle",     &Loader::target_axle);
293         add("target_position", &Loader::target_position);
294         add("target_rod",      &Loader::target_rod);
295 }
296
297 void VehicleType::RodConstraint::Loader::axis(float x, float y, float z)
298 {
299         obj.axis = Vector(x, y, z);
300         obj.axis.normalize();
301 }
302
303 void VehicleType::RodConstraint::Loader::local_position(float x, float y, float z)
304 {
305         obj.local_position = Vector(x/1000, y/1000, z/1000);
306 }
307
308 void VehicleType::RodConstraint::Loader::target_axle(unsigned i)
309 {
310         obj.target = AXLE;
311         obj.target_index = i;
312         // TODO check range
313 }
314
315 void VehicleType::RodConstraint::Loader::target_position(float x, float y, float z)
316 {
317         obj.target_position = Vector(x/1000, y/1000, z/1000);
318 }
319
320 void VehicleType::RodConstraint::Loader::target_rod(const string &n)
321 {
322         obj.target = ROD;
323         TagMap::iterator i = tags.find(n);
324         if(i!=tags.end())
325                 obj.target_index = i->second;
326         else
327         {
328                 obj.target_index = 0x10000+tags.size();
329                 tags[n] = obj.target_index;
330         }
331 }
332
333
334 VehicleType::Rod::Loader::Loader(Rod &r, TagMap &t):
335         DataFile::ObjectLoader<Rod>(r),
336         tags(t)
337 {
338         add("initial_position", &Loader::initial_position);
339         add("mirror_object", &Rod::mirror_object);
340         add("move", &Loader::constraint<RodConstraint::MOVE>);
341         add("object", &Rod::object);
342         add("rotate", &Loader::constraint<RodConstraint::ROTATE>);
343         add("slide", &Loader::constraint<RodConstraint::SLIDE>);
344 }
345
346 template<VehicleType::RodConstraint::Type t>
347 void VehicleType::Rod::Loader::constraint()
348 {
349         RodConstraint cns;
350         cns.type = t;
351         load_sub(cns, tags);
352         obj.constraints.push_back(cns);
353 }
354
355 void VehicleType::Rod::Loader::initial_position(float x, float y, float z)
356 {
357         obj.initial_position = Vector(x/1000, y/1000, z/1000);
358 }
359
360
361 VehicleType::MirrorParametersLoader::MirrorParametersLoader()
362 {
363         add("phase_offset", &MirrorParametersLoader::phase_offs);
364 }
365
366 void VehicleType::MirrorParametersLoader::phase_offs(float o)
367 {
368         phase_offset = Angle::from_degrees(o);
369 }
370
371 } // namespace R2C2