]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/vehicletype.cpp
Give vehicle types a simple box geometry
[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_fixed_axle(unsigned i) const
30 {
31         if(i>=axles.size())
32                 throw out_of_range("VehicleType::get_fixed_axle");
33         return axles[i];
34 }
35
36 const VehicleType::Bogie &VehicleType::get_bogie(unsigned i) const
37 {
38         if(i>=bogies.size())
39                 throw out_of_range("VehicleType::get_bogie");
40         return bogies[i];
41 }
42
43 const VehicleType::Axle &VehicleType::get_bogie_axle(unsigned i, unsigned j) const
44 {
45         if(i>=bogies.size())
46                 throw out_of_range("VehicleType::get_bogie_axle");
47         if(j>=bogies[i].axles.size())
48                 throw out_of_range("VehicleType::get_bogie_axle");
49         return bogies[i].axles[j];
50 }
51
52 const VehicleType::Rod &VehicleType::get_rod(unsigned i) const
53 {
54         if(i>=rods.size())
55                 throw out_of_range("VehicleType::get_rod");
56         return rods[i];
57 }
58
59 float VehicleType::get_front_axle_offset() const
60 {
61         float front = length/2;
62         if(!axles.empty())
63                 front = axles.front().position;
64         if(!bogies.empty())
65         {
66                 const Bogie &bogie = bogies.front();
67                 front = max(front, bogie.position+bogie.axles.front().position);
68         }
69         return front;
70 }
71
72 float VehicleType::get_back_axle_offset() const
73 {
74         float back = -length/2;
75         if(!axles.empty())
76                 back = axles.back().position;
77         if(!bogies.empty())
78         {
79                 const Bogie &bogie = bogies.back();
80                 back = min(back, bogie.position+bogie.axles.back().position);
81         }
82         return back;
83 }
84
85
86 VehicleType::Axle::Axle():
87         position(0),
88         wheel_dia(0),
89         powered(false)
90 { }
91
92
93 VehicleType::Bogie::Bogie():
94         position(0),
95         rotate_object(false)
96 { }
97
98
99 VehicleType::Rod::Rod():
100         pivot(BODY),
101         pivot_index(0),
102         pivot_index2(0),
103         limit(ROTATE),
104         connect_index(-1),
105         mirror_object(false)
106 { }
107
108
109 VehicleType::Loader::Loader(VehicleType &vt):
110         DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>(vt)
111 {
112         add("axle",       &Loader::axle);
113         add("bogie",      &Loader::bogie);
114         add("function",   &Loader::function);
115         add("height",     &Loader::height);
116         add("length",     &Loader::length);
117         add("locomotive", &VehicleType::locomotive);
118         add("object",     &VehicleType::object);
119         add("rod",        &Loader::rod);
120         add("rotate_object", &VehicleType::rotate_object);
121         add("swap_direction", &VehicleType::swap_direction);
122         add("width",      &Loader::width);
123 }
124
125 void VehicleType::Loader::finish()
126 {
127         obj.shape = new Geometry::TransformedShape<float, 3>(
128                 Geometry::Box<float>(obj.length, obj.width, obj.height),
129                 Transform::translation(Vector(0, 0, obj.height/2)));
130 }
131
132 void VehicleType::Loader::axle()
133 {
134         Axle axl;
135         load_sub(axl);
136         obj.axles.push_back(axl);
137 }
138
139 void VehicleType::Loader::bogie()
140 {
141         Bogie bog;
142         load_sub(bog);
143         obj.bogies.push_back(bog);
144 }
145
146 void VehicleType::Loader::function(unsigned i, const string &f)
147 {
148         obj.functions[i] = f;
149 }
150
151 void VehicleType::Loader::height(float h)
152 {
153         obj.height = h/1000;
154 }
155
156 void VehicleType::Loader::length(float l)
157 {
158         obj.length = l/1000;
159 }
160
161 void VehicleType::Loader::rod()
162 {
163         Rod rd;
164         Rod::Loader ldr(rd, rod_tags);
165         load_sub_with(ldr);
166         obj.rods.push_back(rd);
167         if(!ldr.get_tag().empty())
168                 rod_tags[ldr.get_tag()] = obj.rods.size()-1;
169         rod_tags["previous"] = obj.rods.size()-1;
170 }
171
172 void VehicleType::Loader::width(float w)
173 {
174         obj.width = w/1000;
175 }
176
177
178 VehicleType::Axle::Loader::Loader(Axle &a):
179         DataFile::ObjectLoader<Axle>(a)
180 {
181         add("object",         &Axle::object);
182         add("position",       &Loader::position);
183         add("powered",        &Axle::powered);
184         add("wheel_diameter", &Loader::wheel_diameter);
185 }
186
187 void VehicleType::Axle::Loader::position(float p)
188 {
189         obj.position = p/1000;
190 }
191
192 void VehicleType::Axle::Loader::wheel_diameter(float d)
193 {
194         obj.wheel_dia = d/1000;
195 }
196
197
198 VehicleType::Bogie::Loader::Loader(Bogie &b):
199         DataFile::ObjectLoader<Bogie>(b)
200 {
201         add("axle",          &Loader::axle);
202         add("object",        &Bogie::object);
203         add("position",      &Loader::position);
204         add("rotate_object", &Bogie::rotate_object);
205 }
206
207 void VehicleType::Bogie::Loader::axle()
208 {
209         Axle axl;
210         load_sub(axl);
211         obj.axles.push_back(axl);
212 }
213
214 void VehicleType::Bogie::Loader::position(float p)
215 {
216         obj.position = p/1000;
217 }
218
219
220 VehicleType::Rod::Loader::Loader(Rod &r, const map<string, unsigned> &t):
221         DataFile::ObjectLoader<Rod>(r),
222         tags(t)
223 {
224         add("connect",       &Loader::connect);
225         add("limit",         &Rod::limit);
226         add("mirror_object", &Rod::mirror_object);
227         add("object",        &Rod::object);
228         add("pivot_body",    &Loader::pivot_body);
229         add("pivot_axle",    &Loader::pivot_axle);
230         add("pivot_axle",    &Loader::pivot_bogie_axle);
231         add("pivot_rod",     &Loader::pivot_rod);
232         add("position",      &Loader::position);
233         add("tag",           &Loader::set_tag);
234 }
235
236 void VehicleType::Rod::Loader::connect(const string &t, float px, float pz, float ox, float oz)
237 {
238         obj.connect_index = get_item(tags, t);
239         obj.connect_point = Vector(px/1000, 0, pz/1000);
240         obj.connect_offset = Vector(ox/1000, 0, oz/1000);
241 }
242
243 void VehicleType::Rod::Loader::pivot_body()
244 {
245         obj.pivot = BODY;
246 }
247
248 void VehicleType::Rod::Loader::pivot_axle(unsigned i)
249 {
250         obj.pivot = AXLE;
251         obj.pivot_index = i;
252 }
253
254 void VehicleType::Rod::Loader::pivot_bogie_axle(unsigned i, unsigned j)
255 {
256         obj.pivot = BOGIE_AXLE;
257         obj.pivot_index = i;
258         obj.pivot_index2 = j;
259 }
260
261 void VehicleType::Rod::Loader::pivot_rod(const string &t)
262 {
263         obj.pivot_index = get_item(tags, t);
264         obj.pivot = ROD;
265 }
266
267 void VehicleType::Rod::Loader::position(float x, float y, float z)
268 {
269         obj.pivot_point = Vector(x/1000, y/1000, z/1000);
270 }
271
272 void VehicleType::Rod::Loader::set_tag(const string &t)
273 {
274         tag = t;
275 }
276
277
278 void operator>>(const LexicalConverter &c, VehicleType::Rod::Limit &l)
279 {
280         const string &s = c.get();
281         if(s=="FIXED")
282                 l = VehicleType::Rod::FIXED;
283         else if(s=="ROTATE")
284                 l = VehicleType::Rod::ROTATE;
285         else if(s=="SLIDE_X")
286                 l = VehicleType::Rod::SLIDE_X;
287         else
288                 throw lexical_error(format("conversion of '%s' to Rod::Limit", s));
289 }
290
291 } // namespace R2C2