VTK

From bone.wiki
Revision as of 20:41, 28 January 2010 by Enodwell (talk | contribs)
Jump to navigation Jump to search

Tips

Generic C++ Tips

Please familiarize yourself with C++ Development. Tips there apply to VTK classes too, which are after all C++ classes.

Minimize includes in headers

The general rule of header files in VTK is that you include only the header file of the superclass. For everything else, you merely forward declare it in the header. See C++ Development#Minimize includes in headers for more info on forward declarations.

This is a good rule to follow where possible in C++ anyways, but in VTK it is particularly important, because many kinds of objects (e.g. STL - Standard Template objects) will cause Python Wrapping of the class to fail if used in the header file.

Use vtkSmartPointers

VTK requires you to create instances of VTK objects only with the class's static New method, like this:

vtkImageData* image = vtkImageData::New();

The reason for this is that VTK uses reference counting internally, and will automatically delete objects that are no longer used. This is very convenient, because you can create an object somewhere, and link it into one or more pipeline, and not have worry about exactly when to delete it. It has however the disadvantage that when objects are created this way, they will not be automatically destroyed when they go out of scope. This is it should be - we only want them destroyed when their reference count goes to zero. However, you must remember to manually call Delete when the object goes out of scope, like this:

image->Delete();

This may not actually delete the object, it merely decrements the reference counter. It's easy to forget this (or to overlook paths that can take you out of scope - for instance if an exception is thrown.) If you forget, this becomes a memory leak. The best solution to this is to use a vtkSmartPointer, like this:

vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();

This is the only line of code you have to change compared to the abover example - otherwise you can use the variable image exactly as before. Only now, as soon as image goes out of scope, the destructor of the SmartPointer will be called, and it will automatically call the Delete method of image.

NOTE: You don't always need a SmartPointer. If you are getting the pointer to an existing object for some temporary calculation, a bare pointer is adequate.

TIP: You can use regular expressions to search and replace for all creations of VTK objects.

The regular expression search string is:

(vtk\w+) *\* *(\w+) *= *\1::New

And the replace string is:

vtkSmartPointer<$1> $2 = vtkSmartPointer<$1>::New

So for example with sed with would be:

sed -i 's/(vtk\w+) *\* *(\w+) *= *\1::New/vtkSmartPointer<$1> $2 = vtkSmartPointer<$1>::New/' yourfile.cxx

although I actually use TextMate for this.

Note that you amy still have to go through and replace and now-unnecessary delete commands.

Use Doxygen style comments

to write

Avoid printf and similar functions

printf and similar functions (sprintf and scanf and so on) should be avoided. The reason is that the POSIX-style formatting needs to match the length of variables, and this generally cannot be predicted, particularly for software that is to be compiled on many different systems.

For example, this always works

long int n;
printf ("The number is %ld", n);

But this is problematic

vtkIdType n;
printf ("The number is %ld", n);

because even if vtkIdType is the same as a long int on one particular system, it may not be on another. (Note: This will often work anyways on little-endian systems, although it will generate compiler warnings. However there are cases where it will cause a genuine bug. Besides, having 100's of compiler warnings will obscure genuinely important warnings.)

On the other hand, the standard C++ stream formatting modifiers, although overloaded to correctly match the variable type, tend to be overly verbose to conveniently use.

I recommend therefore using boost::format. boost::format has already been adopted in the next official C++ standard. Here is an example using boost::format:

using boost::format;
 
float x = 3.1415926535;
std::cout << format("%.3f\n") % x;