review(CompositeArr): improve doc + refactor + improve testing

- tone down changelog + add more details
- add default keyword for `vtkCompositeImplicitBackend` destructor
- add `const` in places where is useful
- change warning of nullptr into error
- improve documentation for both backend and array
- refactor `vtkCompositeArrayUtilities` namespace in `vtk` namespace
- improve multi component testing
This commit is contained in:
Julien Fausty 2022-11-22 11:40:06 +01:00
parent e7a38ffa71
commit 86a5ba59e2
7 changed files with 66 additions and 17 deletions

View File

@ -85,7 +85,7 @@ vtkSmartPointer<vtkCompositeArray<int>> SetupCompositeArray(int length)
interleaf.emplace_back(intArrays[i]);
}
return vtkCompositeArrayUtilities::Concatenate<int>(interleaf);
return vtk::ConcatenateDataArrays<int>(interleaf);
}
}

View File

@ -50,5 +50,29 @@ int TestCompositeImplicitBackend(int, char*[])
}
}
vtkNew<vtkIntArray> leftMulti;
leftMulti->SetNumberOfComponents(3);
leftMulti->SetNumberOfTuples(10);
auto leftMultiRange = vtk::DataArrayValueRange<3>(leftMulti);
std::iota(leftMultiRange.begin(), leftMultiRange.end(), 0);
vtkNew<vtkIntArray> rightMulti;
rightMulti->SetNumberOfComponents(3);
rightMulti->SetNumberOfTuples(10);
auto rightMultiRange = vtk::DataArrayValueRange<3>(rightMulti);
std::iota(rightMultiRange.begin(), rightMultiRange.end(), 30);
vtkCompositeImplicitBackend<int> compositeMulti(leftMulti, rightMulti);
for (int i = 0; i < 60; ++i)
{
if (i != compositeMulti(i))
{
std::cout << "Composite backend operator not functioning: " << i
<< " != " << compositeMulti(i) << std::endl;
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}

View File

@ -38,6 +38,20 @@
* In order to be usefully included in the dispatchers, these arrays need to be instantiated at the
* vtk library compile time.
*
* An example of potential usage
* ```
* vtkNew<vtkIntArray> leftArr;
* leftArr->SetNumberOfComponents(1);
* leftArr->SetNumberOfTuples(1);
* leftArr->SetValue(0, 0);
* vtkNew<vtkIntArray> rightArr;
* rightArr->SetNumberOfComponents(1);
* rightArr->SetNumberOfTuples(1);
* rightArr->SetValue(0, 1);
* vtkNew<vtkCompositeArray<int>> compositeArr;
* compositeArr->SetBackend(std::make_shared<vtkCompositeImplicitBackend<int>>(leftArr, rightArr));
* CHECK(compositArr->GetValue(1) == 1);
* ```
* @sa
* vtkImplicitArray vtkCompositeImplicitBackend
*/
@ -48,11 +62,12 @@ template <typename T>
using vtkCompositeArray = vtkImplicitArray<vtkCompositeImplicitBackend<T>>;
VTK_ABI_NAMESPACE_END
namespace vtkCompositeArrayUtilities
namespace vtk
{
VTK_ABI_NAMESPACE_BEGIN
template <typename T>
vtkSmartPointer<vtkCompositeArray<T>> Concatenate(const std::vector<vtkDataArray*>& arrays);
vtkSmartPointer<vtkCompositeArray<T>> ConcatenateDataArrays(
const std::vector<vtkDataArray*>& arrays);
VTK_ABI_NAMESPACE_END
}
@ -65,12 +80,12 @@ VTK_ABI_NAMESPACE_END
template class VTKCOMMONIMPLICITARRAYS_EXPORT \
vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>; \
VTK_ABI_NAMESPACE_END \
namespace vtkCompositeArrayUtilities \
namespace vtk \
{ \
VTK_ABI_NAMESPACE_BEGIN \
template VTKCOMMONIMPLICITARRAYS_EXPORT \
vtkSmartPointer<vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>> \
Concatenate(const std::vector<vtkDataArray*>& arrays); \
ConcatenateDataArrays(const std::vector<vtkDataArray*>& arrays); \
VTK_ABI_NAMESPACE_END \
} \
namespace vtkDataArrayPrivate \

View File

@ -3,11 +3,12 @@
#include "vtkDataArray.h"
//-----------------------------------------------------------------------
namespace vtkCompositeArrayUtilities
namespace vtk
{
VTK_ABI_NAMESPACE_BEGIN
template <typename T>
vtkSmartPointer<vtkCompositeArray<T>> Concatenate(const std::vector<vtkDataArray*>& arrays)
vtkSmartPointer<vtkCompositeArray<T>> ConcatenateDataArrays(
const std::vector<vtkDataArray*>& arrays)
{
if (arrays.size() < 2)
{

View File

@ -37,7 +37,8 @@
* rightArr->SetNumberOfComponents(1);
* rightArr->SetNumberOfTuples(1);
* rightArr->SetValue(0, 1);
* vtkNew<vtkImplicitArray<vtkCompositeImplicitBackend<int>>> compositeArr;
* vtkNew<vtkImplicitArray<vtkCompositeImplicitBackend<int>>> compositeArr; // easier with
* `vtkNew<vtkCompositeArray<int>> compositeArr;` if applicable
* compositeArr->SetBackend(std::make_shared<vtkCompositeImplicitBackend<int>>(leftArr, rightArr));
* CHECK(compositArr->GetValue(1) == 1);
* ```
@ -51,9 +52,19 @@ template <typename ValueType>
class vtkCompositeImplicitBackend
{
public:
/**
* Constructor for the backend
* @param leftArr the array starting the composite at index 0
* @param rightArr the array following the leftArr and starting at index
* leftArr->GetNumberOfTuples()
*/
vtkCompositeImplicitBackend(vtkDataArray* leftArr, vtkDataArray* rightArr);
~vtkCompositeImplicitBackend();
/**
* Indexing operator for the composite of the two arrays respecting the `vtkImplicitArray`
* expectations
*/
ValueType operator()(int idx) const;
protected:

View File

@ -31,7 +31,7 @@ struct vtkCompositeImplicitBackend<ValueType>::Internals
{
if (this->Left == nullptr || this->Right == nullptr)
{
vtkWarningWithObjectMacro(nullptr, "Creating composite array with nullptr");
vtkErrorWithObjectMacro(nullptr, "Creating composite array with nullptr");
return;
}
this->LeftRange = vtk::DataArrayValueRange(this->Left);
@ -39,9 +39,9 @@ struct vtkCompositeImplicitBackend<ValueType>::Internals
this->Offset = this->LeftRange.size();
}
vtkSmartPointer<vtkDataArray> Left;
const vtkSmartPointer<vtkDataArray> Left;
vtk::detail::SelectValueRange<vtkDataArray*, vtk::detail::DynamicTupleSize>::type LeftRange;
vtkSmartPointer<vtkDataArray> Right;
const vtkSmartPointer<vtkDataArray> Right;
vtk::detail::SelectValueRange<vtkDataArray*, vtk::detail::DynamicTupleSize>::type RightRange;
int Offset = -1;
};
@ -56,9 +56,7 @@ vtkCompositeImplicitBackend<ValueType>::vtkCompositeImplicitBackend(
//-----------------------------------------------------------------------
template <typename ValueType>
vtkCompositeImplicitBackend<ValueType>::~vtkCompositeImplicitBackend()
{
}
vtkCompositeImplicitBackend<ValueType>::~vtkCompositeImplicitBackend() = default;
//-----------------------------------------------------------------------
template <typename ValueType>

View File

@ -1,8 +1,8 @@
# `vtkCompositeArray`: a new implicit array that concatenates other arrays together
## `vtkCompositeArray`: a new implicit array that concatenates other arrays together
`vtkCompositeArray` is now available in VTK! It is a family of `vtkImplicitArray`s that can concatenate arrays together to interface a group of arrays as if they were a single array.
The new `vtkCompositeArray` is a family of `vtkImplicitArray`s that can concatenate arrays together to interface a group of arrays as if they were a single array. This concatenation operates in the "tuple" direction and not in the "component" direction.
This new array relies on the `vtkCompositeImplicitBackend` template class to join `vtkDataArray`s two at a time. Creating a hiearchy of `vtkCompositeArray`s can generate a binary tree on the indexes of the composite array leading to access with $O(log_2(m))$ time where $m$ is the number of leaves (or base `vtkDataArray`s) composing the composite (or alternatively $O(l)$ where $l$ is the number of levels in the tree).
This new array relies on the `vtkCompositeImplicitBackend` template class to join two `vtkDataArray`s at a time. Creating a hiearchy of `vtkCompositeArray`s can generate a binary tree on the indexes of the composite array leading to access with $O(log_2(m))$ time where $m$ is the number of leaves (or base `vtkDataArray`s) composing the composite (or alternatively $O(l)$ where $l$ is the number of levels in the tree).
To facilitate the creation of `vtkCompositeArray`s in practice, a templated utility function `vtkCompositeArrayUtilities::Concatenate` has been made available to users that can take an `std::vector` of `vtkDataArray`s and turn them into a single concatenated `vtkCompositeArray` whose tree structure should be balanced with respect to number of arrays (a possible improvement would be to balance with respect to number of tuples following a "Huffman coding" approach).