HTGFixUnlimitedToRoot121f39a8da
review(CompositeArr): allow for nullptr in backend construction86a5ba59e2
review(CompositeArr): improve doc + refactor + improve testinge7a38ffa71
build(impArr): include dispatch list header for moduledca028f653
add(TypeList): empty type list `CreateImpl` specializationb9a5755f19
add(changelog): describe `vtkCompositeArray` implementationc0233ec6dd
improve(CompositeArray): switch ordering of allocation2bb46a9b06
add(impArr): module headers for all arrays73b84ead94
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
commit
98e4267bbf
@ -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;
|
||||
}
|
@ -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@)
|
@ -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…
Reference in new issue