On way to simplify the creation of an image is with image iterators, such as vtkImagePointIterator. This iterator will iterate over each pixel/voxel and give you the (x,y,z) coords that you can use to evaluate your function.
I haven’t seen a good example (mea culpa, since I wrote the iterator class), but the usage is roughly as follows:
#include <vtkImageData.h>
#include <vtkImagePointIterator.h>
// set image properties for an image with a domain of
// [ -10.0, +10.0] in x, y and z
double spacing[3] = { 0.1, 0.1, 0.1 };
int size[3] = { 201, 201, 201 };
double origin[3] = { -10.0, -10.0, -10.0 };
// create an image and allocate the pixel data
auto imageData = vtkSmartPointer<vtkImageData>::New();
imageData->SetDimensions(size);
imageData->SetSpacing(spacing);
imageData->SetOrigin(origin);
// replace '1' with '2' if you want to create a complex image
imageData->AllocateScalars(VTK_FLOAT, 1);
// get the scalars from the image (they're allocated but not initialized).
vtkFloatArray *scalars = vtkFloatArray::SafeDownCast(imageData->GetPointData()->GetScalars());
// alternatively, use vtkDataArray to avoid the cast
//vtkDataArray *scalars = imageData->GetPointData()->GetScalars();
vtkImagePointIterator iter(imageData);
while (!iter.IsAtEnd())
{
double point[3];
iter.GetPosition(point);
// as an example, use this simple function
double value = point[0]*point[0] + point[1]*point[1] + point[2]*point[2];
// insert the value into the image
scalars->SetValue(iter.GetId(), value);
iter.Next();
}
// as an optional setp, vtkImageShiftScale can be used with an
// appropriate shift and scale to convert the image from float to
// unsigned short for rendering
Edit: Regarding the crash that you saw, it was probably due to the fact the vtkImageData requires a contiguous array, but your code allocated non-contiguous segments. A vtkImageData would need a single array of length size[0]*size[1]*size[2].