Search code examples
c++eigeneigen3

Assigning elements to Eigen::Vector2d within std vector throws error


I went through few StackOverflow posts but didn't find such error. I am trying to write a simple class which does a few operations on Eigen vectors and matrices. I created a class called MyClass and it has a method by the name MyMethod. It's code is as follows

void MyClass::MyMethod(Eigen::Vector4f X, 
                       std::vector<Eigen::Vector2i> &pixelIndices,
                       std::vector<Eigen::Vector4f> vertices)
{
   // Do some preprocessing

   //Deleacring the std vector
   std::vector<Eigen::Vector2i> currTriangle(3);
   currTriangle[0] = Eigen::Vector2i(0); //Error occurs here

   // Do some more processing
}

Upon executing method from a main function error occurs at the said statement. The error output is given below.

$: ./test1 
test1: /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:285: void Eigen::PlainObjectBase<Derived>::resize(Eigen::Index) [with Derived = Eigen::Matrix<int, 2, 1>; Eigen::Index = long int]: Assertion `((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0' failed.
Aborted (core dumped)

I know that using STL containers with Eigen is problematic, but as mentioned in the documentation the problems seems to be only with fixed size vectorizable Eigen types (that is they should be of 16 byte size), but Vector2i is not such a Eigen type. The assert statement is called in resize() method of PlainObjectBase, which is also weird because I haven't used it anywhere in the code.

Has anyone else faced this error? Any help will be really appreciated.

Update: The error seems to be not because I used std::vector. I made this small changes to the code.

  void MyClass::MyMethod(Eigen::Vector4f X, 
                         std::vector<Eigen::Vector2i> &pixelIndices,
                         std::vector<Eigen::Vector4f> vertices)
{
   // Do some preprocessing

   Eigen::Vector2i temp(0); //Same Error occures here also
   //Deleacring the std vector
   std::vector<Eigen::Vector2i> currTriangle(3);
   currTriangle[0] = Eigen::Vector2i(0);

   // Do some more processing
}

So it seems like the error occurs when initializing the Vector2i.


Solution

  • As @MarcGlisse pointed out, Vector2i(0) tells to construct a Vector2i with 0 elements, which will fail at runtime. The reason why fixed sized matrices/vectors constructed with a single scalar interpret this as size rather than value is to allow generic functions, where it is not clear whether the size dynamic or fixed:

    template<int SizeAtCompileTime>
    void foo(){
        Eigen::Matrix<int, SizeAtCompileTime, 1> v(actualSize);
        // ...
    }
    

    There are two border-cases: Passing two integers to a vector with two elements or passing one integer to a vector with one element, will cause the vector to be initialized with that value(s) if the scalar type of the vector can implicitly constructed from the passed integer type -- otherwise, it will be interpreted as size.

    To solve your original problem, there are several alternatives:

    Eigen::Vector2i temp1(Eigen::Vector2i::Zero());
    Eigen::Vector2i temp2(0,0);
    
    // initialize all elements with a Zero vector:
    std::vector<Eigen::Vector2i> currTriangle(3, Eigen::Vector2i::Zero());
    
    currTriangle[0].setZero(); // set 0th element to Zero vector
    currTriangle[0].setConstant(0); // equivalent to setZero, but works for arbitrary constants
    currTriangle[0].array() = 0; // .array() lets you do element-wise operations