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
37
46
51typedef bool (*VoxelTestFunction)(const ImageVector &p, void *userData);
52
57typedef bool (*WorldVoxelTestFunction)(const Vector6 &p, void *userData);
58
63typedef void (*ModifierFunction)(SubImage *tSubImg, const ImageVector &p, void *userData);
64
65
66//===============================================================================
68//===============================================================================
70{
71public:
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
116 inline void setWorldVoxelTestFunction(WorldVoxelTestFunction f, void *data)
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
183
185 virtual RasterFunction* clone() const { return new RasterFunction(*this); }
186
187protected:
190
193 virtual SubImageBox _getClipBox(const SubImageBox &box) const;
194
197 virtual void _getTransformBase(const ImageVector &p, Vector3 tBase[4]) const;
198
202 template <typename DATATYPE>
204 {
205 // Fill subimage if background filling is enabled.
206 if (_isBGFill) { pSubImg->fill(ml_cast_from_scalar<DATATYPE>(_bgFillValue)); }
207
208 // Cast fill value to right data type to avoid expensive float to long casts on voxel writes.
210
211 // Iterate over all voxels of the box to be tested.
212 ImageVector p=box.v1;
213 for (p.u=box.v1.u; p.u<=box.v2.u; p.u++){
214 for (p.t=box.v1.t; p.t<=box.v2.t; p.t++){
215 for (p.c=box.v1.c; p.c<=box.v2.c; p.c++){
216 // Get origin of plane in world coordinates (origin). Note that c, t and u coordinates remain untransformed.
217 Vector6 moveZ(tBase[0],0,0,0);
218
219 for (p.z=box.v1.z; p.z<=box.v2.z; p.z++){
220 // Test all voxel coordinates of the box whether they are within the sphere or not.
221 // If yes then set voxel value to the value of fillVal.
222 // If not leave other voxels unchanged.
223 // Note that we use the method setImageValue which permits accesses of the
224 // page in global image coordinates even if only a fraction of the
225 // input subimage is currently accessable. Here the important thing is not
226 // to access the region outside box.
227 switch (_testFuncMode){
228
229 //-----------------------------------------------------------------------------------------
230 // If a function pointer shall be used for voxel testing
231 // and the function pointer is valid then test/modify all voxels in plane.
232 case StaticVoxelTest:{
233 if (_voxelTestFunction){
234 for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
235
236 if (_useModifierFunction && _modifierFunction){
237 // Use userdefined functions to modify the image.
238 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
239 if (_voxelTestFunction(p, _voxelTestFunctionData)){
240 _modifierFunction(pSubImg, p, _modifierFunctionData);
241 }
242 }
243 }
244 else{
246 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
247 if (_voxelTestFunction(p, _voxelTestFunctionData)){
248 pSubImg->setImageValue(p, fillVal);
249 }
250 }
251 }
252 }
253 }
254 }
255 break;
256
257 //-----------------------------------------------------------------------------------------
258 case VirtualVoxelTest:{
259 // If the virtual voxel test function shall be used then test/modify all voxels in plane.
260 for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
261
262 if (_useModifierFunction && _modifierFunction){
263 // Use userdefined functions to modify the image.
264 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
265 if (isVoxelInside(p)) _modifierFunction(pSubImg, p, _modifierFunctionData);
266 }
267 }
268 else{
270 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
271 if (isVoxelInside(p)) pSubImg->setImageValue(p, fillVal);
272 }
273 }
274 }
275 }
276 break;
277
278 //-----------------------------------------------------------------------------------------
279 // If a function pointer shall be used for voxel testing
280 // the the function pointer is valid then test/modify all voxels in plane.
282 if (_worldVoxelTestFunction){
283
284 // Set world position of plane start.
285 Vector6 moveY = moveZ;
286 for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
287
288 // Set coordinate to the start of the row.
289 Vector6 moveX = moveY;
290
291 // Modify voxels in a row.
292 if (_useModifierFunction && _modifierFunction){
293 // Use userdefined functions to modify the image.
294 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
295 if (_worldVoxelTestFunction(moveX, _worldVoxelTestFunctionData)){
296 _modifierFunction(pSubImg, p, _modifierFunctionData);
297 }
298 // Go to next voxel in row world space.
299 moveX += tBase[1];
300 } // for (p.x...)
301 }
302 else{
304 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
305 if (_worldVoxelTestFunction(moveX, _worldVoxelTestFunctionData)){
306 pSubImg->setImageValue(p, fillVal);
307 }
308 // Go to next voxel in row world space.
309 moveX += tBase[1];
310 } // for (p.x...)
311 }
312
313 // Move row start coordinate to next row in world space.
314 moveY += tBase[2];
315 } // for (p.y...)
316 }
317 }
318 break;
319
320 //-----------------------------------------------------------------------------------------
322 // Transform origin and voxels in x and y direction to have movement vectors.
323 // Move world position of plane start of voxel to be testetd
324 Vector6 moveY = moveZ;
325 for (p.y=box.v1.y; p.y<=box.v2.y; p.y++){
326
327 // Set world position of plane start.
328 Vector6 moveX = moveY;
329
330 // Modify voxels in a row.
331 if (_useModifierFunction && _modifierFunction){
332 // Use userdefined functions to modify the image.
333 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
334 if (isWorldVoxelInside(moveX)){
335 _modifierFunction(pSubImg, p, _modifierFunctionData);
336 }
337 // Go to next voxel in row in world space.
338 moveX += tBase[1];
339 } // for (p.x...)
340 }
341 else{
343 for (p.x=box.v1.x; p.x<=box.v2.x; p.x++){
344 if (isWorldVoxelInside(moveX)){
345 pSubImg->setImageValue(p, fillVal);
346 }
347 // Go to next voxel in row in world space.
348 moveX += tBase[1];
349 } // for (p.x...)
350 }
351 // Move row start coordinate to next row in world space.
352 moveY += tBase[2];
353 } // for (p.y...)
354 }
355 break;
356 default: {
357 ML_PRINT_WARNING("void RasterFunction::_fillRaster(const SubImageBox &box, TSubImage<DATATYPE> *pSubImg, Vector3 tBase[4]) const", ML_BAD_PARAMETER, "Not rastering!");
358 }
359 return;
360 } // switch
361
362 // Move plane origin to the next z coordinate in world coordinates.
363 moveZ += tBase[3];
364 } // for (p.z...
365 }
366 }
367 }
368} // void fillRaster(...)
369
370
371private:
373 void _init();
374
376 void _composeMatrices();
377
379 double _fillValue;
380
382 double _bgFillValue;
383
385 bool _isBGFill;
386
388 Matrix4 _preTrans;
389
391 Matrix4 _voxToWorld;
392
394 Matrix4 _v2w;
395
397 Matrix4 _w2v;
398
401 SubImageBox _voxSubImgBox;
402
404 SubImageBoxd _worldSubImgBox;
405
407 TestFuncMode _testFuncMode;
408
411 VoxelTestFunction _voxelTestFunction;
412 void * _voxelTestFunctionData;
414
417 WorldVoxelTestFunction _worldVoxelTestFunction;
418 void * _worldVoxelTestFunctionData;
420
423 bool _useModifierFunction;
424 ModifierFunction _modifierFunction;
425 void * _modifierFunctionData;
427
430
431};
432
434
435#endif // __mlRasterFunction_H
Class representing general ML objects that support import/export via strings (setPersistentState() an...
Definition mlBase.h:59
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...
const SubImageBox & getVoxBoundingBox() const
Set/Get bounding boxes of objects in implicit functions in voxel or in world coordinates.
const Matrix4 & getVoxToWorld() const
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
const Matrix4 & getPretransform() 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)
std::string persistentState() const override
Returns a string describing the object's internal state.
double getFillValue() const
void getVoxelTestFunction(VoxelTestFunction &f, void *&data) const
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.
virtual RasterFunction * clone() const
Create a clone of the RasterFunction.
void setFillValue(double val)
virtual void draw(SubImage *sImg) const
Fill intersecting area of sImg with the currently selected function using the transformation matrices...
const SubImageBoxd & getWorldBoundingBox() const
void enableModifierFunction(bool flag)
void setPreTransform(const Matrix4 &pre)
void setFunctionMode(TestFuncMode mode)
double getBGFillValue() const
virtual const RasterFunction & operator=(const RasterFunction &f)
Copy operator.
void setModifierFunction(ModifierFunction f, void *data)
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).
VectorType v2
Corner v2 of the subimage region (also included in region!).
This template class manages/represents a rectangular 6d image region in memory which is organized lin...
#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:823
#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
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
#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