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 <wfmath/point.h>
00035 #include <wfmath/vector.h>
00036 #include <wfmath/quaternion.h>
00037 #include <wfmath/axisbox.h>
00038 #include <wfmath/polygon.h>
00039 #include <wfmath/ball.h>
00040 #include <wfmath/rotbox.h>
00041 #include <wfmath/line.h>
00042
00043 #include <cmath>
00044
00045 namespace WFMath {
00046
00047 #ifndef ATLAS_MESSAGE_ELEMENT_H
00048 #error "You must include Atlas/Message/Element.h before wfmath/atlasconv.h"
00049 #endif
00050
00051 typedef Atlas::Message::WrongTypeException _AtlasBadParse;
00052
00053 class AtlasInType
00054 {
00055 public:
00056 AtlasInType(const Atlas::Message::Element& val) : m_val(val) {}
00057
00058 template<class C> AtlasInType(C c) : m_obj(c), m_val(m_obj) {}
00059 operator const Atlas::Message::Element&() const {return m_val;}
00060 bool IsList() const {return m_val.isList();}
00061 const Atlas::Message::ListType& AsList() const {return m_val.asList();}
00062 private:
00063 Atlas::Message::Element m_obj;
00064 const Atlas::Message::Element& m_val;
00065 };
00066
00067 class AtlasOutType
00068 {
00069 public:
00070 AtlasOutType(const Atlas::Message::ListType& l) : m_val(l) {}
00071 AtlasOutType(const Atlas::Message::MapType& l) : m_val(l) {}
00072 operator Atlas::Message::Element&() {return m_val;}
00073 operator const Atlas::Message::Element&() const {return m_val;}
00074 private:
00075 Atlas::Message::Element m_val;
00076 };
00077
00078 inline AtlasOutType _ArrayToAtlas(const CoordType* array, unsigned len)
00079 {
00080 Atlas::Message::ListType a(len);
00081
00082 for(unsigned i = 0; i < len; ++i)
00083 a[i] = array[i];
00084
00085 return a;
00086 }
00087
00088 inline void _ArrayFromAtlas(CoordType* array, unsigned len, const AtlasInType& a)
00089 {
00090 if(!a.IsList())
00091 throw _AtlasBadParse();
00092
00093 const Atlas::Message::ListType& list(a.AsList());
00094
00095 if(list.size() != (unsigned int) len)
00096 throw _AtlasBadParse();
00097
00098 for(unsigned i = 0; i < len; ++i)
00099 array[i] = list[i].asNum();
00100 }
00101
00102 template<int dim>
00103 inline Vector<dim>::Vector(const AtlasInType& a)
00104 {
00105 fromAtlas(a);
00106 }
00107
00108 template<int dim>
00109 inline void Vector<dim>::fromAtlas(const AtlasInType& a)
00110 {
00111 _ArrayFromAtlas(m_elem, dim, a);
00112 m_valid = true;
00113 }
00114
00115 template<int dim>
00116 inline AtlasOutType Vector<dim>::toAtlas() const
00117 {
00118 return _ArrayToAtlas(m_elem, dim);
00119 }
00120
00121 inline void Quaternion::fromAtlas(const AtlasInType& a)
00122 {
00123 if(!a.IsList())
00124 throw _AtlasBadParse();
00125
00126
00127 const Atlas::Message::ListType& list(a.AsList());
00128
00129 if(list.size() != 4)
00130 throw _AtlasBadParse();
00131
00132
00133 for(int i = 0; i < 3; ++i)
00134 m_vec[i] = list[i].asNum();
00135
00136 m_w = list[3].asNum();
00137
00138 CoordType norm = std::sqrt(m_w * m_w + m_vec.sqrMag());
00139
00140 if (norm <= numeric_constants<CoordType>::epsilon()) {
00141 m_valid = false;
00142 m_vec.setValid(false);
00143 return;
00144 }
00145
00146 m_vec /= norm;
00147 m_w /= norm;
00148
00149 m_valid = true;
00150 m_age = 1;
00151 m_vec.setValid();
00152 }
00153
00154 inline AtlasOutType Quaternion::toAtlas() const
00155 {
00156 Atlas::Message::ListType a(4);
00157
00158 for(int i = 0; i < 3; ++i)
00159 a[i] = m_vec[i];
00160 a[3] = m_w;
00161
00162 return a;
00163 }
00164
00165 template<int dim>
00166 inline Point<dim>::Point(const AtlasInType& a)
00167 {
00168 fromAtlas(a);
00169 }
00170
00171 template<int dim>
00172 inline void Point<dim>::fromAtlas(const AtlasInType& a)
00173 {
00174 _ArrayFromAtlas(m_elem, dim, a);
00175 m_valid = true;
00176 }
00177
00178 template<int dim>
00179 inline AtlasOutType Point<dim>::toAtlas() const
00180 {
00181 return _ArrayToAtlas(m_elem, dim);
00182 }
00183
00184 template<int dim>
00185 inline AxisBox<dim>::AxisBox(const AtlasInType& a)
00186 {
00187 fromAtlas(a);
00188 }
00189
00190 template<int dim>
00191 inline void AxisBox<dim>::fromAtlas(const AtlasInType& a)
00192 {
00193 if(!a.IsList())
00194 throw _AtlasBadParse();
00195
00196 const Atlas::Message::ListType& list(a.AsList());
00197
00198 switch(list.size()) {
00199 case dim:
00200 m_low.setToOrigin();
00201 m_high.fromAtlas(a);
00202 break;
00203 case (2 * dim):
00204 for(int i = 0; i < dim; ++i) {
00205 m_low[i] = list[i].asNum();
00206 m_high[i] = list[i+dim].asNum();
00207 }
00208 m_low.setValid();
00209 m_high.setValid();
00210 break;
00211 default:
00212 throw _AtlasBadParse();
00213 }
00214
00215 for(int i = 0; i < dim; ++i) {
00216 if(m_low[i] > m_high[i]) {
00217 CoordType tmp = m_low[i];
00218 m_low[i] = m_high[i];
00219 m_high[i] = tmp;
00220 }
00221 }
00222 }
00223
00224 template<int dim>
00225 inline AtlasOutType AxisBox<dim>::toAtlas() const
00226 {
00227 int i;
00228
00229 for(i = 0; i < dim; ++i)
00230 if(m_low[i] != 0)
00231 break;
00232
00233 if(i == dim)
00234 return m_high.toAtlas();
00235
00236
00237
00238 Atlas::Message::ListType a(2*dim);
00239 for(i = 0; i < dim; ++i) {
00240 a[i] = m_low[i];
00241 a[dim+i] = m_high[i];
00242 }
00243
00244 return a;
00245 }
00246
00247 template<int dim>
00248 inline void Ball<dim>::fromAtlas(const AtlasInType& a)
00249 {
00250 const Atlas::Message::Element& message(a);
00251 if (message.isMap()) {
00252 const Atlas::Message::MapType& shapeElement(message.asMap());
00253
00254 Atlas::Message::MapType::const_iterator shape_I = shapeElement.find("radius");
00255 if (shape_I != shapeElement.end()) {
00256 const Atlas::Message::Element& shapeRadiusElem(shape_I->second);
00257 if (shapeRadiusElem.isNum()) {
00258 m_radius = shapeRadiusElem.asNum();
00259 }
00260 }
00261 Atlas::Message::MapType::const_iterator pos_I = shapeElement.find("position");
00262 if (pos_I != shapeElement.end()) {
00263 const Atlas::Message::Element& posElem(pos_I->second);
00264 if (posElem.isList()) {
00265 m_center.fromAtlas(posElem);
00266 }
00267 }
00268 }
00269 }
00270
00271 template<int dim>
00272 inline AtlasOutType Ball<dim>::toAtlas() const
00273 {
00274 Atlas::Message::MapType map;
00275 map.insert(Atlas::Message::MapType::value_type("radius", m_radius));
00276 map.insert(Atlas::Message::MapType::value_type("position", m_center.toAtlas()));
00277 return map;
00278 }
00279
00280 template<int dim>
00281 inline Ball<dim>::Ball(const AtlasInType& a) : m_center(Point<dim>::ZERO()),
00282 m_radius(0)
00283 {
00284 fromAtlas(a);
00285 }
00286
00287 inline bool _ListNumCheck(const Atlas::Message::ListType & list, int dim)
00288 {
00289 for(int i = 0; i < dim; ++i) {
00290 if (!list[i].isNum()) {
00291 return false;
00292 }
00293 }
00294 return true;
00295 }
00296
00297 template<template <int> class ShapeT>
00298 inline void _AddCorner(ShapeT<3> & shape,
00299 const Atlas::Message::ListType & point)
00300 {
00301 Point<3> wpt(point[0].asNum(), point[1].asNum(), point[2].asNum());
00302 shape.addCorner(shape.numCorners(), wpt);
00303 }
00304
00305 template<template <int> class ShapeT>
00306 inline void _AddCorner(ShapeT<2> & shape,
00307 const Atlas::Message::ListType & point)
00308 {
00309 Point<2> wpt(point[0].asNum(), point[1].asNum());
00310 shape.addCorner(shape.numCorners(), wpt);
00311 }
00312
00313 template<template <int> class ShapeT, int dim>
00314 inline void _CornersFromAtlas(ShapeT<dim> & shape,
00315 const Atlas::Message::Element& message)
00316 {
00317 if (message.isList()) {
00318 const Atlas::Message::ListType& pointsData(message.asList());
00319
00320 for (size_t p = 0; p < pointsData.size(); ++p) {
00321 if (!pointsData[p].isList()) {
00322 continue;
00323 }
00324
00325 const Atlas::Message::ListType& point(pointsData[p].asList());
00326 if ((point.size() < dim) || !_ListNumCheck(point, dim)) {
00327 continue;
00328 }
00329
00330 _AddCorner(shape, point);
00331 }
00332 }
00333 }
00334
00335 inline void Polygon<2>::fromAtlas(const AtlasInType& a)
00336 {
00337 const Atlas::Message::Element& message(a);
00338 if (message.isMap()) {
00339 const Atlas::Message::MapType& shapeElement(message.asMap());
00340 Atlas::Message::MapType::const_iterator it = shapeElement.find("points");
00341 if ((it != shapeElement.end()) && it->second.isList()) {
00342 _CornersFromAtlas(*this, it->second);
00343 if (numCorners() > 2) {
00344 return;
00345 }
00346 }
00347 } else if (message.isList()) {
00348 _CornersFromAtlas(*this, message);
00349 if (numCorners() > 2) {
00350 return;
00351 }
00352 }
00353 throw _AtlasBadParse();
00354 }
00355
00356 inline AtlasOutType Polygon<2>::toAtlas() const
00357 {
00358 Atlas::Message::ListType points;
00359 for (theConstIter I = m_points.begin(); I != m_points.end(); ++I)
00360 {
00361 points.push_back(I->toAtlas());
00362 }
00363 Atlas::Message::MapType map;
00364 map.insert(Atlas::Message::MapType::value_type("points", points));
00365 return map;
00366 }
00367
00368 template<int dim>
00369 inline void Line<dim>::fromAtlas(const AtlasInType& a)
00370 {
00371 const Atlas::Message::Element& message(a);
00372 if (message.isMap()) {
00373 const Atlas::Message::MapType& shapeElement(message.asMap());
00374 Atlas::Message::MapType::const_iterator it = shapeElement.find("points");
00375 if ((it != shapeElement.end()) && it->second.isList()) {
00376 _CornersFromAtlas(*this, it->second);
00377 if (numCorners() > 0) {
00378 return;
00379 }
00380 }
00381 } else if (message.isList()) {
00382 _CornersFromAtlas(*this, message);
00383 if (numCorners() > 0) {
00384 return;
00385 }
00386 }
00387 throw _AtlasBadParse();
00388 }
00389
00390 template<int dim>
00391 inline AtlasOutType Line<dim>::toAtlas() const
00392 {
00393 Atlas::Message::ListType points;
00394 for (const_iterator I = m_points.begin(); I != m_points.end(); ++I)
00395 {
00396 points.push_back(I->toAtlas());
00397 }
00398 Atlas::Message::MapType map;
00399 map.insert(Atlas::Message::MapType::value_type("points", points));
00400 return map;
00401 }
00402
00403 template<int dim>
00404 inline Line<dim>::Line(const AtlasInType& a) {
00405 fromAtlas(a);
00406 }
00407
00408 template<int dim>
00409 inline void RotBox<dim>::fromAtlas(const AtlasInType& a)
00410 {
00411 const Atlas::Message::Element& message(a);
00412 if (message.isMap()) {
00413 const Atlas::Message::MapType& shapeElement(message.asMap());
00414
00415 Atlas::Message::MapType::const_iterator shape_I = shapeElement.find("point");
00416 if (shape_I != shapeElement.end()) {
00417 const Atlas::Message::Element& shapePointElem(shape_I->second);
00418 Point<dim> shapePoint;
00419 shapePoint.fromAtlas(shapePointElem);
00420
00421 shape_I = shapeElement.find("size");
00422 if (shape_I != shapeElement.end()) {
00423 const Atlas::Message::Element& shapeVectorElem(shape_I->second);
00424 Vector<dim> shapeVector;
00425 shapeVector.fromAtlas(shapeVectorElem);
00426 m_corner0 = shapePoint;
00427 m_size = shapeVector;
00428 m_orient = RotMatrix<dim>().identity();
00429 return;
00430 }
00431 }
00432 }
00433 throw _AtlasBadParse();
00434 }
00435
00436 template<int dim>
00437 inline AtlasOutType RotBox<dim>::toAtlas() const
00438 {
00439 Atlas::Message::MapType map;
00440 map.insert(Atlas::Message::MapType::value_type("point", m_corner0.toAtlas()));
00441 map.insert(Atlas::Message::MapType::value_type("size", m_size.toAtlas()));
00442
00443 return map;
00444 }
00445
00446 template<int dim>
00447 inline RotBox<dim>::RotBox(const AtlasInType& a) {
00448 fromAtlas(a);
00449 }
00450
00451 }
00452
00453 #endif // WFMATH_ATLAS_CONV_H