WFMath  0.3.12
atlasconv.h
1 // atlasconv.h (Functions to convert WFMath library object to/from an Atlas Message)
2 //
3 // The WorldForge Project
4 // Copyright (C) 2001 The WorldForge Project
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //
20 // For information about WorldForge and its authors, please contact
21 // the Worldforge Web Site at http://www.worldforge.org.
22 
23 // Author: Ron Steinke
24 // Created: 2001-12-11
25 
26 // Since we don't want WFMath and Atlas to depend on each other,
27 // we're putting all the atlas interface functions into this header.
28 
29 // WARNING! WARNING! Do not include this file in any other file in wfmath.
30 
31 #ifndef WFMATH_ATLAS_CONV_H
32 #define WFMATH_ATLAS_CONV_H
33 
34 #include <wfmath/point.h>
35 #include <wfmath/vector.h>
36 #include <wfmath/quaternion.h>
37 #include <wfmath/axisbox.h>
38 #include <wfmath/polygon.h>
39 #include <wfmath/ball.h>
40 #include <wfmath/rotbox.h>
41 
42 #include <cmath>
43 
44 namespace WFMath {
45 
46 #ifdef ATLAS_MESSAGE_ELEMENT_H
47 
48 typedef Atlas::Message::WrongTypeException _AtlasBadParse;
49 typedef Atlas::Message::Element _AtlasMessageType;
50 typedef Atlas::Message::FloatType _AtlasFloatType;
51 typedef Atlas::Message::ListType _AtlasListType;
52 typedef Atlas::Message::MapType _AtlasMapType;
53 
54 inline bool _isNum(const _AtlasMessageType& a) {return a.isNum();}
55 inline _AtlasFloatType _asNum(const _AtlasMessageType& a) {return a.asNum();}
56 
57 #else
58 #error "You must include Atlas/Message/Element.h before wfmath/atlasconv.h"
59 #endif
60 
61 class AtlasInType
62 {
63  public:
64  AtlasInType(const _AtlasMessageType& val) : m_val(val) {}
65  // allow nice conversions when necessary
66  template<class C> AtlasInType(C c) : m_obj(c), m_val(m_obj) {}
67  operator const _AtlasMessageType&() const {return m_val;}
68  bool IsList() const {return m_val.isList();}
69  const _AtlasListType& AsList() const {return m_val.asList();}
70  private:
71  _AtlasMessageType m_obj;
72  const _AtlasMessageType& m_val;
73 };
74 
75 class AtlasOutType
76 {
77  public:
78  AtlasOutType(const _AtlasListType& l) : m_val(l) {}
79  AtlasOutType(const _AtlasMapType& l) : m_val(l) {}
80  operator _AtlasMessageType&() {return m_val;}
81  operator const _AtlasMessageType&() const {return m_val;}
82  private:
83  _AtlasMessageType m_val;
84 };
85 
86 inline AtlasOutType _ArrayToAtlas(const CoordType* array, unsigned len)
87 {
88  _AtlasListType a(len);
89 
90  for(unsigned i = 0; i < len; ++i)
91  a[i] = array[i];
92 
93  return a;
94 }
95 
96 inline void _ArrayFromAtlas(CoordType* array, unsigned len, const AtlasInType& a)
97 {
98  if(!a.IsList())
99  throw _AtlasBadParse();
100 
101  const _AtlasListType& list(a.AsList());
102 
103  if(list.size() != (unsigned int) len)
104  throw _AtlasBadParse();
105 
106  for(unsigned i = 0; i < len; ++i)
107  array[i] = _asNum(list[i]);
108 }
109 
110 template<int dim>
111 inline Vector<dim>::Vector(const AtlasInType& a)
112 {
113  fromAtlas(a);
114 }
115 
116 template<int dim>
117 inline void Vector<dim>::fromAtlas(const AtlasInType& a)
118 {
119  _ArrayFromAtlas(m_elem, dim, a);
120  m_valid = true;
121 }
122 
123 template<int dim>
124 inline AtlasOutType Vector<dim>::toAtlas() const
125 {
126  return _ArrayToAtlas(m_elem, dim);
127 }
128 
129 inline void Quaternion::fromAtlas(const AtlasInType& a)
130 {
131  if(!a.IsList())
132  throw _AtlasBadParse();
133 
134 
135  const _AtlasListType& list(a.AsList());
136 
137  if(list.size() != 4)
138  throw _AtlasBadParse();
139 
140 
141  for(int i = 0; i < 3; ++i)
142  m_vec[i] = _asNum(list[i]);
143 
144  m_w = _asNum(list[3]);
145 
146  CoordType norm = std::sqrt(m_w * m_w + m_vec.sqrMag());
147 
148  if (norm <= WFMATH_EPSILON) {
149  m_valid = false;
150  m_vec.setValid(false);
151  return;
152  }
153 
154  m_vec /= norm;
155  m_w /= norm;
156 
157  m_valid = true;
158  m_age = 1;
159  m_vec.setValid();
160 }
161 
162 inline AtlasOutType Quaternion::toAtlas() const
163 {
164  _AtlasListType a(4);
165 
166  for(int i = 0; i < 3; ++i)
167  a[i] = m_vec[i];
168  a[3] = m_w;
169 
170  return a;
171 }
172 
173 template<int dim>
174 inline Point<dim>::Point(const AtlasInType& a)
175 {
176  fromAtlas(a);
177 }
178 
179 template<int dim>
180 inline void Point<dim>::fromAtlas(const AtlasInType& a)
181 {
182  _ArrayFromAtlas(m_elem, dim, a);
183  m_valid = true;
184 }
185 
186 template<int dim>
187 inline AtlasOutType Point<dim>::toAtlas() const
188 {
189  return _ArrayToAtlas(m_elem, dim);
190 }
191 
192 template<int dim>
193 inline AxisBox<dim>::AxisBox(const AtlasInType& a)
194 {
195  fromAtlas(a);
196 }
197 
198 template<int dim>
199 inline void AxisBox<dim>::fromAtlas(const AtlasInType& a)
200 {
201  if(!a.IsList())
202  throw _AtlasBadParse();
203 
204  const _AtlasListType& list(a.AsList());
205 
206  switch(list.size()) {
207  case dim:
208  m_low.setToOrigin();
209  m_high.fromAtlas(a);
210  break;
211  case (2 * dim):
212  for(int i = 0; i < dim; ++i) {
213  m_low[i] = _asNum(list[i]);
214  m_high[i] = _asNum(list[i+dim]);
215  }
216  m_low.setValid();
217  m_high.setValid();
218  break;
219  default:
220  throw _AtlasBadParse();
221  }
222 
223  for(int i = 0; i < dim; ++i) {
224  if(m_low[i] > m_high[i]) { // spec may allow this?
225  CoordType tmp = m_low[i];
226  m_low[i] = m_high[i];
227  m_high[i] = tmp;
228  }
229  }
230 }
231 
232 template<int dim>
233 inline AtlasOutType AxisBox<dim>::toAtlas() const
234 {
235  int i;
236 
237  for(i = 0; i < dim; ++i)
238  if(m_low[i] != 0)
239  break;
240 
241  if(i == dim)
242  return m_high.toAtlas(); // matches case 'dim' above
243 
244  // Do case '2 * dim' above
245 
246  _AtlasListType a(2*dim);
247  for(i = 0; i < dim; ++i) {
248  a[i] = m_low[i];
249  a[dim+i] = m_high[i];
250  }
251 
252  return a;
253 }
254 
255 template<int dim>
256 inline void Ball<dim>::fromAtlas(const AtlasInType& a)
257 {
258  const _AtlasMessageType& message(a);
259  if (message.isMap()) {
260  const Atlas::Message::MapType& shapeElement(message.asMap());
261  // Get sphere's radius
262  Atlas::Message::MapType::const_iterator shape_I = shapeElement.find("radius");
263  if (shape_I != shapeElement.end()) {
264  const Atlas::Message::Element& shapeRadiusElem(shape_I->second);
265  if (shapeRadiusElem.isNum()) {
266  m_radius = shapeRadiusElem.asNum();
267  }
268  }
269  Atlas::Message::MapType::const_iterator pos_I = shapeElement.find("position");
270  if (pos_I != shapeElement.end()) {
271  const Atlas::Message::Element& posElem(pos_I->second);
272  if (posElem.isList()) {
273  m_center.fromAtlas(posElem);
274  }
275  }
276  }
277 }
278 
279 template<int dim>
280 inline AtlasOutType Ball<dim>::toAtlas() const
281 {
282  Atlas::Message::MapType map;
283  map.insert(Atlas::Message::MapType::value_type("radius", _AtlasFloatType(m_radius)));
284  map.insert(Atlas::Message::MapType::value_type("position", m_center.toAtlas()));
285  return map;
286 }
287 
288 template<int dim>
289 inline Ball<dim>::Ball(const AtlasInType& a) : m_center(Point<dim>::ZERO()),
290  m_radius(0)
291 {
292  fromAtlas(a);
293 }
294 
295 template<template <int> class ShapeT, int dim>
296 inline void _CornersFromAtlas(ShapeT<dim> & shape,
297  const _AtlasMessageType& message)
298 {
299  if (message.isList()) {
300  const Atlas::Message::ListType& pointsData(message.asList());
301 
302  for (size_t p = 0; p < pointsData.size(); ++p) {
303  if (!pointsData[p].isList()) {
304  continue;
305  }
306 
307  const Atlas::Message::ListType& point(pointsData[p].asList());
308  if ((point.size() < dim) || !point[0].isNum() || !point[1].isNum()) {
309  continue;
310  }
311 
312  WFMath::Point<dim> wpt(point[0].asNum(), point[1].asNum());
313  shape.addCorner(shape.numCorners(), wpt);
314  }
315  }
316 }
317 
318 inline void Polygon<2>::fromAtlas(const AtlasInType& a)
319 {
320  const _AtlasMessageType& message(a);
321  if (message.isMap()) {
322  const Atlas::Message::MapType& shapeElement(message.asMap());
323  Atlas::Message::MapType::const_iterator it = shapeElement.find("points");
324  if ((it != shapeElement.end()) && it->second.isList()) {
325  _CornersFromAtlas(*this, it->second);
326  if (numCorners() > 2) {
327  return;
328  }
329  }
330  } else if (message.isList()) {
331  _CornersFromAtlas(*this, message);
332  if (numCorners() > 2) {
333  return;
334  }
335  }
336  throw _AtlasBadParse();
337 }
338 
339 inline AtlasOutType Polygon<2>::toAtlas() const
340 {
341  Atlas::Message::ListType points;
342  for (theConstIter I = m_points.begin(); I != m_points.end(); ++I)
343  {
344  points.push_back(I->toAtlas());
345  }
346  Atlas::Message::MapType map;
347  map.insert(Atlas::Message::MapType::value_type("points", points));
348  return map;
349 }
350 
351 
352 template<int dim>
353 inline void RotBox<dim>::fromAtlas(const AtlasInType& a)
354 {
355  const _AtlasMessageType& message(a);
356  if (message.isMap()) {
357  const Atlas::Message::MapType& shapeElement(message.asMap());
358  // Get rotbox's position
359  Atlas::Message::MapType::const_iterator shape_I = shapeElement.find("point");
360  if (shape_I != shapeElement.end()) {
361  const Atlas::Message::Element& shapePointElem(shape_I->second);
362  WFMath::Point<dim> shapePoint;
363  shapePoint.fromAtlas(shapePointElem);
364  // Get rotbox's vector
365  shape_I = shapeElement.find("size");
366  if (shape_I != shapeElement.end()) {
367  const Atlas::Message::Element& shapeVectorElem(shape_I->second);
368  WFMath::Vector<dim> shapeVector;
369  shapeVector.fromAtlas(shapeVectorElem);
370  m_corner0 = shapePoint;
371  m_size = shapeVector;
372  m_orient = WFMath::RotMatrix<dim>().identity(); //TODO: parse rotation matrix (is it needed?)
373  return;
374  }
375  }
376  }
377  throw _AtlasBadParse();
378 }
379 
380 template<int dim>
381 inline AtlasOutType RotBox<dim>::toAtlas() const
382 {
383  Atlas::Message::MapType map;
384  map.insert(Atlas::Message::MapType::value_type("point", m_corner0.toAtlas()));
385  map.insert(Atlas::Message::MapType::value_type("size", m_size.toAtlas()));
386  //TODO: also add the rotmatrix
387  return map;
388 }
389 
390 template<int dim>
391 inline RotBox<dim>::RotBox(const AtlasInType& a) {
392  fromAtlas(a);
393 }
394 
395 } // namespace WFMath
396 
397 #endif // WFMATH_ATLAS_CONV_H
Vector()
Construct an uninitialized vector.
Definition: vector.h:125
RotBox()
construct an uninitialized box
Definition: rotbox.h:50
void fromAtlas(const AtlasInType &a)
Set the box's value to that given by an Atlas object.
Definition: atlasconv.h:353
void fromAtlas(const AtlasInType &a)
Set the box's value to that given by an Atlas object.
Definition: atlasconv.h:256
A dim dimensional rotation matrix. Technically, a member of the group O(dim).
Definition: const.h:53
CoordType sqrMag() const
The squared magnitude of a vector.
Definition: vector_funcs.h:284
A polygon, all of whose points lie in a plane, embedded in dim dimensions.
Definition: const.h:51
AtlasOutType toAtlas() const
Create an Atlas object from the box.
Definition: atlasconv.h:280
AtlasOutType toAtlas() const
Create an Atlas object from the box.
Definition: atlasconv.h:381
void fromAtlas(const AtlasInType &a)
Set the point's value to that given by an Atlas object.
Definition: atlasconv.h:180
void setValid(bool valid=true)
make isValid() return true if you've initialized the vector by hand
Definition: vector.h:154
A dim dimensional vector.
Definition: const.h:55
Ball()
construct an uninitialized ball
Definition: ball.h:64
Point()
Construct an uninitialized point.
Definition: point.h:100
AtlasOutType toAtlas() const
Create an Atlas object from the point.
Definition: atlasconv.h:187
float CoordType
Basic floating point type.
Definition: const.h:79
AtlasOutType toAtlas() const
Create an Atlas object from the Quaternion.
Definition: atlasconv.h:162
AxisBox()
Construct an uninitialized box.
Definition: axisbox.h:66
void fromAtlas(const AtlasInType &a)
Set the box's value to that given by an Atlas object.
Definition: atlasconv.h:199
AtlasOutType toAtlas() const
Create an Atlas object from the vector.
Definition: atlasconv.h:124
void fromAtlas(const AtlasInType &a)
Set the vector's value to that given by an Atlas object.
Definition: atlasconv.h:117
void fromAtlas(const AtlasInType &a)
Set the Quaternion's value to that given by an Atlas object.
Definition: atlasconv.h:129
AtlasOutType toAtlas() const
Create an Atlas object from the box.
Definition: atlasconv.h:233
A dim dimensional point.
Definition: const.h:50