Merge topic 'sharedResourceArrays'

121f39a8da review(CompositeArr): allow for nullptr in backend construction
86a5ba59e2 review(CompositeArr): improve doc + refactor + improve testing
e7a38ffa71 build(impArr): include dispatch list header for module
dca028f653 add(TypeList): empty type list `CreateImpl` specialization
b9a5755f19 add(changelog): describe `vtkCompositeArray` implementation
c0233ec6dd improve(CompositeArray): switch ordering of allocation
2bb46a9b06 add(impArr): module headers for all arrays
73b84ead94 improve(CompositeArr): remove dispatch from implementation
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Acked-by: Mathieu Westphal <mathieu.westphal@kitware.com>
Merge-request: !9691
dev
Julien Fausty 2 months ago committed by Kitware Robot
commit 98e4267bbf

@ -55,6 +55,12 @@ struct CreateImpl<T1>
using type = vtkTypeList::TypeList<T1, vtkTypeList::NullType>;
};
template <>
struct CreateImpl<>
{
using type = vtkTypeList::NullType;
};
template <typename T1, typename T2, typename T3, typename T4, typename... Tail>
struct CreateImpl<T1, T2, T3, T4, Tail...>
{

@ -1,9 +1,11 @@
option(VTK_DISPATCH_AFFINE_ARRAYS "Include implicit vtkDataArray subclasses based on an affine function backend in dispatcher" OFF)
option(VTK_DISPATCH_COMPOSITE_ARRAYS "Include implicit vtkDataArray subclasses based on a composite binary tree backend in dispatcher" OFF)
option(VTK_DISPATCH_CONSTANT_ARRAYS "Include implicit vtkDataArray subclasses based on a constant backend in dispatcher" OFF)
option(VTK_DISPATCH_STD_FUNCTION_ARRAYS "Include implicit vtkDataArray subclasses based on std::function in dispatcher" OFF)
mark_as_advanced(
VTK_DISPATCH_CONSTANT_ARRAYS
VTK_DISPATCH_AFFINE_ARRAYS
VTK_DISPATCH_COMPOSITE_ARRAYS
VTK_DISPATCH_CONSTANT_ARRAYS
VTK_DISPATCH_STD_FUNCTION_ARRAYS
)
@ -31,6 +33,8 @@ foreach (INSTANTIATION_VALUE_TYPE IN LISTS vtkArrayDispatchImplicit_all_types)
string(REPLACE " " "_" _suffix "${INSTANTIATION_VALUE_TYPE}")
list(APPEND _list "vtkAffineArrayInstantiate")
list(APPEND _list "vtkCompositeArrayInstantiate")
list(APPEND _list "vtkCompositeImplicitBackendInstantiate")
list(APPEND _list "vtkConstantArrayInstantiate")
list(APPEND _list "vtkStdFunctionArrayInstantiate")
@ -48,15 +52,18 @@ endforeach ()
set(nowrap_headers
vtkAffineArray.h
vtkAffineImplicitBackend.h
vtkCompositeArray.h
vtkConstantArray.h
vtkConstantImplicitBackend.h
vtkImplicitArrayTraits.h
vtkStdFunctionArray.h
"${CMAKE_CURRENT_BINARY_DIR}/vtkVTK_DISPATCH_IMPLICIT_ARRAYS.h"
"${CMAKE_CURRENT_BINARY_DIR}/vtkArrayDispatchImplicitArrayList.h"
)
set(nowrap_template_classes
vtkImplicitArray
vtkCompositeImplicitBackend
)
set(sources

@ -1,6 +1,8 @@
vtk_add_test_cxx(vtkCommonImplicitArrayCxxTests tests
NO_DATA NO_OUTPUT NO_VALID
TestAffineArray.cxx
TestCompositeArray.cxx
TestCompositeImplicitBackend.cxx
TestConstantArray.cxx
TestImplicitArraysBase.cxx
TestImplicitArrayTraits.cxx

@ -0,0 +1,161 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestCompositeArray.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkCompositeArray.h"
#include "vtkAffineArray.h"
#include "vtkDataArrayRange.h"
#include "vtkIntArray.h"
#include "vtkVTK_DISPATCH_IMPLICIT_ARRAYS.h"
#ifdef VTK_DISPATCH_COMPOSITE_ARRAYS
#include "vtkArrayDispatch.h"
#include "vtkArrayDispatchImplicitArrayList.h"
#endif // VTK_DISPATCH_AFFINE_ARRAYS
#include <cstdlib>
#include <memory>
namespace
{
#ifdef VTK_DISPATCH_COMPOSITE_ARRAYS
struct ScaleWorker
{
template <typename SrcArray, typename DstArray>
void operator()(SrcArray* srcArr, DstArray* dstArr, double scale)
{
using SrcType = vtk::GetAPIType<SrcArray>;
using DstType = vtk::GetAPIType<DstArray>;
const auto srcRange = vtk::DataArrayValueRange(srcArr);
auto dstRange = vtk::DataArrayValueRange(dstArr);
if (srcRange.size() != dstRange.size())
{
std::cout << "Different array sizes in ScaleWorker" << std::endl;
return;
}
auto dstIter = dstRange.begin();
for (SrcType srcVal : srcRange)
{
*dstIter++ = static_cast<DstType>(srcVal * scale);
}
}
};
#endif // VTK_DISPATCH_COMPOSITE_ARRAYS
vtkSmartPointer<vtkCompositeArray<int>> SetupCompositeArray(int length)
{
std::vector<vtkSmartPointer<vtkAffineArray<int>>> affArrays(length / 20);
std::vector<vtkSmartPointer<vtkIntArray>> intArrays(length / 20);
for (int i = 0; i < length / 20; ++i)
{
vtkNew<vtkAffineArray<int>> affine;
affine->SetBackend(std::make_shared<vtkAffineImplicitBackend<int>>(1, i * 20));
affine->SetNumberOfTuples(10);
affine->SetNumberOfComponents(1);
affArrays[i] = affine;
}
for (int i = 0; i < length / 20; ++i)
{
vtkNew<vtkIntArray> iota;
iota->SetNumberOfTuples(10);
iota->SetNumberOfComponents(1);
auto range = vtk::DataArrayValueRange<1>(iota);
std::iota(range.begin(), range.end(), 10 * (2 * i + 1));
intArrays[i] = iota;
}
std::vector<vtkDataArray*> interleaf;
for (int i = 0; i < length / 20; ++i)
{
interleaf.emplace_back(affArrays[i]);
interleaf.emplace_back(intArrays[i]);
}
return vtk::ConcatenateDataArrays<int>(interleaf);
}
}
int TestCompositeArray(int vtkNotUsed(argc), char* vtkNotUsed(argv)[])
{
int res = EXIT_SUCCESS;
vtkSmartPointer<vtkCompositeArray<int>> composite = ::SetupCompositeArray(100);
for (int iArr = 0; iArr < 100; iArr++)
{
if (composite->GetValue(iArr) != iArr)
{
res = EXIT_FAILURE;
std::cout << "get value failed with vtkCompositeArray: " << iArr
<< " != " << composite->GetValue(iArr) << std::endl;
}
}
int iArr = 0;
for (auto val : vtk::DataArrayValueRange<1>(composite))
{
if (val != iArr)
{
res = EXIT_FAILURE;
std::cout << "range iterator failed with vtkCompositerray" << std::endl;
}
iArr++;
}
#ifdef VTK_DISPATCH_COMPOSITE_ARRAYS
std::cout << "vtkCompositeArray: performing dispatch tests" << std::endl;
vtkNew<vtkIntArray> destination;
destination->SetNumberOfTuples(100);
destination->SetNumberOfComponents(1);
using Dispatcher =
vtkArrayDispatch::Dispatch2ByArray<vtkArrayDispatch::ReadOnlyArrays, vtkArrayDispatch::Arrays>;
::ScaleWorker worker;
if (!Dispatcher::Execute(composite, destination, worker, 3.0))
{
res = EXIT_FAILURE;
std::cout << "vtkArrayDispatch failed with vtkCompositeArray" << std::endl;
worker(composite.Get(), destination.Get(), 3.0);
}
iArr = 0;
for (auto val : vtk::DataArrayValueRange<1>(destination))
{
if (val != 3 * iArr)
{
res = EXIT_FAILURE;
std::cout << "dispatch failed to populate the array with the correct values" << std::endl;
}
iArr++;
}
#endif // VTK_DISPATCH_COMPOSITE_ARRAYS
// test a 1 composite
vtkSmartPointer<vtkCompositeArray<int>> oneComposite =
vtk::ConcatenateDataArrays<int>(std::vector<vtkDataArray*>({ composite }));
for (iArr = 0; iArr < 100; iArr++)
{
if (oneComposite->GetValue(iArr) != iArr)
{
res = EXIT_FAILURE;
std::cout << "get value failed with vtkCompositeArray for composite with one array: " << iArr
<< " != " << composite->GetValue(iArr) << std::endl;
}
}
return res;
};

@ -0,0 +1,78 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestCompositeImplicitBackend.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkCompositeImplicitBackend.h"
#include "vtkCompositeImplicitBackend.txx"
#include "vtkDataArrayRange.h"
#include "vtkIntArray.h"
#include <algorithm>
#include <numeric>
int TestCompositeImplicitBackend(int, char*[])
{
// Setup branches
vtkNew<vtkIntArray> left;
left->SetNumberOfComponents(1);
left->SetNumberOfTuples(10);
auto leftRange = vtk::DataArrayValueRange<1>(left);
std::iota(leftRange.begin(), leftRange.end(), 0);
vtkNew<vtkIntArray> right;
right->SetNumberOfComponents(1);
right->SetNumberOfTuples(10);
auto rightRange = vtk::DataArrayValueRange<1>(right);
std::iota(rightRange.begin(), rightRange.end(), 10);
// Make structure
vtkCompositeImplicitBackend<int> composite(left, right);
// Do checks on structure
for (int i = 0; i < 20; ++i)
{
if (i != composite(i))
{
std::cout << "Composite backend operator not functioning: " << i << " != " << composite(i)
<< std::endl;
return EXIT_FAILURE;
}
}
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;
}

@ -21,7 +21,8 @@
#include "vtkDataArrayPrivate.txx"
#endif
#include "vtkAffineImplicitBackend.h" // for the array backend
#include "vtkAffineImplicitBackend.h" // for the array backend
#include "vtkCommonImplicitArraysModule.h" // for export macro
#include "vtkImplicitArray.h"
#ifdef VTK_AFFINE_ARRAY_INSTANTIATING

@ -0,0 +1,109 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompositeArray.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef vtkCompositeArray_h
#define vtkCompositeArray_h
#ifdef VTK_COMPOSITE_ARRAY_INSTANTIATING
#define VTK_IMPLICIT_VALUERANGE_INSTANTIATING
#include "vtkDataArrayPrivate.txx"
#endif
#include "vtkCommonImplicitArraysModule.h" // for export macro
#include "vtkCompositeImplicitBackend.h" // for the array backend
#include "vtkImplicitArray.h"
#ifdef VTK_COMPOSITE_ARRAY_INSTANTIATING
#undef VTK_IMPLICIT_VALUERANGE_INSTANTIATING
#endif
#include <vector>
/**
* \var vtkCompositeArray
* \brief A utility alias for concatenating arrays into an implicit array
*
* 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));
* compositeArr->SetNumberOfComponents(1);
* compositeArr->SetNumberOfTuples(2);
* CHECK(compositArr->GetValue(1) == 1);
* ```
* @sa
* vtkImplicitArray vtkCompositeImplicitBackend
*/
VTK_ABI_NAMESPACE_BEGIN
class vtkDataArray;
template <typename T>
using vtkCompositeArray = vtkImplicitArray<vtkCompositeImplicitBackend<T>>;
VTK_ABI_NAMESPACE_END
namespace vtk
{
VTK_ABI_NAMESPACE_BEGIN
template <typename T>
/**
* \fn ConcatenateDataArrays
* A method that can take a `std::vector` of `vtkDataArray`s and concatenate them together into a
* single `vtkCompositeArray`. Input arrays should all have the same number of components and the
* resulting composite array has as many tuples as the sum of all the inputs.
*
* The method is templated based on the value type of composite array the caller wishes as a result.
*/
vtkSmartPointer<vtkCompositeArray<T>> ConcatenateDataArrays(
const std::vector<vtkDataArray*>& arrays);
VTK_ABI_NAMESPACE_END
}
#endif // vtkCompositeArray_h
#ifdef VTK_COMPOSITE_ARRAY_INSTANTIATING
#define VTK_INSTANTIATE_COMPOSITE_ARRAY(ValueType) \
VTK_ABI_NAMESPACE_BEGIN \
template class VTKCOMMONIMPLICITARRAYS_EXPORT \
vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>; \
VTK_ABI_NAMESPACE_END \
namespace vtk \
{ \
VTK_ABI_NAMESPACE_BEGIN \
template VTKCOMMONIMPLICITARRAYS_EXPORT \
vtkSmartPointer<vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>> \
ConcatenateDataArrays(const std::vector<vtkDataArray*>& arrays); \
VTK_ABI_NAMESPACE_END \
} \
namespace vtkDataArrayPrivate \
{ \
VTK_ABI_NAMESPACE_BEGIN \
VTK_INSTANTIATE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>, double) \
VTK_ABI_NAMESPACE_END \
}
#endif

@ -0,0 +1,65 @@
#include "vtkCompositeArray.h"
#include "vtkDataArray.h"
//-----------------------------------------------------------------------
namespace vtk
{
VTK_ABI_NAMESPACE_BEGIN
template <typename T>
vtkSmartPointer<vtkCompositeArray<T>> ConcatenateDataArrays(
const std::vector<vtkDataArray*>& arrays)
{
if (arrays.size() == 0)
{
return nullptr;
}
if (arrays.size() == 1)
{
vtkNew<vtkCompositeArray<T>> composite;
composite->SetBackend(std::make_shared<vtkCompositeImplicitBackend<T>>(arrays[0], nullptr));
composite->SetNumberOfComponents(arrays[0]->GetNumberOfComponents());
composite->SetNumberOfTuples(arrays[0]->GetNumberOfTuples());
return composite;
}
vtkIdType nComps = arrays[0]->GetNumberOfComponents();
for (auto arr : arrays)
{
if (arr->GetNumberOfComponents() != nComps)
{
vtkErrorWithObjectMacro(nullptr, "Number of components of all the arrays are not equal");
return nullptr;
}
}
std::vector<vtkSmartPointer<vtkDataArray>> lifetimeBuffer;
lifetimeBuffer.assign(arrays.begin(), arrays.end());
std::vector<vtkSmartPointer<vtkCompositeArray<T>>> newComps;
while (lifetimeBuffer.size() != 1)
{
newComps.clear();
for (int i = 0; i < static_cast<int>(lifetimeBuffer.size() - 1); i += 2)
{
vtkNew<vtkCompositeArray<T>> composite;
composite->SetBackend(
std::make_shared<vtkCompositeImplicitBackend<T>>(lifetimeBuffer[i], lifetimeBuffer[i + 1]));
composite->SetNumberOfComponents(lifetimeBuffer[i]->GetNumberOfComponents());
composite->SetNumberOfTuples(
lifetimeBuffer[i]->GetNumberOfTuples() + lifetimeBuffer[i + 1]->GetNumberOfTuples());
newComps.emplace_back(composite);
}
if (lifetimeBuffer.size() % 2 != 0)
{
vtkNew<vtkCompositeArray<T>> composite;
composite->SetBackend(
std::make_shared<vtkCompositeImplicitBackend<T>>(newComps.back(), lifetimeBuffer.back()));
composite->SetNumberOfComponents(lifetimeBuffer.back()->GetNumberOfComponents());
composite->SetNumberOfTuples(
newComps.back()->GetNumberOfTuples() + lifetimeBuffer.back()->GetNumberOfTuples());
newComps.back() = composite;
}
lifetimeBuffer.assign(newComps.begin(), newComps.end());
}
return newComps[0];
}
VTK_ABI_NAMESPACE_END
}

@ -0,0 +1,19 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompositeArray.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#define VTK_COMPOSITE_ARRAY_INSTANTIATING
#include "vtkCompositeArray.h"
#include "vtkCompositeArray.txx"
VTK_INSTANTIATE_COMPOSITE_ARRAY(@INSTANTIATION_VALUE_TYPE@)

@ -0,0 +1,87 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompositeImplicitBackend.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef vtkCompositeImplicitBackend_h
#define vtkCompositeImplicitBackend_h
/**
* \class vtkCompositeImplicitBackend
* \brief A utility structure serving as a backend for composite arrays: an array composed of
* multiple arrays concatenated together
*
* This structure can be classified as a closure and can be called using syntax similar to a
* function call.
*
* The class implements a binary tree like structure for facilitating fast access.
*
* At construction it takes two arrays in order to represent their concatenation.
*
* An example of potential usage in a vtkImplicitArray
* ```
* 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<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);
* ```
*
* > WARNING:
* > Arrays input to the backend are flattened upon use and are no longer sensitive to component
* > information.
*/
#include "vtkCommonImplicitArraysModule.h"
#include <memory>
VTK_ABI_NAMESPACE_BEGIN
class vtkDataArray;
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:
struct Internals;
std::unique_ptr<Internals> Internal;
};
VTK_ABI_NAMESPACE_END
#endif // vtkCompositeImplicitBackend_h
#ifdef VTK_COMPOSITE_BACKEND_INSTANTIATING
#define VTK_INSTANTIATE_COMPOSITE_BACKEND(ValueType) \
VTK_ABI_NAMESPACE_BEGIN \
template class VTKCOMMONIMPLICITARRAYS_EXPORT vtkCompositeImplicitBackend<ValueType>; \
VTK_ABI_NAMESPACE_END
#endif

@ -0,0 +1,79 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompositeImplicitBackend.txx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkCompositeImplicitBackend.h"
#include "vtkAOSDataArrayTemplate.h"
#include "vtkArrayDispatch.h"
#include "vtkArrayDispatchImplicitArrayList.h"
#include "vtkDataArray.h"
#include "vtkDataArrayRange.h"
#include "vtkSmartPointer.h"
VTK_ABI_NAMESPACE_BEGIN
//-----------------------------------------------------------------------
template <typename ValueType>
struct vtkCompositeImplicitBackend<ValueType>::Internals
{
Internals(vtkDataArray* leftArr, vtkDataArray* rightArr)
: Left(leftArr)
, Right(rightArr)
{
if (!this->Left && !this->Right)
{
vtkWarningWithObjectMacro(nullptr, "Creating composite array with two nullptrs");
}
auto checkNullRectify = [](vtkSmartPointer<vtkDataArray>& arr) {
if (!arr)
{
arr = vtkSmartPointer<vtkAOSDataArrayTemplate<ValueType>>::New();
arr->SetNumberOfComponents(1);
arr->SetNumberOfTuples(0);
}
};
checkNullRectify(this->Left);
checkNullRectify(this->Right);
this->LeftRange = vtk::DataArrayValueRange(this->Left);
this->RightRange = vtk::DataArrayValueRange(this->Right);
this->Offset = this->LeftRange.size();
}
vtkSmartPointer<vtkDataArray> Left;
vtk::detail::SelectValueRange<vtkDataArray*, vtk::detail::DynamicTupleSize>::type LeftRange;
vtkSmartPointer<vtkDataArray> Right;
vtk::detail::SelectValueRange<vtkDataArray*, vtk::detail::DynamicTupleSize>::type RightRange;
int Offset = -1;
};
//-----------------------------------------------------------------------
template <typename ValueType>
vtkCompositeImplicitBackend<ValueType>::vtkCompositeImplicitBackend(
vtkDataArray* leftArr, vtkDataArray* rightArr)
: Internal(std::unique_ptr<Internals>(new Internals(leftArr, rightArr)))
{
}
//-----------------------------------------------------------------------
template <typename ValueType>
vtkCompositeImplicitBackend<ValueType>::~vtkCompositeImplicitBackend() = default;
//-----------------------------------------------------------------------
template <typename ValueType>
ValueType vtkCompositeImplicitBackend<ValueType>::operator()(int idx) const
{
return static_cast<ValueType>((idx < this->Internal->Offset)
? this->Internal->LeftRange[idx]
: this->Internal->RightRange[idx - this->Internal->Offset]);
}
VTK_ABI_NAMESPACE_END

@ -0,0 +1,19 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompositeImplicitBackend.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#define VTK_COMPOSITE_BACKEND_INSTANTIATING
#include "vtkCompositeImplicitBackend.h"
#include "vtkCompositeImplicitBackend.txx"
VTK_INSTANTIATE_COMPOSITE_BACKEND(@INSTANTIATION_VALUE_TYPE@)

@ -21,7 +21,8 @@
#include "vtkDataArrayPrivate.txx"
#endif
#include "vtkConstantImplicitBackend.h" // for the array backend
#include "vtkCommonImplicitArraysModule.h" // for export macro
#include "vtkConstantImplicitBackend.h" // for the array backend
#include "vtkImplicitArray.h"
#ifdef VTK_CONSTANT_ARRAY_INSTANTIATING

@ -129,6 +129,13 @@ if (VTK_DISPATCH_AFFINE_ARRAYS)
)
endif()
if (VTK_DISPATCH_COMPOSITE_ARRAYS)
list(APPEND vtkArrayDispatchImplicit_containers vtkCompositeArray)
set(vtkArrayDispatchImplicit_vtkCompositeArray_header vtkCompositeArray.h)
set(vtkArrayDispatchImplicit_vtkCompositeArray_types
${vtkArrayDispatchImplicit_all_types}
)
endif()
endmacro()

