VTK
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 from the standard C library (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;