Initialization of NCollection_Array2 in a class

Hi all

I am writing a program that creates geometric models, with each geometric element is defined in a class which holds the parameters and also the calling functions. Therefore there are 1D and 2D arrays to be initialised every time a class instance is created. So far I managed to create NCollection_Array1 objects without special initialisation, however with NCollection_Array2 objects I am unable to assign values to them (rather unsurprising given the "should be used with caution" warning in the documentation). However, I also failed to create a proper constructor to the arrays, I'm sure I'm missing something here. Below is an example with default constructor to illustrate:

class surface
{
   public:
      //example internal variables
      Standard_Integer udegree;
      Standard_Integer vdegree;
      TColgp_Array2OfPnt Poles;
      TColgp_Array1OfReal Uknots;
      TColgp_Array1OfReal Vknots;
   protected:
      //example surface
      Handle(Geom_BSplineSurface) Surface;

   public:
      //parameters are initialized here
      void parameters_init();
      //surface created here
      void surface_init();
};

surface::parameters_init()
{
   //assume udegree, vdegree initialized and poles and knots values given

   //Uknots, Vknots and Poles are resized correctly
   Uknots.Resize(umin, umax, vmin, vmax);
   Vknots.Resize(umin, umax, vmin, vmax);
   Poles.Resize(umin, umax, vmin, vmax);

   //Uknots and Vknots are assigned correctly, trying to assign Poles with gp_Pnt incurs in segmentation fault
   //Similar for other types of 2D arrays such as TColStd_Array2OfReal 
   Uknots.SetValue(umin, Uknot_value); 
   Vknots.SetValue(vmin, Vknot_value);
   Poles.SetValue(umin, vmin, gp_Pnt(xmin, ymin, zmin);
}

I tried to create a default constructor for the class such as the one below so that the arrays are properly initialised, however I could not find an initalisation that works, and the compiler errors don't make sense to me. 

class surface
{
   surface();
   //(...)
}

surface::surface()
{
   Points(1,1,1,1);
}

I guess I could store the data using shared_ptr but I was looking for a more elegant solution. I am using C++17 with GCC 12.1 and OCC 7.6.2 from the Msys2 package. 

Thanks!

Kirill Gavrilov's picture
surface::surface()
{
   Points(1,1,1,1);
}

This code sample makes no sense to me - C++ initialization list should look like "surface::surface() : Points (1, 1, 1, 1) {}".

   Uknots.Resize(umin, umax, vmin, vmax);

NCollection_Array2 has no ::Resize() method that takes 4 arguments, so the code should not compile. Method description takes 5 mandatory arguments - the latter indicating if old values in array should be copied or discarded:

  //! Resizes the array to specified bounds.
  //! No re-allocation will be done if length of array does not change,
  //! but existing values will not be discarded if theToCopyData set to FALSE.
  //! @param theRowLower new lower Row of array
  //! @param theRowUpper new upper Row of array
  //! @param theColLower new lower Column of array
  //! @param theColUpper new upper Column of array
  //! @param theToCopyData flag to copy existing data into new array
  void Resize (Standard_Integer theRowLower,
               Standard_Integer theRowUpper,
               Standard_Integer theColLower,
               Standard_Integer theColUpper,
               Standard_Boolean theToCopyData)
L C's picture

Hi Kirill! Thanks very much for your reply. I apologise for the spelling errors, I tried to simplify the code into something understandable and ended up making some mistakes that I didn't catch. 

Just wanted to follow up that the issue was a tad bit more complicated. The OCC version that I was using for compilation was in reality 7.5.3.1 and not 7.6.2. For some reason either in 7.5.3.1 (or GCC versions before 12.2?) it is not possible to create an unitialised NCollection_Array2 (although I've only tested with reals and gp_Pnt). The fact that the compiler will throw strange errors like complaining that 1 is not a Standard_Integer and also the NCollection_Array2 documentation ("use with caution") made it quite hard to find the issue. I'd be curious if someone else would be able to see the same issue since the definition of NCollection_Array2 did not change between the OCC versions, but at least it is solved for now. 

The issue can be isolated using the example code below, if the error is present the code should fail after printing Array1:

#include <iostream>

#include <string>

// #include <NCollection_Array1.hxx>

// #include <NCollection_Array2.hxx>

#include <TColgp_Array1OfPnt.hxx>

#include <TColgp_Array2OfPnt.hxx>



class Theclass

{

    private:

        TColgp_Array1OfPnt theArray1;

        TColgp_Array2OfPnt theArray2;



    public:

        void init1();

        void get1();

        void init2();

        void get2();

};



void Theclass::init1()

{

    theArray1.Resize(1,1,Standard_False);

    theArray1.SetValue(1,gp_Pnt(1,2,3));

}

void Theclass::get1()

{

    gp_Pnt pnt = theArray1.Value(1);

    std::cout << "Array1: " << pnt.X() << "," << pnt.Y() << "," << pnt.Z() << std::endl;

}



void Theclass::init2()

{

    theArray2.Resize(1,2,1,2,Standard_False);

    theArray2.SetValue(1,1,gp_Pnt(4.1,5.1,6.1));

    theArray2.SetValue(1,2,gp_Pnt(4.2,5.2,6.2));

    theArray2.SetValue(2,1,gp_Pnt(4.3,5.3,6.3));

    theArray2.SetValue(2,2,gp_Pnt(4.4,5.4,6.4));

}

void Theclass::get2()

{

    gp_Pnt pnt = theArray2.Value(2,2);

    std::cout << "Array2: " << pnt.X() << "," << pnt.Y() << "," << pnt.Z() << std::endl;

}



int main()

{

    Theclass foobar1;

    foobar1.init1();

    foobar1.get1();

    Theclass foobar2;

    foobar2.init2();

    foobar2.get2();

    std::cout << "great success!" << std::endl;

    return 0;

}

Expected result:

Array1: 1,2,3
Array2: 4.4,5.4,6.4
great success!
Kirill Gavrilov's picture

OCCT 7.5 has a bug in NCollection_Array2::Resize() method fixed in OCCT 7.6, if that would make any help to your findings.

L C's picture

That's the one with 99% certainty. Thank you very much for the information, much appreciated!