00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef WFMATH_ATLAS_CONV_H
00032 #define WFMATH_ATLAS_CONV_H
00033
00034 #include <stdexcept>
00035 #include <wfmath/const.h>
00036 #include <wfmath/point.h>
00037 #include <wfmath/vector.h>
00038 #include <wfmath/quaternion.h>
00039 #include <wfmath/axisbox.h>
00040 #include <wfmath/polygon.h>
00041 #include <wfmath/ball.h>
00042 #include <wfmath/rotbox.h>
00043
00044 namespace WFMath {
00045
00046 #ifdef ATLAS_MESSAGE_ELEMENT_H
00047
00048 typedef Atlas::Message::WrongTypeException _AtlasBadParse;
00049 typedef Atlas::Message::Element _AtlasMessageType;
00050 typedef Atlas::Message::FloatType _AtlasFloatType;
00051 typedef Atlas::Message::ListType _AtlasListType;
00052 typedef Atlas::Message::MapType _AtlasMapType;
00053
00054 inline bool _isNum(const _AtlasMessageType& a) {return a.isNum();}
00055 inline _AtlasFloatType _asNum(const _AtlasMessageType& a) {return a.asNum();}
00056
00057 #elif defined(ATLAS_MESSAGE_OBJECT_H)
00058
00059 struct _AtlasBadParse : public Atlas::Message::WrongTypeException,
00060 virtual public std::exception
00061 {
00062 virtual ~_AtlasBadParse() throw() {}
00063 };
00064
00065 typedef Atlas::Message::Object _AtlasMessageType;
00066 typedef Atlas::Message::Object::FloatType _AtlasFloatType;
00067 typedef Atlas::Message::Object::ListType _AtlasListType;
00068 typedef Atlas::Message::Object::MapType _AtlasMapType;
00069
00070 inline bool _isNum(const _AtlasMessageType& a) {return a.IsNum();}
00071 inline _AtlasMessageType::FloatType _asNum(const _AtlasMessageType& a) {return a.AsNum();}
00072
00073 #else
00074 #error "You must include Atlas/Message/Element.h or Atlas/Message/Object.h before wfmath/atlasconv.h"
00075 #endif
00076
00077 class AtlasInType
00078 {
00079 public:
00080 AtlasInType(const _AtlasMessageType& val) : m_val(val) {}
00081
00082 template<class C> AtlasInType(C c) : m_obj(c), m_val(m_obj) {}
00083 operator const _AtlasMessageType&() const {return m_val;}
00084 #ifdef ATLAS_MESSAGE_ELEMENT_H
00085 bool IsList() const {return m_val.isList();}
00086 const _AtlasListType& AsList() const {return m_val.asList();}
00087 #else // ATLAS_MESSAGE_OBJECT_H
00088 bool IsList() const {return m_val.IsList();}
00089 const _AtlasListType& AsList() const {return m_val.AsList();}
00090 #endif
00091 private:
00092 _AtlasMessageType m_obj;
00093 const _AtlasMessageType& m_val;
00094 };
00095
00096 class AtlasOutType
00097 {
00098 public:
00099 AtlasOutType(const _AtlasListType& l) : m_val(l) {}
00100 AtlasOutType(const _AtlasMapType& l) : m_val(l) {}
00101 operator _AtlasMessageType&() {return m_val;}
00102 operator const _AtlasMessageType&() const {return m_val;}
00103 private:
00104 _AtlasMessageType m_val;
00105 };
00106
00107 inline AtlasOutType _ArrayToAtlas(const CoordType* array, unsigned len)
00108 {
00109 _AtlasListType a(len);
00110
00111 for(unsigned i = 0; i < len; ++i)
00112 a[i] = array[i];
00113
00114 return a;
00115 }
00116
00117 inline void _ArrayFromAtlas(CoordType* array, unsigned len, const AtlasInType& a)
00118 {
00119 if(!a.IsList())
00120 throw _AtlasBadParse();
00121
00122 const _AtlasListType& list(a.AsList());
00123
00124 if(list.size() != (unsigned int) len)
00125 throw _AtlasBadParse();
00126
00127 for(unsigned i = 0; i < len; ++i)
00128 array[i] = _asNum(list[i]);
00129 }
00130
00131 template<const int dim>
00132 inline Vector<dim>::Vector(const AtlasInType& a)
00133 {
00134 fromAtlas(a);
00135 }
00136
00137 template<const int dim>
00138 inline void Vector<dim>::fromAtlas(const AtlasInType& a)
00139 {
00140 _ArrayFromAtlas(m_elem, dim, a);
00141 m_valid = true;
00142 }
00143
00144 template<const int dim>
00145 inline AtlasOutType Vector<dim>::toAtlas() const
00146 {
00147 return _ArrayToAtlas(m_elem, dim);
00148 }
00149
00150 inline void Quaternion::fromAtlas(const AtlasInType& a)
00151 {
00152 if(!a.IsList())
00153 throw _AtlasBadParse();
00154
00155
00156 const _AtlasListType& list(a.AsList());
00157
00158 if(list.size() != 4)
00159 throw _AtlasBadParse();
00160
00161
00162 for(int i = 0; i < 3; ++i)
00163 m_vec[i] = _asNum(list[i]);
00164
00165 m_w = _asNum(list[3]);
00166
00167 CoordType norm = sqrt(m_w * m_w + m_vec.sqrMag());
00168
00169 if (norm <= WFMATH_EPSILON) {
00170 m_valid = false;
00171 m_vec.setValid(false);
00172 return;
00173 }
00174
00175 m_vec /= norm;
00176 m_w /= norm;
00177
00178 m_valid = true;
00179 m_age = 1;
00180 m_vec.setValid();
00181 }
00182
00183 inline AtlasOutType Quaternion::toAtlas() const
00184 {
00185 _AtlasListType a(4);
00186
00187 for(int i = 0; i < 3; ++i)
00188 a[i] = m_vec[i];
00189 a[3] = m_w;
00190
00191 return a;
00192 }
00193
00194 template<const int dim>
00195 inline Point<dim>::Point(const AtlasInType& a)
00196 {
00197 fromAtlas(a);
00198 }
00199
00200 template<const int dim>
00201 inline void Point<dim>::fromAtlas(const AtlasInType& a)
00202 {
00203 _ArrayFromAtlas(m_elem, dim, a);
00204 m_valid = true;
00205 }
00206
00207 template<const int dim>
00208 inline AtlasOutType Point<dim>::toAtlas() const
00209 {
00210 return _ArrayToAtlas(m_elem, dim);
00211 }
00212
00213 template<const int dim>
00214 inline AxisBox<dim>::AxisBox(const AtlasInType& a)
00215 {
00216 fromAtlas(a);
00217 }
00218
00219 template<const int dim>
00220 inline void AxisBox<dim>::fromAtlas(const AtlasInType& a)
00221 {
00222 if(!a.IsList())
00223 throw _AtlasBadParse();
00224
00225 const _AtlasListType& list(a.AsList());
00226
00227 switch(list.size()) {
00228 case dim:
00229 m_low.setToOrigin();
00230 m_high.fromAtlas(a);
00231 break;
00232 case (2 * dim):
00233 for(int i = 0; i < dim; ++i) {
00234 m_low[i] = _asNum(list[i]);
00235 m_high[i] = _asNum(list[i+dim]);
00236 }
00237 m_low.setValid();
00238 m_high.setValid();
00239 break;
00240 default:
00241 throw _AtlasBadParse();
00242 }
00243
00244 for(int i = 0; i < dim; ++i) {
00245 if(m_low[i] > m_high[i]) {
00246 CoordType tmp = m_low[i];
00247 m_low[i] = m_high[i];
00248 m_high[i] = tmp;
00249 }
00250 }
00251 }
00252
00253 template<const int dim>
00254 inline AtlasOutType AxisBox<dim>::toAtlas() const
00255 {
00256 int i;
00257
00258 for(i = 0; i < dim; ++i)
00259 if(m_low[i] != 0)
00260 break;
00261
00262 if(i == dim)
00263 return m_high.toAtlas();
00264
00265
00266
00267 _AtlasListType a(2*dim);
00268 for(i = 0; i < dim; ++i) {
00269 a[i] = m_low[i];
00270 a[dim+i] = m_high[i];
00271 }
00272
00273 return a;
00274 }
00275
00276 template<const int dim>
00277 inline void Ball<dim>::fromAtlas(const AtlasInType& a)
00278 {
00279 const _AtlasMessageType& message(a);
00280 if (message.isMap()) {
00281 const Atlas::Message::MapType& shapeElement(message.asMap());
00282
00283 Atlas::Message::MapType::const_iterator shape_I = shapeElement.find("radius");
00284 if (shape_I != shapeElement.end()) {
00285 const Atlas::Message::Element& shapeRadiusElem(shape_I->second);
00286 if (shapeRadiusElem.isNum()) {
00287 m_radius = shapeRadiusElem.asNum();
00288 }
00289 }
00290 Atlas::Message::MapType::const_iterator pos_I = shapeElement.find("position");
00291 if (pos_I != shapeElement.end()) {
00292 const Atlas::Message::Element& posElem(pos_I->second);
00293 if (posElem.isList()) {
00294 m_center.fromAtlas(posElem);
00295 }
00296 }
00297 }
00298 }
00299
00300 template<const int dim>
00301 inline AtlasOutType Ball<dim>::toAtlas() const
00302 {
00303 Atlas::Message::MapType map;
00304 map.insert(Atlas::Message::MapType::value_type("radius", _AtlasFloatType(m_radius)));
00305 map.insert(Atlas::Message::MapType::value_type("position", m_center.toAtlas()));
00306 return map;
00307 }
00308
00309 inline void Polygon<2>::fromAtlas(const AtlasInType& a)
00310 {
00311 const _AtlasMessageType& message(a);
00312 if (message.isMap()) {
00313 const Atlas::Message::MapType& shapeElement(message.asMap());
00314 Atlas::Message::MapType::const_iterator it = shapeElement.find("points");
00315 if ((it != shapeElement.end()) && it->second.isList()) {
00316 const Atlas::Message::ListType& pointsData(it->second.asList());
00317
00318 for (size_t p = 0; p < pointsData.size(); ++p) {
00319 if (!pointsData[p].isList()) {
00320 continue;
00321 }
00322
00323 const Atlas::Message::ListType& point(pointsData[p].asList());
00324 if ((point.size() < 2) || !point[0].isNum() || !point[1].isNum()) {
00325 continue;
00326 }
00327
00328 WFMath::Point<2> wpt(point[0].asNum(), point[1].asNum());
00329 addCorner(numCorners(), wpt);
00330 }
00331 if (numCorners() > 2) {
00332 return;
00333 }
00334 }
00335 }
00336 throw _AtlasBadParse();
00337 }
00338
00339 inline AtlasOutType Polygon<2>::toAtlas() const
00340 {
00341 Atlas::Message::ListType points;
00342 for (theConstIter I = m_points.begin(); I != m_points.end(); ++I)
00343 {
00344 points.push_back(I->toAtlas());
00345 }
00346 Atlas::Message::MapType map;
00347 map.insert(Atlas::Message::MapType::value_type("points", points));
00348 return map;
00349 }
00350
00351
00352 template<const int dim>
00353 inline void RotBox<dim>::fromAtlas(const AtlasInType& a)
00354 {
00355 const _AtlasMessageType& message(a);
00356 if (message.isMap()) {
00357 const Atlas::Message::MapType& shapeElement(message.asMap());
00358
00359 Atlas::Message::MapType::const_iterator shape_I = shapeElement.find("point");
00360 if (shape_I != shapeElement.end()) {
00361 const Atlas::Message::Element& shapePointElem(shape_I->second);
00362 WFMath::Point<dim> shapePoint;
00363 shapePoint.fromAtlas(shapePointElem);
00364
00365 shape_I = shapeElement.find("size");
00366 if (shape_I != shapeElement.end()) {
00367 const Atlas::Message::Element& shapeVectorElem(shape_I->second);
00368 WFMath::Vector<dim> shapeVector;
00369 shapeVector.fromAtlas(shapeVectorElem);
00370 m_corner0 = shapePoint;
00371 m_size = shapeVector;
00372 m_orient = WFMath::RotMatrix<dim>().identity();
00373 return;
00374 }
00375 }
00376 }
00377 throw _AtlasBadParse();
00378 }
00379
00380 template<const int dim>
00381 inline AtlasOutType RotBox<dim>::toAtlas() const
00382 {
00383 Atlas::Message::MapType map;
00384 map.insert(Atlas::Message::MapType::value_type("point", m_corner0.toAtlas()));
00385 map.insert(Atlas::Message::MapType::value_type("size", m_size.toAtlas()));
00386
00387 return map;
00388 }
00389
00390 }
00391
00392 #endif // WFMATH_ATLAS_CONV_H