atlasconv.h

00001 // atlasconv.h (Functions to convert WFMath library object to/from an Atlas Message)
00002 //
00003 //  The WorldForge Project
00004 //  Copyright (C) 2001  The WorldForge Project
00005 //
00006 //  This program is free software; you can redistribute it and/or modify
00007 //  it under the terms of the GNU General Public License as published by
00008 //  the Free Software Foundation; either version 2 of the License, or
00009 //  (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 //
00020 //  For information about WorldForge and its authors, please contact
00021 //  the Worldforge Web Site at http://www.worldforge.org.
00022 
00023 // Author: Ron Steinke
00024 // Created: 2001-12-11
00025 
00026 // Since we don't want WFMath and Atlas to depend on each other,
00027 // we're putting all the atlas interface functions into this header.
00028 
00029 // WARNING! WARNING! Do not include this file in any other file in wfmath.
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 
00041 namespace WFMath {
00042 
00043 #ifdef ATLAS_MESSAGE_ELEMENT_H
00044 
00045 typedef Atlas::Message::WrongTypeException _AtlasBadParse;
00046 typedef Atlas::Message::Element _AtlasMessageType;
00047 typedef Atlas::Message::FloatType _AtlasFloatType;
00048 typedef Atlas::Message::ListType _AtlasListType;
00049 
00050 inline bool _isNum(const _AtlasMessageType& a) {return a.isNum();}
00051 inline _AtlasFloatType _asNum(const _AtlasMessageType& a) {return a.asNum();}
00052 
00053 #elif defined(ATLAS_MESSAGE_OBJECT_H)
00054 
00055 struct _AtlasBadParse : public Atlas::Message::WrongTypeException,
00056                         virtual public std::exception
00057 {
00058   virtual ~_AtlasBadParse() throw() {}
00059 };
00060 
00061 typedef Atlas::Message::Object _AtlasMessageType;
00062 typedef Atlas::Message::Object::FloatType _AtlasFloatType;
00063 typedef Atlas::Message::Object::ListType _AtlasListType;
00064 
00065 inline bool _isNum(const _AtlasMessageType& a) {return a.IsNum();}
00066 inline _AtlasMessageType::FloatType _asNum(const _AtlasMessageType& a) {return a.AsNum();}
00067 
00068 #else
00069 #error "You must include Atlas/Message/Element.h or Atlas/Message/Object.h before wfmath/atlasconv.h"
00070 #endif
00071 
00072 class AtlasInType
00073 {
00074  public:
00075   AtlasInType(const _AtlasMessageType& val) : m_val(val) {}
00076   // allow nice conversions when necessary
00077   template<class C> AtlasInType(C c) : m_obj(c), m_val(m_obj) {}
00078   operator const _AtlasMessageType&() const {return m_val;}
00079 #ifdef ATLAS_MESSAGE_ELEMENT_H
00080   bool IsList() const {return m_val.isList();}
00081   const _AtlasListType& AsList() const {return m_val.asList();}
00082 #else // ATLAS_MESSAGE_OBJECT_H
00083   bool IsList() const {return m_val.IsList();}
00084   const _AtlasListType& AsList() const {return m_val.AsList();}
00085 #endif
00086  private:
00087   _AtlasMessageType m_obj;
00088   const _AtlasMessageType& m_val;
00089 };
00090 
00091 class AtlasOutType
00092 {
00093  public:
00094   AtlasOutType(const _AtlasListType& l) : m_val(l) {}
00095   operator _AtlasMessageType&() {return m_val;}
00096   operator const _AtlasMessageType&() const {return m_val;}
00097  private:
00098   _AtlasMessageType m_val;
00099 };
00100 
00101 inline AtlasOutType _ArrayToAtlas(const CoordType* array, unsigned len)
00102 {
00103   _AtlasListType a(len);
00104 
00105   for(unsigned i = 0; i < len; ++i)
00106     a[i] = array[i];
00107 
00108   return a;
00109 }
00110 
00111 inline void _ArrayFromAtlas(CoordType* array, unsigned len, const AtlasInType& a)
00112 {
00113   if(!a.IsList())
00114     throw _AtlasBadParse();
00115 
00116   const _AtlasListType& list(a.AsList());
00117 
00118   if(list.size() != (unsigned int) len)
00119     throw _AtlasBadParse();
00120 
00121   for(unsigned i = 0; i < len; ++i)
00122     array[i] = _asNum(list[i]);
00123 }
00124 
00125 template<const int dim>
00126 inline void Vector<dim>::fromAtlas(const AtlasInType& a)
00127 {
00128   _ArrayFromAtlas(m_elem, dim, a);
00129   m_valid = true;
00130 }
00131 
00132 template<const int dim>
00133 inline AtlasOutType Vector<dim>::toAtlas() const
00134 {
00135   return _ArrayToAtlas(m_elem, dim);
00136 }
00137 
00138 inline void Quaternion::fromAtlas(const AtlasInType& a)
00139 {
00140   if(!a.IsList())
00141     throw _AtlasBadParse();
00142 
00143 
00144   const _AtlasListType& list(a.AsList());
00145 
00146   if(list.size() != 4)
00147     throw _AtlasBadParse();
00148 
00149 
00150   for(int i = 0; i < 3; ++i)
00151     m_vec[i] = _asNum(list[i]);
00152 
00153   m_w = _asNum(list[3]);
00154 
00155   CoordType norm = sqrt(m_w * m_w + m_vec.sqrMag());
00156 
00157   if (norm <= WFMATH_EPSILON) {
00158     m_valid = false;
00159     m_vec.setValid(false);
00160     return;
00161   }
00162 
00163   m_vec /= norm;
00164   m_w /= norm;
00165 
00166   m_valid = true;
00167   m_age = 1;
00168   m_vec.setValid();
00169 }
00170 
00171 inline AtlasOutType Quaternion::toAtlas() const
00172 {
00173   _AtlasListType a(4);
00174 
00175   for(int i = 0; i < 3; ++i)
00176     a[i] = m_vec[i];
00177   a[3] = m_w;
00178 
00179   return a;
00180 }
00181 
00182 template<const int dim>
00183 inline void Point<dim>::fromAtlas(const AtlasInType& a)
00184 {
00185   _ArrayFromAtlas(m_elem, dim, a);
00186   m_valid = true;
00187 }
00188 
00189 template<const int dim>
00190 inline AtlasOutType Point<dim>::toAtlas() const
00191 {
00192   return _ArrayToAtlas(m_elem, dim);
00193 }
00194 
00195 template<const int dim>
00196 void AxisBox<dim>::fromAtlas(const AtlasInType& a)
00197 {
00198   if(!a.IsList())
00199     throw _AtlasBadParse();
00200 
00201   const _AtlasListType& list(a.AsList());
00202 
00203   switch(list.size()) {
00204     case dim:
00205       m_low.setToOrigin();
00206       m_high.fromAtlas(a);
00207       break;
00208     case (2 * dim):
00209       for(int i = 0; i < dim; ++i) {
00210         m_low[i] = _asNum(list[i]);
00211         m_high[i] = _asNum(list[i+dim]);
00212       }
00213       m_low.setValid();
00214       m_high.setValid();
00215       break;
00216     default:
00217       throw _AtlasBadParse();
00218   }
00219 
00220   for(int i = 0; i < dim; ++i) {
00221     if(m_low[i] > m_high[i]) { // spec may allow this?
00222       CoordType tmp = m_low[i];
00223       m_low[i] = m_high[i];
00224       m_high[i] = tmp;
00225     }
00226   }
00227 }
00228 
00229 template<const int dim>
00230 AtlasOutType AxisBox<dim>::toAtlas() const
00231 {
00232   int i;
00233 
00234   for(i = 0; i < dim; ++i)
00235     if(m_low[i] != 0)
00236       break;
00237 
00238   if(i == dim)
00239     return m_high.toAtlas(); // matches case 'dim' above
00240 
00241   // Do case '2 * dim' above
00242 
00243   _AtlasListType a(2*dim);
00244   for(i = 0; i < dim; ++i) {
00245     a[i] = m_low[i];
00246     a[dim+i] = m_high[i];
00247   }
00248 
00249   return a;
00250 }
00251 
00252 } // namespace WFMath
00253 
00254 #endif // WFMATH_ATLAS_CONV_H

Generated on Sun Dec 16 11:40:13 2007 for WFMath by  doxygen 1.5.2