OpenWalnut 1.3.1
WValueSet.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WVALUESET_H
00026 #define WVALUESET_H
00027 
00028 #include <cmath>
00029 #include <cstddef>
00030 #include <limits>
00031 #include <vector>
00032 #include <boost/shared_ptr.hpp>
00033 
00034 #include "../common/math/WValue.h"
00035 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
00036 #include "../common/WAssert.h"
00037 #include "../common/WLimits.h"
00038 #include "WDataHandlerEnums.h"
00039 #include "WValueSetBase.h"
00040 
00041 /**
00042  * Base Class for all value set types.
00043  * \ingroup dataHandler
00044  */
00045 template< typename T > class WValueSet : public WValueSetBase
00046 {
00047 /**
00048  * Only UnitTests are allowed to be friends
00049  */
00050 friend class WValueSetTest;
00051 
00052 public:
00053     /**
00054      * The type of the single value in this value set.
00055      */
00056     typedef T ValueT;
00057 
00058     /**
00059      * \class SubArray
00060      *
00061      * A helper class granting safe access to a certain part of the valueset.
00062      */
00063     class SubArray
00064     {
00065     public:
00066         //! make the valueset a friend
00067         friend class WValueSet;
00068 
00069         /**
00070          * Destructor.
00071          */
00072         ~SubArray()
00073         {
00074         }
00075 
00076         /**
00077          * Safe access. Only the const version is allowed.
00078          *
00079          * \param i The relative position of the element in the subarray's range.
00080          *
00081          * \note If i is not in ( 0, size - 1 ), the first element will be returned.
00082          *
00083          * \return the value
00084          */
00085         T const& operator[] ( std::size_t i ) const
00086         {
00087             return *( m_ptr + i * static_cast< std::size_t >( i < m_size ) );
00088         }
00089 
00090         // use the standard copy constructor and operator
00091     private:
00092         /**
00093          * Construct an object that allows safe access.
00094          * (no access to elements not in the subarray's range).
00095          * Only a valueset may construct a SubArray.
00096          *
00097          * \param p A pointer to the first element.
00098          * \param size The size of the subarray.
00099          */
00100         SubArray( T const* const p, std::size_t size )
00101             : m_ptr( p ),
00102               m_size( size )
00103         {
00104         }
00105 
00106         //! the pointer to the first element
00107         T const* const m_ptr;
00108 
00109         //! the size of the subarray
00110         std::size_t const m_size;
00111     };
00112 
00113     /**
00114      * Constructs a value set with values of type T. Sets order and dimension
00115      * to allow to interpret the values as tensors of a certain order and dimension.
00116      * \param order tensor order of values stored in the value set
00117      * \param dimension tensor dimension of values stored in the value set
00118      * \param data the vector holding the raw data
00119      * \param inDataType indicator telling us which dataType comes in
00120      */
00121     WValueSet( size_t order, size_t dimension, const boost::shared_ptr< std::vector< T > > data, dataType inDataType )
00122         : WValueSetBase( order, dimension, inDataType ),
00123           m_data( data )
00124     {
00125         // calculate min and max
00126         // Calculating this once simply ensures that it does not need to be recalculated in textures, histograms ...
00127         m_minimum = std::numeric_limits< T >::max();
00128         m_maximum = std::numeric_limits< T >::min();
00129         for( typename std::vector< T >::const_iterator iter = data->begin(); iter != data->end(); ++iter )
00130         {
00131             m_minimum = m_minimum > *iter ? *iter : m_minimum;
00132             m_maximum = m_maximum < *iter ? *iter : m_maximum;
00133         }
00134     }
00135 
00136     /**
00137      * Constructs a value set with values of type T. Sets order and dimension
00138      * to allow to interpret the values as tensors of a certain order and dimension.
00139      * \param order tensor order of values stored in the value set
00140      * \param dimension tensor dimension of values stored in the value set
00141      * \param data the vector holding the raw data
00142      */
00143     WValueSet( size_t order, size_t dimension, const boost::shared_ptr< std::vector< T > > data )
00144         : WValueSetBase( order, dimension, DataType< T >::type ),
00145           m_data( data )
00146     {
00147         // calculate min and max
00148         // Calculating this once simply ensures that it does not need to be recalculated in textures, histograms ...
00149         m_minimum = std::numeric_limits< T >::max();
00150         m_maximum = std::numeric_limits< T >::min();
00151         for( typename std::vector< T >::const_iterator iter = data->begin(); iter != data->end(); ++iter )
00152         {
00153             m_minimum = m_minimum > *iter ? *iter : m_minimum;
00154             m_maximum = m_maximum < *iter ? *iter : m_maximum;
00155         }
00156     }
00157 
00158     /**
00159      * \return The number of tensors stored in this set.
00160      */
00161     virtual size_t size() const
00162     {
00163         switch( m_order )
00164         {
00165             case 0  :  // scalar
00166                 WAssert( m_dimension == 1, "Although order zero, (dimension != 1) was found." );
00167                 return rawSize();
00168             case 1  :  // vector
00169                 WAssert( rawSize() % m_dimension == 0, "Raw size and dimension don't fit." );
00170                 return rawSize() / m_dimension;
00171             case 2  :  // matrix
00172                 WAssert( rawSize() % ( m_dimension * m_dimension ) == 0, "Raw size and dimension don't fit." );
00173                 return rawSize() / ( m_dimension * m_dimension );
00174             default :  // other
00175                 WAssert( false, "Unsupported tensor order." );
00176                 return 0;
00177         }
00178     }
00179 
00180     /**
00181      * \return The number of integral types stored in this set.
00182      */
00183     virtual size_t rawSize() const
00184     {
00185         return (*m_data.get()).size();
00186     }
00187 
00188     /**
00189      * \param i id of the scalar to retrieve
00190      * \return The i-th scalar stored in this value set. There are rawSize() such scalars.
00191      */
00192     virtual T getScalar( size_t i ) const
00193     {
00194         return (*m_data.get())[i];
00195     }
00196 
00197     /**
00198      * \param i id of the scalar to retrieve
00199      * \return The i-th scalar stored in this value set. There are rawSize() such scalars.
00200      */
00201     virtual double getScalarDouble( size_t i ) const
00202     {
00203         return static_cast< double >( (*m_data.get())[i] );
00204     }
00205 
00206     /**
00207      * \param i id of the WValue to retrieve
00208      * \return The i-th WValue stored in this value set. There are size() such scalars.
00209      */
00210     virtual WValue< double > getWValueDouble( size_t i ) const
00211     {
00212         return WValue< double >( getWValue( i ) );
00213     }
00214 
00215     /**
00216      * \param i id of the WVector to retrieve
00217      * \return The i-th WValue (stored in this value set) as WVector. There are size() such scalars.
00218      */
00219     virtual WVector_2 getWVector( size_t i ) const
00220     {
00221         return ( WValue< double >( getWValue( i ) ) ).toWVector();
00222     }
00223 
00224     /**
00225      * Get the i'th vector
00226      *
00227      * \param index the index number of the vector
00228      *
00229      * \return the vector
00230      */
00231     WVector3d getVector3D( size_t index ) const;
00232 
00233 
00234     /**
00235      * Get the i'th WValue with the dimension of WValueSet
00236      *
00237      * \param index the index number of the WValue
00238      *
00239      * \return a WValue with the dimension WValueSet
00240      */
00241     WValue< T > getWValue( size_t index ) const;
00242 
00243     /**
00244      * Sometimes we need raw access to the data array, for e.g. OpenGL.
00245      *
00246      * \return the raw data pointer
00247      */
00248     const T * rawData() const
00249     {
00250         return &(*m_data.get())[0];
00251     }
00252 
00253     /**
00254      * Sometimes we need raw access to the data vector.
00255      *
00256      * \return the data vector
00257      */
00258     const std::vector< T >* rawDataVectorPointer() const
00259     {
00260         return &(*m_data.get());
00261     }
00262 
00263     /**
00264      * Request (read-) access object to a subarray of this valueset.
00265      * The object returned by this function can be used as an array
00266      * ( starting at index 0 ), whose elements are the data elements
00267      * at positions start to ( including ) start + size - 1 of the valueset.
00268      *
00269      * \param start The position of the first element of the subarray.
00270      * \param size The number of elements in the subarray.
00271      * \return The subarray.
00272      */
00273     SubArray const getSubArray( std::size_t start, std::size_t size ) const
00274     {
00275         WAssert( start + size <= rawSize(), "" );
00276         WAssert( size != 0, "" );
00277         return SubArray( rawData() + start, size );
00278     }
00279 
00280     /**
00281      * This method returns the smallest value in the valueset. It does not handle vectors, matrices and so on well. It simply returns the
00282      * smallest value in the data array. This is especially useful for texture scaling or other statistic tools (histograms).
00283      *
00284      * \return the smallest value in the data.
00285      */
00286     virtual double getMinimumValue() const
00287     {
00288         return m_minimum;
00289     }
00290 
00291     /**
00292      * This method returns the largest value in the valueset. It does not handle vectors, matrices and so on well. It simply returns the
00293      * largest value in the data array. This is especially useful for texture scaling or other statistic tools (histograms).
00294      *
00295      * \return the largest value in the data.
00296      */
00297     virtual double getMaximumValue() const
00298     {
00299         return m_maximum;
00300     }
00301 
00302     /**
00303      * Calculates the needed number of integral values for a valueset with specified order and dimension for one voxel. The whole dataset will
00304      * then be as large as the number of voxels multiplied by this value.
00305      *
00306      * \param oder desired tensor order.
00307      * \param dimension desired dimension.
00308      *
00309      * \return the number of values needed
00310      */
00311     static size_t getRequiredRawSizePerVoxel( size_t oder, size_t dimension );
00312 protected:
00313     /**
00314      * The smallest value in m_data.
00315      */
00316     T m_minimum;
00317 
00318     /**
00319      * The largest value in m_data.
00320      */
00321     T m_maximum;
00322 
00323 private:
00324     /**
00325      * Stores the values of type T as simple array which never should be modified.
00326      */
00327     const boost::shared_ptr< std::vector< T > > m_data;  // WARNING: don't remove constness since &m_data[0] won't work anymore!
00328 
00329     /**
00330      * Get a variant reference to this valueset (the reference is stored in the variant).
00331      * \note Use this as a temporary object inside a function or something like that.
00332      * \return var A variant reference.
00333      */
00334     virtual WValueSetVariant const getVariant() const
00335     {
00336         return WValueSetVariant( this );
00337     }
00338 };
00339 
00340 template< typename T > WVector3d WValueSet< T >::getVector3D( size_t index ) const
00341 {
00342     WAssert( m_order == 1 && m_dimension == 3, "WValueSet<T>::getVector3D only implemented for order==1, dim==3 value sets" );
00343     WAssert( ( index + 1 ) * 3 <= m_data->size(), "index in WValueSet<T>::getVector3D too big" );
00344     size_t offset = index * 3;
00345     return WVector3d( ( *m_data )[offset], ( *m_data )[offset + 1], ( *m_data )[offset + 2] );
00346 }
00347 
00348 template< typename T > WValue< T > WValueSet< T >::getWValue( size_t index ) const
00349 {
00350     WAssert( m_order == 1, "WValueSet<T>::getWValue only implemented for order==1 value sets" );
00351     WAssert( ( index + 1 ) * m_dimension <= m_data->size(), "index in WValueSet<T>::getWValue too big" );
00352 
00353     size_t offset = index * m_dimension;
00354 
00355     WValue< T > result( m_dimension );
00356 
00357     // copying values
00358     for( std::size_t i = 0; i < m_dimension; i++ )
00359         result[i] = ( *m_data )[offset+i];
00360 
00361     return result;
00362 }
00363 
00364 template< typename T >
00365 size_t WValueSet< T >::getRequiredRawSizePerVoxel( size_t oder, size_t dimension )
00366 {
00367     // NOTE: std::pow works only for floating point types
00368     size_t pow = 1;
00369     for( size_t v = 0; v < oder; ++v )
00370     {
00371         pow *= dimension;
00372     }
00373 
00374     return pow;
00375 }
00376 
00377 #endif  // WVALUESET_H