]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/vehicletype.cpp
Store all axles in a single array
[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         pivot(BODY),
99         pivot_index(0),
100         pivot_index2(0),
101         limit(ROTATE),
102         connect_index(-1),
103         mirror_object(false)
104 { }
105
106
107 VehicleType::Loader::Loader(VehicleType &vt):
108         DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>(vt)
109 {
110         add("axle",       &Loader::axle);
111         add("bogie",      &Loader::bogie);
112         add("function",   &Loader::function);
113         add("height",     &Loader::height);
114         add("length",     &Loader::length);
115         add("locomotive", &VehicleType::locomotive);
116         add("object",     &VehicleType::object);
117         add("rod",        &Loader::rod);
118         add("rotate_object", &VehicleType::rotate_object);
119         add("swap_direction", &VehicleType::swap_direction);
120         add("width",      &Loader::width);
121 }
122
123 void VehicleType::Loader::finish()
124 {
125         for(unsigned i=0; i<obj.bogies.size(); ++i)
126         {
127                 obj.bogies[i].index = i;
128                 for(unsigned j=0; j<obj.bogies[i].axles.size(); ++j)
129                 {
130                         obj.bogies[i].axles[j] = &obj.axles[obj.bogies[i].first_axle+j];
131                         obj.bogies[i].axles[j]->bogie = &obj.bogies[i];
132                         obj.bogies[i].axles[j]->position += obj.bogies[i].position;
133                 }
134         }
135
136         for(unsigned i=0; i<obj.axles.size(); ++i)
137         {
138                 obj.axles[i].index = i;
139                 if(!obj.axles[i].bogie)
140                         obj.fixed_axles.push_back(&obj.axles[i]);
141         }
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::rod()
179 {
180         Rod rd;
181         Rod::Loader ldr(rd, rod_tags);
182         load_sub_with(ldr);
183         obj.rods.push_back(rd);
184         if(!ldr.get_tag().empty())
185                 rod_tags[ldr.get_tag()] = obj.rods.size()-1;
186         rod_tags["previous"] = obj.rods.size()-1;
187 }
188
189 void VehicleType::Loader::width(float w)
190 {
191         obj.width = w/1000;
192 }
193
194
195 VehicleType::Axle::Loader::Loader(Axle &a):
196         DataFile::ObjectLoader<Axle>(a)
197 {
198         add("object",         &Axle::object);
199         add("position",       &Loader::position);
200         add("powered",        &Axle::powered);
201         add("wheel_diameter", &Loader::wheel_diameter);
202 }
203
204 void VehicleType::Axle::Loader::position(float p)
205 {
206         obj.local_position = p/1000;
207         obj.position = obj.local_position;
208 }
209
210 void VehicleType::Axle::Loader::wheel_diameter(float d)
211 {
212         obj.wheel_dia = d/1000;
213 }
214
215
216 VehicleType::Bogie::Loader::Loader(VehicleType &t, Bogie &b):
217         DataFile::ObjectLoader<Bogie>(b),
218         parent(t)
219 {
220         add("axle",          &Loader::axle);
221         add("object",        &Bogie::object);
222         add("position",      &Loader::position);
223         add("rotate_object", &Bogie::rotate_object);
224 }
225
226 void VehicleType::Bogie::Loader::axle()
227 {
228         Axle axl;
229         load_sub(axl);
230         if(obj.axles.empty())
231                 obj.first_axle = parent.axles.size();
232         parent.axles.push_back(axl);
233         // Actual pointers will be filled after everything is loaded
234         obj.axles.push_back(0);
235 }
236
237 void VehicleType::Bogie::Loader::position(float p)
238 {
239         obj.position = p/1000;
240 }
241
242
243 VehicleType::Rod::Loader::Loader(Rod &r, const map<string, unsigned> &t):
244         DataFile::ObjectLoader<Rod>(r),
245         tags(t)
246 {
247         add("connect",       &Loader::connect);
248         add("limit",         &Rod::limit);
249         add("mirror_object", &Rod::mirror_object);
250         add("object",        &Rod::object);
251         add("pivot_body",    &Loader::pivot_body);
252         add("pivot_axle",    &Loader::pivot_axle);
253         add("pivot_axle",    &Loader::pivot_bogie_axle);
254         add("pivot_rod",     &Loader::pivot_rod);
255         add("position",      &Loader::position);
256         add("tag",           &Loader::set_tag);
257 }
258
259 void VehicleType::Rod::Loader::connect(const string &t, float px, float pz, float ox, float oz)
260 {
261         obj.connect_index = get_item(tags, t);
262         obj.connect_point = Vector(px/1000, 0, pz/1000);
263         obj.connect_offset = Vector(ox/1000, 0, oz/1000);
264 }
265
266 void VehicleType::Rod::Loader::pivot_body()
267 {
268         obj.pivot = BODY;
269 }
270
271 void VehicleType::Rod::Loader::pivot_axle(unsigned i)
272 {
273         obj.pivot = AXLE;
274         obj.pivot_index = i;
275 }
276
277 void VehicleType::Rod::Loader::pivot_bogie_axle(unsigned i, unsigned j)
278 {
279         obj.pivot = BOGIE_AXLE;
280         obj.pivot_index = i;
281         obj.pivot_index2 = j;
282 }
283
284 void VehicleType::Rod::Loader::pivot_rod(const string &t)
285 {
286         obj.pivot_index = get_item(tags, t);
287         obj.pivot = ROD;
288 }
289
290 void VehicleType::Rod::Loader::position(float x, float y, float z)
291 {
292         obj.pivot_point = Vector(x/1000, y/1000, z/1000);
293 }
294
295 void VehicleType::Rod::Loader::set_tag(const string &t)
296 {
297         tag = t;
298 }
299
300
301 void operator>>(const LexicalConverter &c, VehicleType::Rod::Limit &l)
302 {
303         const string &s = c.get();
304         if(s=="FIXED")
305                 l = VehicleType::Rod::FIXED;
306         else if(s=="ROTATE")
307                 l = VehicleType::Rod::ROTATE;
308         else if(s=="SLIDE_X")
309                 l = VehicleType::Rod::SLIDE_X;
310         else
311                 throw lexical_error(format("conversion of '%s' to Rod::Limit", s));
312 }
313
314 } // namespace R2C2