I’m using vtkIdTypeArray
to implement a half-edge data structure for 2D meshes. Once the faces are prepared, the connectivity and offsets array will be sent to vtkCellArray
with (vtkCellArray::SetData(vtkIdTypeArray*, vtkIdTypeArray*)
).
I’m stuck b/w certain syntactic/API choices. It would help to get an expert opinion before I choose one over the other.
Internally, the struct
uses API of said data arrays. But, I want to access member data-arrays through traditional operator[]
. Now, I have two options: 1. Ranges
, 2. GetPointer()
.
Also right after any Resize
/InsertTypedComponent
these proxy-like accessors are invalid, so I’ve to revalidate them.
Ex: Build 2-D meshes with half-edge data-structure and fill a vtkCellArray
struct HalfEdgeMesh
{
HalfEdgeMesh()
: m_Conn(vtkIdTypeArray::New())
, m_Offsts(vtkIdTypeArray::New())
, m_HalfEdges(vtkIdTypeArray::New())
{}
// vtkCellArray will assume ownership, so no need to invoke GC rn.
~HalfEdgeMesh() {m_Conn->FastDelete(); m_Offsts->FastDelete(); ...}
// to simplify access, provide public pointers.
vtkIdType* polys
vtkIdType* offsets
vtkIdType* halfEdges
void Allocate(vtkIdType maxPolys) {...}
void Insert(vtkIdType* verts, vtkIdType* hedges) {...}
void FillUp(vtkCellArray* polys) { polys->SetData(m_Conn, m_Offsts); }
void Link(vtkIdType hedge1, vtkIdType hedge2){...}
void Size() {...}
private:
vtkIdTypeArray* m_Conn;
vtkIdTypeArray* m_Offsts;
vtkIdTypeArray* m_HalfEdges;
protected:
// must call this post-allocation or post-resize
// in methods `Allocate`, `Insert` and `Link`
void __revalidate_mem_accessors() {...}
};
Possible implementations of __revalidate_mem_accessors
:
- This looks weird. Each line makes 4 assertions and is the one suggested by docs.
{
polys = vtk::DataArrayValueRange<1>(m_Conn).begin();
offsets = vtk::DataArrayValueRange<1>(m_Offsts).begin();
halfEdges= vtk::DataArrayValueRange<1>(m_HalfEdges).begin();
}
- This is simple and readable. It has minimal overhead; zero assertions, zero range checks.
{
polys = m_Conn->GetPointer(0);
offsets = m_Offsts->GetPointer(0);
halfEdges= m_HalfEdges->GetPointer(0);
}
Also, the functions Insert
and Link
are called in very tight loops that need to be performant. Which would be better? Is this a bad design?
I’m aware that exposing non-const public pointers is scary but I use this in a translation unit where I am the sole user of this struct
.
Posting after a mini panic-attack when I found this in the documentation for GetPointer
.
Get the address of a particular data index.
Performs no checks to verify that the memory has been allocated etc. Use of this method is
discouraged, as newer arrays require a deep-copy of the array data in order to return a suitable
pointer. See vtkArrayDispatch for a safer
alternative for fast data access.
Will that mean GetPointer
will soon be deprecated
in coming releases?
It would be great for typed data-arrays to retain this method.
Edit: code typos