My solution is based on @Peter-ReinstateMonica suggestion: create a wrapper class where both objects vtkFloatArray
and Eigen::MatrixXf
would reside and that would make possibe to control the lifetime of both these objects.
Let's call wrapper class vtkEigenFloatArray
and let it be inherited from vtkFloatArray
. As our wrapper class implicitely inherits vtkObject
we should follow vtk's inheritance structure to make it usable within vtk (for example vtkNew<vtkEigenFloatArray>
) while keeping pimp idiom (that is why you can see many vtk methods and macros within created class, this is done by analogy with vtkFloatArray
source code).
We add Eigen::MatrixXf* eigArr
member variable to our vtkEigenFloatArray
class.
We also add the method Eigen::MatrixXf* GetEigenArray()
that returns Eigen::MatrixXf* eigArr
pointer and setter void SetEigenArray(Eigen::MatrixXf* arr)
to make available to use the inner Eigen::MatrixXf
object from ouside created class.
It worth to note that vtkEigenFloatArray
and its protected Eigen::MatrixXf* eigArr
object share the same buffer. It is set every time one calls void UpdateEigenBuffer()
function. Moreover everytime when one resizes Eigen::MatrixXf* eigArr
from outside the created class the function void UpdateEigenBuffer()
must be called to update size of vtkFloatArray
-inherited class.
Also user must never externally delete Eigen::MatrixXf* eigArr
as it is deleted in vtkEigenFloatArray
's destructor.
The drawback of proposed solution:
When the main vtkEigenFloatArray
object is deleted the pointer Eigen::MatrixXf* eigArr
will not be equal to nullptr
. Thus you cannot check whether Eigen::MatrixXf* eigArr
is alive or not while you don't have holder vtkEigenFloatArray
object.
#include <vtkNew.h>
#include <vtkFloatArray.h>
#include <Eigen/Dense>
#include <iostream>
class vtkEigenFloatArray : public vtkFloatArray
{
public:
static vtkEigenFloatArray* New();
vtkTypeMacro(vtkEigenFloatArray, vtkFloatArray);
void PrintSelf(ostream& os, vtkIndent indent) override
{
this->RealSuperclass::PrintSelf(os, indent);
}
// This macro expands to the set of method declarations that
// make up the interface of vtkAOSDataArrayTemplate, which is ignored
// by the wrappers.
#if defined(__VTK_WRAP__) || defined(__WRAP_GCCXML__)
vtkCreateWrappedArrayInterface(float);
#endif
/**
* A faster alternative to SafeDownCast for downcasting vtkAbstractArrays.
*/
static vtkEigenFloatArray* FastDownCast(vtkAbstractArray* source)
{
return static_cast<vtkEigenFloatArray*>(Superclass::FastDownCast(source));
}
/**
* Get the minimum data value in its native type.
*/
static float GetDataTypeValueMin() { return VTK_FLOAT_MIN; }
/**
* Get the maximum data value in its native type.
*/
static float GetDataTypeValueMax() { return VTK_FLOAT_MAX; }
/**
* Deletes previous pointer and sets new
*/
void SetEigenArray(Eigen::MatrixXf* arr)
{
delete eigArr;
eigArr = arr;
UpdateEigenBuffer();
}
/**
* Don't delete this pointer!
*/
Eigen::MatrixXf* GetEigenArray()
{
return eigArr;
}
/**
* Must be manually called every time Eigen::MatrixXf resized
*/
void UpdateEigenBuffer()
{
this->SetArray(eigArr->data(), eigArr->size(), 1); // must be set to 1 or in destructor runtime error
}
protected:
vtkEigenFloatArray()
{
eigArr = new Eigen::MatrixXf();
}
~vtkEigenFloatArray() override
{
delete eigArr;
eigArr = nullptr;
}
Eigen::MatrixXf* eigArr;
private:
typedef vtkAOSDataArrayTemplate<float> RealSuperclass;
vtkEigenFloatArray(const vtkEigenFloatArray&) = delete;
void operator=(const vtkEigenFloatArray&) = delete;
friend class vtkNew<vtkEigenFloatArray>;
};
vtkStandardNewMacro(vtkEigenFloatArray);
int main(int argc, char *argv[]) {
/* General usage */
vtkNew<vtkEigenFloatArray> arr;
Eigen::MatrixXf* M = arr->GetEigenArray();
M->resize(2, 2);
*M << 1, 2, 3, 4;
arr->UpdateEigenBuffer();
std::cout << "Eigen M:" << std::endl;
std::cout << *M << std::endl;
std::cout << "VTK array:" << std::endl;
for(int i = 0; i < arr->GetSize(); i++)
std::cout << arr->GetValue(i) << std::endl;
arr->Allocate(5);
std::cout << "Eigen M:" << std::endl;
std::cout << *M << std::endl;
std::cout << "VTK array:" << std::endl;
for(int i = 0; i < arr->GetSize(); i++)
std::cout << arr->GetValue(i) << std::endl;
/* Test `SetEigenArray` */
Eigen::MatrixXf* MM = new Eigen::MatrixXf();
MM->resize(2,2);
*MM << 11, 22, 33, 44;
arr->SetEigenArray(MM);
std::cout << "Eigen MM:" << std::endl;
std::cout << *MM << std::endl;
std::cout << "VTK array:" << std::endl;
for(int i = 0; i < arr->GetSize(); i++)
std::cout << arr->GetValue(i) << std::endl;
return 0;
}