@ -313,6 +313,8 @@ VTK_ABI_NAMESPACE_BEGIN
template <typename ValueType>
struct vtkAffineImplicitBackend;
template <typename ValueType>
class vtkCompositeImplicitBackend;
template <typename ValueType>
struct vtkConstantImplicitBackend;
VTK_ABI_NAMESPACE_END
#include <functional>
@ -331,6 +333,8 @@ VTK_ABI_NAMESPACE_END
#define VTK_INSTANTIATE_VALUERANGE_VALUETYPE(ValueType) \
VTK_INSTANTIATE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkAffineImplicitBackend<ValueType>>, ValueType) \
VTK_INSTANTIATE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>, ValueType) \
VTK_INSTANTIATE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkConstantImplicitBackend<ValueType>>, ValueType) \
VTK_INSTANTIATE_VALUERANGE_ARRAYTYPE(vtkImplicitArray<std::function<ValueType(int)>>, ValueType)
@ -350,6 +354,8 @@ VTK_ABI_NAMESPACE_BEGIN
template <typename ValueType>
struct vtkAffineImplicitBackend;
template <typename ValueType>
class vtkCompositeImplicitBackend;
template <typename ValueType>
struct vtkConstantImplicitBackend;
VTK_ABI_NAMESPACE_END
#include <functional>
@ -381,6 +387,8 @@ VTK_ABI_NAMESPACE_END
#define VTK_DECLARE_VALUERANGE_VALUETYPE(ValueType) \
VTK_DECLARE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkAffineImplicitBackend<ValueType>>, ValueType) \
VTK_DECLARE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkCompositeImplicitBackend<ValueType>>, ValueType) \
VTK_DECLARE_VALUERANGE_ARRAYTYPE( \
vtkImplicitArray<vtkConstantImplicitBackend<ValueType>>, ValueType) \
VTK_DECLARE_VALUERANGE_ARRAYTYPE(vtkImplicitArray<std::function<ValueType(int)>>, ValueType)
@ -405,6 +413,7 @@ namespace vtkDataArrayPrivate
VTK_ABI_NAMESPACE_BEGIN
VTK_DECLARE_VALUERANGE_IMPLICIT_BACKENDTYPE(vtkAffineImplicitBackend)
VTK_DECLARE_VALUERANGE_IMPLICIT_BACKENDTYPE(vtkConstantImplicitBackend)
VTK_DECLARE_VALUERANGE_IMPLICIT_BACKENDTYPE(vtkCompositeImplicitBackend)
VTK_DECLARE_VALUERANGE_ARRAYTYPE(vtkImplicitArray<std::function<float(int)>>, double)
VTK_DECLARE_VALUERANGE_ARRAYTYPE(vtkImplicitArray<std::function<double(int)>>, double)

