MeVisLabToolboxReference
|
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