OpenWalnut  1.4.0
WTransferFunction.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 WTRANSFERFUNCTION_H
00026 #define WTRANSFERFUNCTION_H
00027 
00028 #include <iosfwd>
00029 #include <vector>
00030 
00031 #include "WColor.h"
00032 
00033 /**
00034  * A class that stores a 1D transfer function which consists
00035  * of a linear interpolation of alpha and color values.
00036  */
00037 class WTransferFunction // NOLINT problem with macro
00038 {
00039 public:
00040     /**
00041      * Default constructor of a meaningless transfer function
00042      */
00043     WTransferFunction() : m_isomin( 0. ), m_isomax( 0. )
00044     {
00045     }
00046 
00047     /**
00048      * Deep copy constructor.
00049      *
00050      * \param rhs the value to histogram
00051      */
00052     WTransferFunction( const WTransferFunction &rhs )
00053         : m_colors( rhs.m_colors ), m_alphas( rhs.m_alphas ), m_isomin( rhs.m_isomin ), m_isomax( rhs.m_isomax ), m_histogram( rhs.m_histogram )
00054     {
00055     }
00056 
00057     /**
00058      * Deep copy operator
00059      *
00060      * \param rhs the value to copy
00061      * \returns reference to current object
00062      * \returns reference to current object
00063      */
00064     WTransferFunction& operator=( const WTransferFunction &rhs )
00065     {
00066         this->m_colors = rhs.m_colors;
00067         this->m_alphas = rhs.m_alphas;
00068         this->m_isomin = rhs.m_isomin;
00069         this->m_isomax = rhs.m_isomax;
00070         this->m_histogram = rhs.m_histogram;
00071         return ( *this );
00072     }
00073 
00074     /**
00075      * Check equivalence of two transfer functions.
00076      *
00077      * \returns true if this object contains exactly the same
00078      * data as rhs
00079      * \param rhs object to compare with
00080      */
00081     bool operator==( const WTransferFunction &rhs ) const;
00082 
00083     /**
00084      * Check equivalence of two transfer functions.
00085      *
00086      * \returns negated result of operator==
00087      * \param rhs the value to compare with
00088      */
00089     bool operator!=( const WTransferFunction &rhs ) const;
00090 
00091     /**
00092      * Default destuctor.
00093      */
00094     ~WTransferFunction()
00095     {
00096     }
00097 
00098     /**
00099      * Get the number of alphas
00100      *
00101      * \returns the number of alpha points
00102      */
00103     size_t numAlphas() const
00104     {
00105         return m_alphas.size();
00106     }
00107 
00108     /**
00109      * Get the number of colors.
00110      *
00111      * \returns the number of color points
00112      */
00113     size_t numColors() const
00114     {
00115         return m_colors.size();
00116     }
00117 
00118     /**
00119      * Get the isovalue at a given index in the alpha values.
00120      *
00121      * \param i the index of the point to query
00122      * \returns the alpha values position/isovalue at index i
00123      */
00124     double getAlphaIsovalue( size_t i ) const
00125     {
00126         return m_alphas.at( i ).iso;
00127     }
00128 
00129     /**
00130      * The isovalue of the color at a given index.
00131      *
00132      * \param i the index of the point to query.
00133      * \returns the color values position/isovalue at index i
00134      */
00135     double getColorIsovalue( size_t i ) const
00136     {
00137         return m_colors.at( i ).iso;
00138     }
00139 
00140     /**
00141      * Get alpha at given index.
00142      *
00143      * \param i the index to query
00144      * \returns the alpha value at index i
00145      */
00146     double getAlpha( size_t i ) const
00147     {
00148         return m_alphas.at( i ).alpha;
00149     }
00150 
00151     /**
00152      * Get color at given index.
00153      *
00154      * \param i the index to query
00155      * \returns the color at index i
00156      */
00157     const WColor& getColor( size_t i ) const
00158     {
00159         return m_colors.at( i ).color;
00160     }
00161 
00162     /**
00163      * Insert a new color point.
00164      *
00165      * \param iso the new iso value
00166      * \param color the new color at the given iso value
00167      */
00168     void addColor( double iso, const WColor& color );
00169 
00170     /**
00171      * Insert a new alpha point.
00172      *
00173      * \param iso the new iso value
00174      * \param alpha the new alpha value at the given iso value
00175      */
00176     void addAlpha( double iso, double alpha );
00177 
00178     /**
00179      * Set the histogram going along with the transfer function
00180      *
00181      * This should be changed in the future to be handled in a different
00182      * way. A good option would be to introduce an object encapsulating
00183      * a transfer function and histogram information.
00184      *
00185      * \param data the histogram data between m_isomin and m_isomax
00186      */
00187     void setHistogram( std::vector< double > & data )
00188     {
00189         m_histogram.swap( data );
00190     }
00191 
00192     /**
00193      * Clears the histogram data so the gui won't show any
00194      */
00195     void removeHistogram()
00196     {
00197         m_histogram.clear();
00198     }
00199 
00200     /**
00201      * Returns the histogram.
00202      *
00203      * \returns a reference to the internal representation of the histogram
00204      */
00205     const std::vector< double >& getHistogram() const
00206     {
00207         return m_histogram;
00208     }
00209 
00210     /**
00211      * sample/render the transfer function linearly between min and max in an RGBA texture.
00212      * \param array pointer to an allocated data structure
00213      * \param width is the number of RGBA samples.
00214      * \param min the lowest value to be sampled
00215      * \param max the hightes value to be sampled
00216      * \post array contains the sampled data
00217      * \pre array is allocated and has space for width elements
00218      */
00219     void sample1DTransferFunction( unsigned char*array, int width, double min, double max ) const;
00220 
00221     /**
00222      * Try to estimate a transfer function from an RGBA image.
00223      *
00224      * \param rgba: values between 0 and 255 representing the red, green, and blue channel
00225      * \param size: number of color entries in rgba
00226      * \returns approximated transfer function
00227      */
00228     static WTransferFunction createFromRGBA( unsigned char const * const rgba, size_t size );
00229 private:
00230     /**
00231      * Prototype for a storage element
00232      */
00233     struct Entry
00234     {
00235         /**
00236          * Default constructor
00237          * \param iso the iso value
00238          */
00239         explicit Entry( double iso ) : iso( iso )
00240         {
00241         }
00242 
00243         /**
00244          * comparison by isovalue
00245          * \param rhs entry to compare t
00246          * \returns true if this->iso <=  rhs.iso
00247          */
00248         bool operator <= ( const Entry &rhs ) const
00249         {
00250             return iso <= rhs.iso;
00251         }
00252 
00253         /** the isovalue */
00254         double iso;
00255     };
00256 
00257     /**
00258      * Color entries are linearly interpolated colors along isovalues
00259      */
00260     struct ColorEntry : public Entry
00261     {
00262         /** default constructor
00263          * \param iso the isovalue
00264          * \param color the color at the isovalue
00265          */
00266         ColorEntry( double iso, WColor color ) : Entry( iso ), color( color )
00267         {
00268         }
00269 
00270         /**
00271          * comparison operator to check for changes
00272          * \param rhs ColorEntry to compare to
00273          * \returns true if rhs equals this
00274          */
00275         bool operator==( const ColorEntry& rhs ) const
00276         {
00277             return iso == rhs.iso && color == rhs.color;
00278         }
00279 
00280         /** holds the current color at isovalue Entry::iso */
00281         WColor color;
00282     };
00283 
00284     /**
00285      * Alpha entries represent linearly interpolated transparency values
00286      * along the isovalue scale. Alpha is in the range [ 0...1 ] where
00287      * 1 signifies entirely opaque ( which makes it more an opacity value instead
00288      * of alpha, but I use the commonly used language here )
00289      */
00290     struct AlphaEntry : public Entry
00291     {
00292         /** default constructor
00293          * \param iso the isovalue
00294          * \param alpha the alpha at the isovalue in the range from 0 = transparent to 1 = opaque
00295          */
00296          AlphaEntry( double iso, double alpha ) : Entry( iso ), alpha( alpha )
00297         {
00298         }
00299 
00300         /**
00301          * comparison operator to check for changes
00302          * \param rhs AlphaEntry to compare to
00303          * \returns true if rhs is equal to this
00304          */
00305         bool operator==( const AlphaEntry& rhs ) const
00306         {
00307             return iso == rhs.iso && alpha == rhs.alpha;
00308         }
00309 
00310         /** holds the current alpha at isovalue Entry::iso */
00311         double alpha;
00312     };
00313 
00314     /**
00315      * Templatized comparison predicate for internal searching
00316      */
00317     template<typename T>
00318     struct LessPred
00319     {
00320         /** constructs a predicate that compares for less than iso
00321          * \param iso: used iso value
00322          */
00323         explicit LessPred( double iso ) : iso( iso )
00324         {
00325         }
00326 
00327         /** isovalue-based comparison
00328          * \param t the object to compare to
00329          * \returns true if iso is less than t.iso
00330          */
00331         bool operator()( const T& t )
00332         {
00333             return iso < t.iso;
00334         }
00335 
00336         /** the isovalue to compare to */
00337         double iso;
00338     };
00339 
00340     /**
00341      * Sorted list of colors
00342      */
00343     std::vector<ColorEntry> m_colors;
00344 
00345     /**
00346      * Sorted list of alpha values.
00347      */
00348     std::vector<AlphaEntry> m_alphas;
00349 
00350     /**
00351      * The smallest used iso value.
00352      */
00353     double m_isomin;
00354 
00355     /**
00356      * The largest used iso value.
00357      */
00358     double m_isomax;
00359 
00360     /**
00361      * Sores a histogram. This is used for property-handling only
00362      * and does not change the transfer function at all.
00363      */
00364     std::vector< double > m_histogram;
00365 
00366     friend std::ostream& operator << ( std::ostream& out, const WTransferFunction& tf );
00367 };
00368 
00369 /**
00370  * Default output operator. Currently stores values the same way as it is done in the properties.
00371  * This code should only be used for debugging and you should not rely on the interface.
00372  *
00373  * \param tf The transfer function to output
00374  * \param out The stream to which we write
00375  *
00376  * \returns reference to out
00377  */
00378 std::ostream& operator << ( std::ostream& out, const WTransferFunction& tf );
00379 
00380 #endif  // WTRANSFERFUNCTION_H