@ -21,6 +21,7 @@
#include "vtkDataArrayPrivate.txx"
#endif
#include "vtkCommonImplicitArraysModule.h" // for export macro
#include "vtkImplicitArray.h"
#ifdef VTK_STD_FUNCTION_ARRAY_INSTANTIATING

@ -16,10 +16,12 @@
#ifndef vtkVTK_DISPATCH_IMPLICIT_ARRAYS_h
#define vtkVTK_DISPATCH_IMPLICIT_ARRAYS_h
// defined if VTK dispatches the vtkConstantArray class
#cmakedefine VTK_DISPATCH_CONSTANT_ARRAYS
// defined if VTK dispatches the vtkAffineArray class
#cmakedefine VTK_DISPATCH_AFFINE_ARRAYS
// defined if VTK dispatches the vtkCompositeArray class
#cmakedefine VTK_DISPATCH_COMPOSITE_ARRAYS
// defined if VTK dispatches the vtkConstantArray class
#cmakedefine VTK_DISPATCH_CONSTANT_ARRAYS
// defined if VTK dispatches the vtkStdFunctionArray class
#cmakedefine VTK_DISPATCH_STD_FUNCTION_ARRAYS

@ -0,0 +1,26 @@
## `vtkCompositeArray`: a new implicit array that concatenates other arrays together
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 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).
A code snippet using this type of array:
```
std::vector<vtkDataArray*> baseArrays(16); // 16 == 2^4, will make 4 levels in binary tree
vtkNew<vtkDoubleArray> baseArray;
baseArray->SetNumberOfComponents(3);
baseArray->SetNumberOfTuples(10);
baseArray->Fill(0.0);
std::fill(baseArrays.begin(), baseArrays.end(), baseArray);
vtkSmartPointer<vtkCompositeArray<double>> composite = vtkCompositeArrayUtilities::Concatenate<double>(baseArrays); // nTuples = 160
CHECK(composite->GetComponent(42, 1) == 0.0); // always true
```
> **WARNINGS**
>
> * Any two arrays composited into a `vtkCompositeArray` using the `vtk::ConcatenateDataArrays` method must have the same number of components.
> * Iteration over the composited array incurs a lot of overhead compared to an explicit memory array (~3x slower with only 1 level). The use case is truly when memory efficiency is more important than compute performance.
Loading…
Cancel
Save