]> git.tdb.fi Git - libs/math.git/blob - source/geometry/loader.h
Rename AffineTransformation to AffineTransform
[libs/math.git] / source / geometry / loader.h
1 #ifndef MSP_GEOMETRY_LOADER_H_
2 #define MSP_GEOMETRY_LOADER_H_
3
4 #include <list>
5 #include <msp/datafile/loader.h>
6 #include "extrudedshape.h"
7 #include "halfspace.h"
8 #include "hyperbox.h"
9 #include "hypersphere.h"
10 #include "intersection.h"
11 #include "negation.h"
12 #include "shape.h"
13 #include "transformedshape.h"
14 #include "union.h"
15
16 namespace Msp {
17 namespace Geometry {
18
19 template<typename T, unsigned D>
20 class DimensionIndependentLoader: public DataFile::Loader
21 {
22 protected:
23         bool single;
24         std::list<Shape<T, D> *> shapes;
25
26         DimensionIndependentLoader(bool = true);
27 public:
28         virtual ~DimensionIndependentLoader();
29
30         const Shape<T, D> &get_shape() const;
31
32 protected:
33         template<typename S>
34         void shape();
35 };
36
37
38 template<typename T, unsigned D, bool = (D>1)>
39 class Loader;
40
41 template<typename T, unsigned D>
42 class Loader<T, D, false>: public DimensionIndependentLoader<T, D>
43 {
44 public:
45         Loader(bool = true);
46 };
47
48 template<typename T, unsigned D>
49 class Loader<T, D, true>: public DimensionIndependentLoader<T, D>
50 {
51 public:
52         Loader(bool = true);
53 };
54
55
56 template<typename S>
57 class ShapeLoader;
58
59 template<typename T, unsigned D>
60 class ShapeLoader<ExtrudedShape<T, D> >: public Loader<T, D-1>
61 {
62 private:
63         T length_;
64
65 public:
66         ShapeLoader();
67
68         ExtrudedShape<T, D> *create() const;
69
70 private:
71         void length(T);
72 };
73
74 template<typename T, unsigned D>
75 class ShapeLoader<HalfSpace<T, D> >: public DataFile::Loader
76 {
77 private:
78         LinAl::Vector<T, D> normal_;
79
80 public:
81         ShapeLoader();
82
83         HalfSpace<T, D> *create() const;
84
85 private:
86         void normal(const std::vector<T> &);
87 };
88
89 template<typename T, unsigned D>
90 class ShapeLoader<HyperBox<T, D> >: public DataFile::Loader
91 {
92 private:
93         LinAl::Vector<T, D> dimensions_;
94
95 public:
96         ShapeLoader();
97
98         HyperBox<T, D> *create() const;
99
100 private:
101         void dimensions(const std::vector<T> &);
102 };
103
104 template<typename T, unsigned D>
105 class ShapeLoader<HyperSphere<T, D> >: public DataFile::Loader
106 {
107 private:
108         T radius_;
109
110 public:
111         ShapeLoader();
112
113         HyperSphere<T, D> *create() const;
114
115 private:
116         void radius(T);
117 };
118
119 template<typename T, unsigned D, typename S>
120 class CompositeLoader: public Loader<T, D>
121 {
122 public:
123         CompositeLoader();
124
125         S *create() const;
126 };
127
128 template<typename T, unsigned D>
129 class ShapeLoader<Intersection<T, D> >: public CompositeLoader<T, D, Intersection<T, D> >
130 { };
131
132 template<typename T, unsigned D>
133 class ShapeLoader<Negation<T, D> >: public Loader<T, D>
134 {
135 public:
136         Negation<T, D> *create() const;
137 };
138
139 template<typename T, unsigned D>
140 class TransformationLoader: public Loader<T, D>
141 {
142 protected:
143         AffineTransform<T, D> transformation;
144
145 public:
146         TransformationLoader();
147
148         TransformedShape<T, D> *create() const;
149
150         void translate(const std::vector<T> &);
151         void scale(const std::vector<T> &);
152         void shear(const std::vector<T> &);
153 };
154
155 template<typename T, unsigned D>
156 class ShapeLoader<TransformedShape<T, D> >: public TransformationLoader<T, D>
157 { };
158
159 template<typename T>
160 class ShapeLoader<TransformedShape<T, 2> >: public TransformationLoader<T, 2>
161 {
162 public:
163         ShapeLoader();
164
165         void rotate(T);
166 };
167
168 template<typename T>
169 class ShapeLoader<TransformedShape<T, 3> >: public TransformationLoader<T, 3>
170 {
171 public:
172         ShapeLoader();
173
174         void rotate(T, T, T, T);
175 };
176
177 template<typename T, unsigned D>
178 class ShapeLoader<Union<T, D> >: public CompositeLoader<T, D, Union<T, D> >
179 { };
180
181
182 template<typename T, unsigned D>
183 inline DimensionIndependentLoader<T, D>::DimensionIndependentLoader(bool s):
184         single(s)
185 {
186         add("box", &DimensionIndependentLoader::shape<HyperBox<T, D> >);
187         add("halfspace", &DimensionIndependentLoader::shape<HalfSpace<T, D> >);
188         add("intersection", &DimensionIndependentLoader::shape<Intersection<T, D> >);
189         add("negation", &DimensionIndependentLoader::shape<Negation<T, D> >);
190         add("sphere", &DimensionIndependentLoader::shape<HyperSphere<T, D> >);
191         add("transformed", &DimensionIndependentLoader::shape<TransformedShape<T, D> >);
192         add("union", &DimensionIndependentLoader::shape<Union<T, D> >);
193 }
194
195 template<typename T, unsigned D>
196 inline DimensionIndependentLoader<T, D>::~DimensionIndependentLoader()
197 {
198         for(typename std::list<Shape<T, D> *>::iterator i=shapes.begin(); i!=shapes.end(); ++i)
199                 delete *i;
200 }
201
202 template<typename T, unsigned D>
203 inline const Shape<T, D> &DimensionIndependentLoader<T, D>::get_shape() const
204 {
205         if(shapes.empty())
206                 throw std::runtime_error("no shape");
207         return *shapes.front();
208 }
209
210 template<typename T, unsigned D>
211 template<typename S>
212 inline void DimensionIndependentLoader<T, D>::shape()
213 {
214         if(single && !shapes.empty())
215                 throw std::runtime_error("shape already loaded");
216
217         ShapeLoader<S> ldr;
218         load_sub_with(ldr);
219         shapes.push_back(ldr.create());
220 }
221
222
223 template<typename T, unsigned D>
224 inline Loader<T, D, false>::Loader(bool s):
225         DimensionIndependentLoader<T, D>(s)
226 { }
227
228 template<typename T, unsigned D>
229 inline Loader<T, D, true>::Loader(bool s):
230         DimensionIndependentLoader<T, D>(s)
231 {
232         this->add("extruded", &Loader<T, D>::template shape<ExtrudedShape<T, D> >);
233 }
234
235
236 template<typename T, unsigned D>
237 inline ShapeLoader<ExtrudedShape<T, D> >::ShapeLoader():
238         length_(T(1))
239 {
240         this->add("length", &ShapeLoader::length);
241 }
242
243 template<typename T, unsigned D>
244 inline ExtrudedShape<T, D> *ShapeLoader<ExtrudedShape<T, D> >::create() const
245 {
246         return new ExtrudedShape<T, D>(*this->shapes.front(), length_);
247 }
248
249 template<typename T, unsigned D>
250 inline void ShapeLoader<ExtrudedShape<T, D> >::length(T l)
251 {
252         length_ = l;
253 }
254
255
256 template<typename T, unsigned D>
257 inline ShapeLoader<HalfSpace<T, D> >::ShapeLoader()
258 {
259         normal_[D-1] = T(1);
260
261         add("normal", &ShapeLoader::normal);
262 }
263
264 template<typename T, unsigned D>
265 inline HalfSpace<T, D> *ShapeLoader<HalfSpace<T, D> >::create() const
266 {
267         return new HalfSpace<T, D>(normal_);
268 }
269
270 template<typename T, unsigned D>
271 inline void ShapeLoader<HalfSpace<T, D> >::normal(const std::vector<T> &d)
272 {
273         if(d.size()!=D)
274                 throw std::invalid_argument("ShapeLoader<HalfSpace>::normal");
275
276         normal_ = LinAl::Vector<T, D>(&d[0]);
277 }
278
279
280 template<typename T, unsigned D>
281 inline ShapeLoader<HyperBox<T, D> >::ShapeLoader()
282 {
283         for(unsigned i=0; i<D; ++i)
284                 dimensions_[i] = T(1);
285
286         add("dimensions", &ShapeLoader::dimensions);
287 }
288
289 template<typename T, unsigned D>
290 inline HyperBox<T, D> *ShapeLoader<HyperBox<T, D> >::create() const
291 {
292         return new HyperBox<T, D>(dimensions_);
293 }
294
295 template<typename T, unsigned D>
296 inline void ShapeLoader<HyperBox<T, D> >::dimensions(const std::vector<T> &d)
297 {
298         if(d.size()!=D)
299                 throw std::invalid_argument("ShapeLoader<HyperBox>::dimensions");
300
301         dimensions_ = LinAl::Vector<T, D>(&d[0]);
302 }
303
304
305 template<typename T, unsigned D>
306 inline ShapeLoader<HyperSphere<T, D> >::ShapeLoader():
307         radius_(T(1))
308 {
309         add("radius", &ShapeLoader::radius);
310 }
311
312 template<typename T, unsigned D>
313 inline HyperSphere<T, D> *ShapeLoader<HyperSphere<T, D> >::create() const
314 {
315         return new HyperSphere<T, D>(radius_);
316 }
317
318 template<typename T, unsigned D>
319 inline void ShapeLoader<HyperSphere<T, D> >::radius(T r)
320 {
321         radius_ = r;
322 }
323
324
325 template<typename T, unsigned D>
326 inline Negation<T, D> *ShapeLoader<Negation<T, D> >::create() const
327 {
328         return new Negation<T, D>(*this->shapes.front());
329 }
330
331
332 template<typename T, unsigned D>
333 inline TransformationLoader<T, D>::TransformationLoader()
334 {
335         this->add("translate", &TransformationLoader::translate);
336         this->add("scale", &TransformationLoader::scale);
337         this->add("shear", &TransformationLoader::shear);
338 }
339
340 template<typename T, unsigned D>
341 inline TransformedShape<T, D> *TransformationLoader<T, D>::create() const
342 {
343         return new TransformedShape<T, D>(*this->shapes.front(), transformation);
344 }
345
346 template<typename T, unsigned D>
347 inline void TransformationLoader<T, D>::translate(const std::vector<T> &offset)
348 {
349         if(offset.size()!=D)
350                 throw std::invalid_argument("TransformationLoader::translate");
351
352         transformation *= AffineTransform<T, D>::translation(LinAl::Vector<T, D>(&offset[0]));
353 }
354
355 template<typename T, unsigned D>
356 inline void TransformationLoader<T, D>::scale(const std::vector<T> &s)
357 {
358         if(s.size()!=1 && s.size()!=D)
359                 throw std::invalid_argument("TransformationLoader::scale");
360
361         if(s.size()==1)
362         {
363                 LinAl::Vector<T, D> us;
364                 for(unsigned i=0; i<D; ++i)
365                         us[i] = s.front();
366                 transformation *= AffineTransform<T, D>::scaling(us);
367         }
368         else
369                 transformation *= AffineTransform<T, D>::scaling(LinAl::Vector<T, D>(&s[0]));
370 }
371
372 template<typename T, unsigned D>
373 inline void TransformationLoader<T, D>::shear(const std::vector<T> &s)
374 {
375         if(s.size()!=2*D)
376                 throw std::invalid_argument("TransformationLoader::shear");
377
378         transformation *= AffineTransform<T, D>::shear(LinAl::Vector<T, D>(&s[0]), LinAl::Vector<T, D>(&s[D]));
379 }
380
381
382 template<typename T>
383 inline ShapeLoader<TransformedShape<T, 2> >::ShapeLoader()
384 {
385         this->add("rotate", &ShapeLoader::rotate);
386 }
387
388 template<typename T>
389 inline void ShapeLoader<TransformedShape<T, 2> >::rotate(T a)
390 {
391         TransformationLoader<T, 2>::transformation *= AffineTransform<T, 2>::rotation(Angle<T>::from_degrees(a));
392 }
393
394
395 template<typename T>
396 inline ShapeLoader<TransformedShape<T, 3> >::ShapeLoader()
397 {
398         this->add("rotate", &ShapeLoader::rotate);
399 }
400
401 template<typename T>
402 inline void ShapeLoader<TransformedShape<T, 3> >::rotate(T a, T x, T y, T z)
403 {
404         TransformationLoader<T, 3>::transformation *= AffineTransform<T, 3>::rotation(Angle<T>::from_degrees(a), LinAl::Vector<T, 3>(x, y, z));
405 }
406
407
408 template<typename T, unsigned D, typename S>
409 inline CompositeLoader<T, D, S>::CompositeLoader():
410         Loader<T, D>(false)
411 { }
412
413 template<typename T, unsigned D, typename S>
414 inline S *CompositeLoader<T, D, S>::create() const
415 {
416         if(this->shapes.empty())
417                 throw std::runtime_error("no shapes");
418         return S::from_iterator_range(this->shapes.begin(), this->shapes.end()).clone();
419 }
420
421 } // namespace Geometry
422 } // namespace Msp
423
424 #endif