MeVisLab Toolbox Reference
mlRasterFunction.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2007, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #ifndef ML_RASTER_FUNCTION_H
14 #define ML_RASTER_FUNCTION_H
15 
16 
18 
19 // This class handles two types of implicit functions which can be rastered
20 // into a subimage with the methods \c draw().
21 //
22 // The first function type tests a voxel coordinate which shall be drawn or not.
23 // The second function type tests a world coordinate which shall be rastered or not.
24 // These functions can be set alternatively as static static function or can be
25 // implemented as overloaded virtual method.
26 //
27 // For the implicit functions in world coordinates a pretransformation and
28 // a voxel to world matrix can be defined so that transformations to the rastered
29 // objects can be applied simply.
30 // Note that transformations are only applied in 3d.
31 
32 #include <mlModuleIncludes.h>
33 #include "mlBaseInit.h"
34 #include "mlSubImageBoxd.h"
35 
36 ML_START_NAMESPACE
37 
45 };
46 
51 typedef bool (*VoxelTestFunction)(const ImageVector &p, void *userData);
52 
57 typedef bool (*WorldVoxelTestFunction)(const Vector6 &p, void *userData);
58 
63 typedef void (*ModifierFunction)(SubImage *tSubImg, const ImageVector &p, void *userData);
64 
65 
66 //===============================================================================
68 //===============================================================================
70 {
71 public:
73  RasterFunction() : Base() { _init(); }
74 
76  RasterFunction(const RasterFunction &f) : Base() { _init(); *this = f; };
77 
79  ~RasterFunction() override {};
80 
82  virtual const RasterFunction &operator=(const RasterFunction &f);
83 
86  inline void setFunctionMode(TestFuncMode mode) { _testFuncMode = mode; }
87  inline TestFuncMode getFunctionMode() const { return _testFuncMode; }
89 
95  virtual bool isVoxelInside(const ImageVector &) const { return false; }
96 
102  virtual bool isWorldVoxelInside(const Vector6 &) const { return false; }
103 
107  inline void setVoxelTestFunction(VoxelTestFunction f, void *data)
108  { _voxelTestFunction = f; _voxelTestFunctionData = data; };
109  inline void getVoxelTestFunction(VoxelTestFunction &f, void *&data) const
110  { f = _voxelTestFunction; data = _voxelTestFunctionData; };
112 
117  { _worldVoxelTestFunction = f; _worldVoxelTestFunctionData = data; };
118  inline void getWorldVoxelTestFunction(WorldVoxelTestFunction &f, void *&data) const
119  { f = _worldVoxelTestFunction; data = _worldVoxelTestFunctionData; };
121 
127  inline void setModifierFunction(ModifierFunction f, void *data)
128  { _modifierFunction = f; _modifierFunctionData = data; };
129  inline void getModifierFunction(ModifierFunction &f, void *&data) const
130  { f = _modifierFunction; data = _modifierFunctionData; };
131  inline void enableModifierFunction(bool flag) { _useModifierFunction = flag; };
132  inline bool isModifierFunctionOn() const { return _useModifierFunction; };
134 
137  inline void setFillValue(double val) { _fillValue=val; }
138  inline double getFillValue() const { return _fillValue; }
140 
143  inline void setBGFillValue(double val) { _bgFillValue=val; }
144  inline double getBGFillValue() const { return _bgFillValue; }
146 
149  inline void enableBGFilling(bool val) { _isBGFill=val; }
150  inline bool isBGFilling() const { return _isBGFill; }
152 
155  inline const SubImageBox &getVoxBoundingBox () const { return _voxSubImgBox; }
156  inline void setVoxBoundingBox(const SubImageBox &box) { _voxSubImgBox = box; }
157  inline const SubImageBoxd &getWorldBoundingBox() const { return _worldSubImgBox; }
158  inline void setWorldBoundingBox(const SubImageBoxd &box) { _worldSubImgBox = box; }
160 
163  inline void setPreTransform(const Matrix4 &pre) { _preTrans = pre; _composeMatrices(); }
164  inline const Matrix4 & getPretransform() const { return _preTrans; }
166 
169  inline void setVoxToWorld(const Matrix4 &v2w) { _voxToWorld = v2w; _composeMatrices(); }
170  inline const Matrix4 & getVoxToWorld() const { return _voxToWorld; }
172 
174  virtual void draw(SubImage *sImg) const;
175 
178  std::string persistentState() const override { return {}; }
179 
180  void setPersistentState(const std::string& /*state*/) override {}
181 
182 #if ML_DEPRECATED_SINCE(3,5,0)
183  [[nodiscard]][[deprecated]] char* getPersistentState() const override { return nullptr; }
184 
185  [[deprecated]] void setPersistentState(const char* /*state*/) override {}
186 
187  [[deprecated]] void clearPersistentState(char* /*state*/) const override {}
188 #endif
190 
192  virtual RasterFunction* clone() const { return new RasterFunction(*this); }
193 
194 protected:
196  virtual SubImageBox _transformSubImgBox(const SubImageBoxd &box) const;
197 
200  virtual SubImageBox _getClipBox(const SubImageBox &box) const;
201 
204  virtual void _getTransformBase(const ImageVector &p, Vector3 tBase[4]) const;
205 
209  template <typename DATATYPE>
210  void _fillRaster(const SubImageBox &box, TSubImage<DATATYPE> *pSubImg, Vector3 tBase[4]) const
211  {
212  // Fill subimage if background filling is enabled.
213  if (_isBGFill) { pSubImg->fill(ml_cast_from_scalar<DATATYPE>(_bgFillValue)); }
214 
215  // Cast fill value to right data type to avoid expensive float to long casts on voxel writes.
216  const DATATYPE fillVal = ml_cast_from_scalar<DATATYPE>(_fillValue);
217 
218  // Iterate over all voxels of the box to be tested.
219  ImageVector p=box.v1;
220  for (p.u=box.v1.u; p.u<=box.v2.u; p.u++){
221  for (p.t=box.v1.t; p.t<=box.v2.t; p.t++){
222  for (p.c=box.v1.c; p.c<=box.v2.c; p.c++){
223  // Get origin of plane in world coordinates (origin). Note that c, t and u coordinates remain untransformed.
224  Vector6 moveZ(tBase[0],0,0,0);
225 
226  for (p.z=box.v1.z; p.z<=box.v2.z; p.z++){
227  // Test all voxel coordinates of the box whether they are within the sphere or not.
228  // If yes then set voxel value to the value of fillVal.
229  // If not leave other voxels unchanged.
230  // Note that we use the method setImageValue which permits accesses of the
231  // page in global image coordinates even if only a fraction of the
232  // input subimage is currently accessable. Here the important thing is not
233  // to access the region outside box.
234  switch (_testFuncMode){
235 
236  //-----------------------------------------------------------------------------------------
237  // If a function pointer shall be used for voxel testing
238  // and the function pointer is valid then test/modify all voxels in plane.
239  case StaticVoxelTest:{
240  if (_voxelTestFunction){
241  for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
242 
243  if (_useModifierFunction && _modifierFunction){
244  // Use userdefined functions to modify the image.
245  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
246  if (_voxelTestFunction(p, _voxelTestFunctionData)){
247  _modifierFunction(pSubImg, p, _modifierFunctionData);
248  }
249  }
250  }
251  else{
253  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
254  if (_voxelTestFunction(p, _voxelTestFunctionData)){
255  pSubImg->setImageValue(p, fillVal);
256  }
257  }
258  }
259  }
260  }
261  }
262  break;
263 
264  //-----------------------------------------------------------------------------------------
265  case VirtualVoxelTest:{
266  // If the virtual voxel test function shall be used then test/modify all voxels in plane.
267  for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
268 
269  if (_useModifierFunction && _modifierFunction){
270  // Use userdefined functions to modify the image.
271  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
272  if (isVoxelInside(p)) _modifierFunction(pSubImg, p, _modifierFunctionData);
273  }
274  }
275  else{
277  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
278  if (isVoxelInside(p)) pSubImg->setImageValue(p, fillVal);
279  }
280  }
281  }
282  }
283  break;
284 
285  //-----------------------------------------------------------------------------------------
286  // If a function pointer shall be used for voxel testing
287  // the the function pointer is valid then test/modify all voxels in plane.
288  case StaticWorldVoxelTest:{
289  if (_worldVoxelTestFunction){
290 
291  // Set world position of plane start.
292  Vector6 moveY = moveZ;
293  for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
294 
295  // Set coordinate to the start of the row.
296  Vector6 moveX = moveY;
297 
298  // Modify voxels in a row.
299  if (_useModifierFunction && _modifierFunction){
300  // Use userdefined functions to modify the image.
301  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
302  if (_worldVoxelTestFunction(moveX, _worldVoxelTestFunctionData)){
303  _modifierFunction(pSubImg, p, _modifierFunctionData);
304  }
305  // Go to next voxel in row world space.
306  moveX += tBase[1];
307  } // for (p.x...)
308  }
309  else{
311  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
312  if (_worldVoxelTestFunction(moveX, _worldVoxelTestFunctionData)){
313  pSubImg->setImageValue(p, fillVal);
314  }
315  // Go to next voxel in row world space.
316  moveX += tBase[1];
317  } // for (p.x...)
318  }
319 
320  // Move row start coordinate to next row in world space.
321  moveY += tBase[2];
322  } // for (p.y...)
323  }
324  }
325  break;
326 
327  //-----------------------------------------------------------------------------------------
328  case VirtualWorldVoxelTest:{
329  // Transform origin and voxels in x and y direction to have movement vectors.
330  // Move world position of plane start of voxel to be testetd
331  Vector6 moveY = moveZ;
332  for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
333 
334  // Set world position of plane start.
335  Vector6 moveX = moveY;
336 
337  // Modify voxels in a row.
338  if (_useModifierFunction && _modifierFunction){
339  // Use userdefined functions to modify the image.
340  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
341  if (isWorldVoxelInside(moveX)){
342  _modifierFunction(pSubImg, p, _modifierFunctionData);
343  }
344  // Go to next voxel in row in world space.
345  moveX += tBase[1];
346  } // for (p.x...)
347  }
348  else{
350  for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
351  if (isWorldVoxelInside(moveX)){
352  pSubImg->setImageValue(p, fillVal);
353  }
354  // Go to next voxel in row in world space.
355  moveX += tBase[1];
356  } // for (p.x...)
357  }
358  // Move row start coordinate to next row in world space.
359  moveY += tBase[2];
360  } // for (p.y...)
361  }
362  break;
363  default: {
364  ML_PRINT_WARNING("void RasterFunction::_fillRaster(const SubImageBox &box, TSubImage<DATATYPE> *pSubImg, Vector3 tBase[4]) const", ML_BAD_PARAMETER, "Not rastering!");
365  }
366  return;
367  } // switch
368 
369  // Move plane origin to the next z coordinate in world coordinates.
370  moveZ += tBase[3];
371  } // for (p.z...
372  }
373  }
374  }
375 } // void fillRaster(...)
376 
377 
378 private:
380  void _init();
381 
383  void _composeMatrices();
384 
386  double _fillValue;
387 
389  double _bgFillValue;
390 
392  bool _isBGFill;
393 
395  Matrix4 _preTrans;
396 
398  Matrix4 _voxToWorld;
399 
401  Matrix4 _v2w;
402 
404  Matrix4 _w2v;
405 
408  SubImageBox _voxSubImgBox;
409 
411  SubImageBoxd _worldSubImgBox;
412 
414  TestFuncMode _testFuncMode;
415 
418  VoxelTestFunction _voxelTestFunction;
419  void * _voxelTestFunctionData;
421 
424  WorldVoxelTestFunction _worldVoxelTestFunction;
425  void * _worldVoxelTestFunctionData;
427 
430  bool _useModifierFunction;
431  ModifierFunction _modifierFunction;
432  void * _modifierFunctionData;
434 
437 
438 };
439 
440 ML_END_NAMESPACE
441 
442 #endif // __mlRasterFunction_H
Class representing general ML objects that support import/export via strings (setPersistentState() an...
Definition: mlBase.h:62
virtual void setPersistentState(const std::string &state)
Restores the object's internal state from a string that had been previously generated using persisten...
virtual void clearPersistentState(char *) const
Disposes a string previously allocated by getPersistentState().
Definition: mlBase.h:123
virtual char * getPersistentState() const
Returns a C string describing the object's internal state.
Definition: mlBase.h:115
Base object to handle implicit or explicit functions to draw into subimages.
virtual bool isWorldVoxelInside(const Vector6 &) const
The implicit function used to test whether a point p is inside (result == 1), onto (result == 0) or o...
void enableBGFilling(bool val)
void _fillRaster(const SubImageBox &box, TSubImage< DATATYPE > *pSubImg, Vector3 tBase[4]) const
Test all voxels within pSubImg against the selected function if they are inside box.
void setPersistentState(const std::string &) override
Restores the object's internal state from a string that had been previously generated using persisten...
void setWorldBoundingBox(const SubImageBoxd &box)
void getModifierFunction(ModifierFunction &f, void *&data) const
~RasterFunction() override
Destructor.
void setWorldVoxelTestFunction(WorldVoxelTestFunction f, void *data)
void getWorldVoxelTestFunction(WorldVoxelTestFunction &f, void *&data) const
TestFuncMode getFunctionMode() const
void setVoxToWorld(const Matrix4 &v2w)
const Matrix4 & getPretransform() const
std::string persistentState() const override
Returns a string describing the object's internal state.
double getFillValue() const
void getVoxelTestFunction(VoxelTestFunction &f, void *&data) const
const SubImageBox & getVoxBoundingBox() const
Set/Get bounding boxes of objects in implicit functions in voxel or in world coordinates.
RasterFunction(const RasterFunction &f)
Copy constructor.
void setBGFillValue(double val)
virtual void _getTransformBase(const ImageVector &p, Vector3 tBase[4]) const
Get world coordinate of p, and world vectors from p to p+(1,0,0), to p+(0,1,0) and p+(0,...
bool isModifierFunctionOn() const
virtual SubImageBox _transformSubImgBox(const SubImageBoxd &box) const
Transforms a subImgBox from world coordinates to a subImgBox in voxel coordinates.
void setVoxelTestFunction(VoxelTestFunction f, void *data)
virtual SubImageBox _getClipBox(const SubImageBox &box) const
Returns the subImgBox whose voxels are going to be tested.
void setVoxBoundingBox(const SubImageBox &box)
virtual bool isVoxelInside(const ImageVector &) const
The implicit function used to test whether a point p is inside (result == 1), onto (result == 0) or o...
RasterFunction()
Constructor.
bool isBGFilling() const
void setFillValue(double val)
virtual void draw(SubImage *sImg) const
Fill intersecting area of sImg with the currently selected function using the transformation matrices...
void enableModifierFunction(bool flag)
void setPreTransform(const Matrix4 &pre)
virtual const RasterFunction & operator=(const RasterFunction &f)
Copy operator.
void setFunctionMode(TestFuncMode mode)
double getBGFillValue() const
const Matrix4 & getVoxToWorld() const
const SubImageBoxd & getWorldBoundingBox() const
void setModifierFunction(ModifierFunction f, void *data)
virtual RasterFunction * clone() const
Create a clone of the RasterFunction.
SubImageBoxd - SubImageBox with coordinates of float data type.
This class manages/represents a rectangular 6d image region which is organized linearly in memory.
Definition: mlSubImage.h:75
VectorType v1
Corner v1 of the subimage region (included in region).
Definition: mlSubImageBox.h:63
VectorType v2
Corner v2 of the subimage region (also included in region!).
Definition: mlSubImageBox.h:69
This template class manages/represents a rectangular 6d image region in memory which is organized lin...
Definition: mlTSubImage.h:110
void setImageValue(const ImageVector &position, DATATYPE value)
Sets the 6d voxel at the given position to the given value.
Definition: mlTSubImage.h:379
void fill(DATATYPE value)
Sets all voxel values in subimage to value.
Definition: mlTSubImage.h:778
ComponentType c
Color component of the vector.
Definition: mlImageVector.h:65
ComponentType t
Time component of the vector.
Definition: mlImageVector.h:67
ComponentType u
Unit/Modality/User component of the vector.
Definition: mlImageVector.h:69
ComponentType z
Z component of the vector.
Definition: mlImageVector.h:63
ComponentType x
X component of the vector.
Definition: mlImageVector.h:59
ComponentType y
Y component of the vector.
Definition: mlImageVector.h:61
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm;...
Definition: mlTypeDefs.h:925
#define ML_PRINT_WARNING(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_WARNING_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be dumped...
#define MLBASEEXPORT
defined Header file mlBaseInit.h
Definition: mlBaseInit.h:22
#define ML_CLASS_HEADER(className)
Same like ML_CLASS_HEADER_EXPORTED with a non existing export symbol.
void(* ModifierFunction)(SubImage *tSubImg, const ImageVector &p, void *userData)
Function type which modifies a value in a typed subimage given by tSubImg.
bool(* WorldVoxelTestFunction)(const Vector6 &p, void *userData)
Function type used to decide whether a voxel is within an object or not.
bool(* VoxelTestFunction)(const ImageVector &p, void *userData)
Function type used to decide whether a voxel is within an object or not.
TestFuncMode
The modes how the voxel is tested.
@ VirtualWorldVoxelTest
@ StaticWorldVoxelTest
@ StaticVoxelTest
@ VirtualVoxelTest