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