MeVisLabToolboxReference
MeVisLab/Standard/Sources/ML/MLBase/mlRasterFunction.h
Go to the documentation of this file.
00001 // **InsertLicense** code
00002 //----------------------------------------------------------------------------------
00004 
00010 // This class handles two types of implicit functions which can be rastered
00011 // into a subimage with the methods \c draw().
00012 //
00013 // The first function type tests a voxel coordinate which shall be drawn or not.
00014 // The second function type tests a world coordinate which shall be rastered or not.
00015 // These functions can be set alternatively as static static function or can be
00016 // implemented as overloaded virtual method.
00017 //
00018 // For the implicit functions in world coordinates a pretransformation and
00019 // a voxel to world matrix can be defined so that transformations to the rastered
00020 // objects can be applied simply.
00021 // Note that transformations are only applied in 3d.
00022 //--------------------------------------------------------------------------------
00023 #ifndef __mlRasterFunction_H
00024 #define __mlRasterFunction_H
00025 
00026 #ifndef __mlModuleIncludes_H
00027 #include <mlModuleIncludes.h>
00028 #endif
00029 #ifndef __mlBaseInit_H
00030 #include "mlBaseInit.h"
00031 #endif
00032 #ifndef __mlSubImageBoxd_H
00033 #include "mlSubImageBoxd.h"
00034 #endif
00035 
00036 ML_START_NAMESPACE
00037 
00040 enum TestFuncMode {
00041   StaticVoxelTest,
00042   VirtualVoxelTest,
00043   StaticWorldVoxelTest,
00044   VirtualWorldVoxelTest
00045 };
00046 
00051 typedef bool (*VoxelTestFunction)(const ImageVector &p, void *userData);
00052 
00057 typedef bool (*WorldVoxelTestFunction)(const Vector6 &p,  void *userData);
00058 
00063 typedef void (*ModifierFunction)(SubImage *tSubImg, const ImageVector &p, void *userData);
00064 
00065 
00066 //===============================================================================
00068 //===============================================================================
00069 class MLBASEEXPORT RasterFunction : public Base
00070 {
00071 public:
00073     RasterFunction() : Base()                                          { _init();              }
00074     
00076     RasterFunction(const RasterFunction &f) : Base()                   { _init(); *this = f;   };
00077     
00079     virtual ~RasterFunction()                                          {};
00080     
00082     virtual const RasterFunction &operator=(const RasterFunction &f);
00083     
00085 
00086     inline void          setFunctionMode(TestFuncMode mode)            { _testFuncMode = mode; }
00087     inline TestFuncMode  getFunctionMode() const                       { return _testFuncMode; }
00089     
00095     virtual bool         isVoxelInside(const ImageVector &) const           { return false;                                 }
00096     
00102     virtual bool         isWorldVoxelInside(const Vector6 &) const        { return false;                                 }
00103     
00106 
00107     inline void          setVoxelTestFunction(VoxelTestFunction  f, void  *data)
00108     { _voxelTestFunction = f; _voxelTestFunctionData = data; };
00109     inline void          getVoxelTestFunction(VoxelTestFunction &f, void *&data) const
00110     { f = _voxelTestFunction; data = _voxelTestFunctionData; };
00112     
00115 
00116     inline void          setWorldVoxelTestFunction(WorldVoxelTestFunction  f, void  *data)
00117     { _worldVoxelTestFunction = f; _worldVoxelTestFunctionData = data; };
00118     inline void          getWorldVoxelTestFunction(WorldVoxelTestFunction &f, void *&data) const
00119     { f = _worldVoxelTestFunction; data = _worldVoxelTestFunctionData; };
00121     
00126 
00127     inline void          setModifierFunction(ModifierFunction  f, void  *data)
00128     { _modifierFunction = f; _modifierFunctionData = data; };
00129     inline void          getModifierFunction(ModifierFunction &f, void *&data) const
00130     { f = _modifierFunction; data = _modifierFunctionData; };
00131     inline void          enableModifierFunction(bool flag)    { _useModifierFunction = flag; };
00132     inline bool          isModifierFunctionOn() const         { return _useModifierFunction; };
00134     
00136 
00137     inline void          setFillValue(long double val)                    { _fillValue=val;                               }
00138     inline long double   getFillValue() const                             { return _fillValue;                            }
00140     
00142 
00143     inline void          setBGFillValue(long double val)                  { _bgFillValue=val;                             }
00144     inline long double   getBGFillValue() const                           { return _bgFillValue;                          }
00146     
00148 
00149     inline void          enableBGFilling(bool val)                        { _isBGFill=val;                                }
00150     inline bool          isBGFilling() const                              { return _isBGFill;                             }
00152     
00154 
00155     inline const SubImageBox &getVoxBoundingBox () const                    { return _voxSubImgBox;                         }
00156     inline void          setVoxBoundingBox(const SubImageBox &box)          { _voxSubImgBox = box;                          }
00157     inline const SubImageBoxd &getWorldBoundingBox() const                  { return _worldSubImgBox;                       }
00158     inline void          setWorldBoundingBox(const SubImageBoxd &box)       { _worldSubImgBox = box;                        }
00160     
00162 
00163     inline void          setPreTransform(const Matrix4 &pre)                 { _preTrans = pre; _composeMatrices();          }
00164     inline const Matrix4 &  getPretransform() const                          { return _preTrans;                             }
00166     
00168 
00169     inline void          setVoxToWorld(const Matrix4 &v2w)                   { _voxToWorld = v2w; _composeMatrices();        }
00170     inline const Matrix4 &  getVoxToWorld() const                            { return _voxToWorld;                           }
00172     
00174     virtual void         draw(SubImage *sImg) const;
00175     
00177 
00178     virtual char*        getPersistentState() const                       { return 0; };
00179     virtual void         setPersistentState(const char* /*state*/)        {};
00180     virtual void         clearPersistentState(char* /*state*/) const      {};
00182     
00184     virtual RasterFunction* clone() const { return new RasterFunction(*this); };
00185 
00186 protected:
00188     virtual SubImageBox  _transformSubImgBox(const SubImageBoxd &box) const;
00189     
00192     virtual SubImageBox  _getClipBox(const SubImageBox &box) const;
00193     
00196     virtual void         _getTransformBase(const ImageVector &p, Vector3 tBase[4]) const;
00197     
00201     template <typename DATATYPE>
00202         void                 _fillRaster(const SubImageBox &box, TSubImage<DATATYPE> *pSubImg, Vector3 tBase[4]) const
00203     {
00204         // Fill subimage if background filling is enabled.
00205         if (_isBGFill) { pSubImg->fill(static_cast<DATATYPE>(_bgFillValue)); }
00206         
00207         // Cast fill value to right data type to avoid expensive float to long casts on voxel writes.
00208         const DATATYPE fillVal = static_cast<DATATYPE>(_fillValue);
00209         
00210         // Iterate over all voxels of the box to be tested.
00211         ImageVector p=box.v1;
00212         for (p.u=box.v1.u;  p.u<=box.v2.u;  p.u++){
00213             for (p.t=box.v1.t;  p.t<=box.v2.t;  p.t++){
00214                 for (p.c=box.v1.c;  p.c<=box.v2.c;  p.c++){
00215                     // Get origin of plane in world coordinates (origin). Note that c, t and u coordinates remain untransformed.
00216                     Vector6 moveZ(tBase[0],0,0,0);
00217                     
00218                     for (p.z=box.v1.z;  p.z<=box.v2.z;  p.z++){
00219                         // Test all voxel coordinates of the box whether they are within the sphere or not.
00220                         // If yes then set voxel value to the value of fillVal.
00221                         // If not leave other voxels unchanged.
00222                         // Note that we use the method setImageValue which permits accesses of the
00223                         // page in global image coordinates even if only a fraction of the
00224                         // input subimage is currently accessable. Here the important thing is not
00225                         // to access the region outside box.
00226                         switch (_testFuncMode){
00227                             
00228                             //-----------------------------------------------------------------------------------------
00229                             // If a function pointer shall be used for voxel testing
00230                             // and the function pointer is valid then test/modify all voxels in plane.
00231                         case StaticVoxelTest:{
00232                             if (_voxelTestFunction){
00233                                 for (p.y=box.v1.y;  p.y<=box.v2.y;  p.y++){
00234                                     
00235                                     if (_useModifierFunction && _modifierFunction){
00236                                         // Use userdefined functions to modify the image.
00237                                         for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00238                                             if (_voxelTestFunction(p, _voxelTestFunctionData)){
00239                                                 _modifierFunction(pSubImg, p, _modifierFunctionData);
00240                                             }
00241                                         }
00242                                     }
00243                                     else{
00245                                         for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00246                                             if (_voxelTestFunction(p, _voxelTestFunctionData)){
00247                                                 pSubImg->setImageValue(p, fillVal);
00248                                             }
00249                                         }
00250                                     }
00251                                 }
00252                             }
00253                                              }
00254                             break;
00255                             
00256                             //-----------------------------------------------------------------------------------------
00257                         case VirtualVoxelTest:{
00258                             // If the virtual voxel test function shall be used then test/modify all voxels in plane.
00259                             for (p.y=box.v1.y;  p.y<=box.v2.y;  p.y++){
00260                                 
00261                                 if (_useModifierFunction && _modifierFunction){
00262                                     // Use userdefined functions to modify the image.
00263                                     for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00264                                         if (isVoxelInside(p)) _modifierFunction(pSubImg, p, _modifierFunctionData);
00265                                     }
00266                                 }
00267                                 else{
00269                                     for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00270                                         if (isVoxelInside(p)) pSubImg->setImageValue(p, fillVal);
00271                                     }
00272                                 }
00273                             }
00274                                               }
00275                             break;
00276                             
00277                             //-----------------------------------------------------------------------------------------
00278                             // If a function pointer shall be used for voxel testing
00279                             // the the function pointer is valid then test/modify all voxels in plane.
00280                         case StaticWorldVoxelTest:{
00281                             if (_worldVoxelTestFunction){
00282                                 
00283                                 // Set world position of plane start.
00284                                 Vector6 moveY = moveZ;
00285                                 for (p.y=box.v1.y;  p.y<=box.v2.y;  p.y++){
00286                                     
00287                                     // Set coordinate to the start of the row.
00288                                     Vector6 moveX = moveY;
00289                                     
00290                                     // Modify voxels in a row.
00291                                     if (_useModifierFunction && _modifierFunction){
00292                                         // Use userdefined functions to modify the image.
00293                                         for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00294                                             if (_worldVoxelTestFunction(moveX, _worldVoxelTestFunctionData)){
00295                                                 _modifierFunction(pSubImg, p, _modifierFunctionData);
00296                                             }
00297                                             // Go to next voxel in row world space.
00298                                             moveX += tBase[1];
00299                                         } // for (p.x...)
00300                                     }
00301                                     else{
00303                                         for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00304                                             if (_worldVoxelTestFunction(moveX, _worldVoxelTestFunctionData)){
00305                                                 pSubImg->setImageValue(p, fillVal);
00306                                             }
00307                                             // Go to next voxel in row world space.
00308                                             moveX += tBase[1];
00309                                         } // for (p.x...)
00310                                     }
00311                                     
00312                                     // Move row start coordinate to next row in world space.
00313                                     moveY += tBase[2];
00314                                 } // for (p.y...)
00315                             }
00316                                                   }
00317                             break;
00318                             
00319                             //-----------------------------------------------------------------------------------------
00320                         case VirtualWorldVoxelTest:{
00321                             // Transform origin and voxels in x and y direction to have movement vectors.
00322                             // Move world position of plane start of voxel to be testetd
00323                             Vector6 moveY = moveZ;
00324                             for (p.y=box.v1.y;  p.y<=box.v2.y;  p.y++){
00325                                 
00326                                 // Set world position of plane start.
00327                                 Vector6 moveX = moveY;
00328                                 
00329                                 // Modify voxels in a row.
00330                                 if (_useModifierFunction && _modifierFunction){
00331                                     // Use userdefined functions to modify the image.
00332                                     for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00333                                         if (isWorldVoxelInside(moveX)){
00334                                             _modifierFunction(pSubImg, p, _modifierFunctionData);
00335                                         }
00336                                         // Go to next voxel in row in world space.
00337                                         moveX += tBase[1];
00338                                     } // for (p.x...)
00339                                 }
00340                                 else{
00342                                     for (p.x=box.v1.x;  p.x<=box.v2.x;  p.x++){
00343                                         if (isWorldVoxelInside(moveX)){
00344                                             pSubImg->setImageValue(p, fillVal);
00345                                         }
00346                                         // Go to next voxel in row in world space.
00347                                         moveX += tBase[1];
00348                                     } // for (p.x...)
00349                                 }
00350                                 // Move row start coordinate to next row in world space.
00351                                 moveY += tBase[2];
00352                             } // for (p.y...)
00353                                                    }
00354                             break;
00355                         default: {
00356                             ML_PRINT_WARNING("void RasterFunction::_fillRaster(const SubImageBox &box, TSubImage<DATATYPE> *pSubImg, Vector3 tBase[4]) const", ML_BAD_PARAMETER, "Not rastering!");
00357                                  }
00358                             return;
00359           }  // switch
00360           
00361           // Move plane origin to the next z coordinate in world coordinates.
00362           moveZ += tBase[3];
00363         }  // for (p.z...
00364       }
00365     }
00366   }
00367 } // void fillRaster(...)
00368 
00369 
00370 private:
00372     void              _init();
00373     
00375     void              _composeMatrices();
00376     
00378     long double       _fillValue;
00379     
00381     long double       _bgFillValue;
00382     
00384     bool              _isBGFill;
00385     
00387     Matrix4           _preTrans;
00388     
00390     Matrix4           _voxToWorld;
00391     
00393     Matrix4           _v2w;
00394     
00396     Matrix4           _w2v;
00397     
00400     SubImageBox       _voxSubImgBox;
00401     
00403     SubImageBoxd      _worldSubImgBox;
00404     
00406     TestFuncMode      _testFuncMode;
00407     
00409 
00410     VoxelTestFunction _voxelTestFunction;
00411     void *            _voxelTestFunctionData;
00413     
00415 
00416     WorldVoxelTestFunction _worldVoxelTestFunction;
00417     void *            _worldVoxelTestFunctionData;
00419     
00421 
00422     bool              _useModifierFunction;
00423     ModifierFunction  _modifierFunction;
00424     void *            _modifierFunctionData;
00426     
00428     ML_CLASS_HEADER(RasterFunction);
00429     
00430 };
00431 
00432 ML_END_NAMESPACE
00433 
00434 #endif // __mlRasterFunction_H