Add in the implementation of a `vtkIndexedImplicitBackend` to reference indexes of existing arrays in a new array without any excess memory allocation.dev
parent
08c4b0ad52
commit
6a49775c3f
@ -0,0 +1,169 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: Visualization Toolkit
|
||||
Module: TestIndexedImplicitBackend.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 "vtkIndexedImplicitBackend.h"
|
||||
|
||||
#include "vtkDataArrayRange.h"
|
||||
#include "vtkIdList.h"
|
||||
#include "vtkIntArray.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
int LoopAndTest(vtkIdList* handles, vtkIndexedImplicitBackend<int>& backend)
|
||||
{
|
||||
for (int idx = 0; idx < handles->GetNumberOfIds(); idx++)
|
||||
{
|
||||
if (backend(idx) != static_cast<int>(handles->GetId(idx)))
|
||||
{
|
||||
std::cout << "Indexed backend evaluation failed with: " << backend(idx)
|
||||
<< " != " << handles->GetId(idx) << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int TestWithIDList()
|
||||
{
|
||||
vtkNew<vtkIntArray> baseArray;
|
||||
baseArray->SetNumberOfComponents(1);
|
||||
baseArray->SetNumberOfTuples(100);
|
||||
auto range = vtk::DataArrayValueRange<1>(baseArray);
|
||||
std::iota(range.begin(), range.end(), 0);
|
||||
|
||||
vtkNew<vtkIdList> handles;
|
||||
handles->SetNumberOfIds(100);
|
||||
{
|
||||
std::vector<vtkIdType> buffer(100);
|
||||
std::iota(buffer.begin(), buffer.end(), 0);
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
std::shuffle(buffer.begin(), buffer.end(), g);
|
||||
for (vtkIdType idx = 0; idx < 100; idx++)
|
||||
{
|
||||
handles->SetId(idx, buffer[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
vtkIndexedImplicitBackend<int> backend(handles, baseArray);
|
||||
|
||||
int res = LoopAndTest(handles, backend);
|
||||
|
||||
vtkNew<vtkIntArray> baseMultiArray;
|
||||
baseMultiArray->SetNumberOfComponents(3);
|
||||
baseMultiArray->SetNumberOfTuples(100);
|
||||
auto multiRange = vtk::DataArrayValueRange<3>(baseMultiArray);
|
||||
std::iota(multiRange.begin(), multiRange.end(), 0);
|
||||
|
||||
vtkNew<vtkIdList> multiHandles;
|
||||
multiHandles->SetNumberOfIds(300);
|
||||
{
|
||||
std::vector<vtkIdType> buffer(100);
|
||||
std::iota(buffer.begin(), buffer.end(), 0);
|
||||
std::random_device randdev;
|
||||
std::mt19937 generator(randdev());
|
||||
std::shuffle(buffer.begin(), buffer.end(), generator);
|
||||
for (vtkIdType idx = 0; idx < 100; idx++)
|
||||
{
|
||||
for (vtkIdType comp = 0; comp < 3; comp++)
|
||||
{
|
||||
multiHandles->SetId(3 * idx + comp, 3 * buffer[idx] + comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vtkIndexedImplicitBackend<int> multiBackend(multiHandles, baseMultiArray);
|
||||
return LoopAndTest(multiHandles, multiBackend) == EXIT_SUCCESS ? res : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int LoopAndTest(vtkIntArray* handles, vtkIndexedImplicitBackend<int>& backend)
|
||||
{
|
||||
for (int idx = 0; idx < handles->GetNumberOfTuples(); idx++)
|
||||
{
|
||||
if (backend(idx) != static_cast<int>(handles->GetValue(idx)))
|
||||
{
|
||||
std::cout << "Indexed backend evaluation failed with: " << backend(idx)
|
||||
<< " != " << handles->GetValue(idx) << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int TestWithDataArrayIndexing()
|
||||
{
|
||||
vtkNew<vtkIntArray> baseArray;
|
||||
baseArray->SetNumberOfComponents(1);
|
||||
baseArray->SetNumberOfTuples(100);
|
||||
auto range = vtk::DataArrayValueRange<1>(baseArray);
|
||||
std::iota(range.begin(), range.end(), 0);
|
||||
|
||||
vtkNew<vtkIntArray> handles;
|
||||
handles->SetNumberOfComponents(1);
|
||||
handles->SetNumberOfTuples(100);
|
||||
{
|
||||
std::vector<int> buffer(100);
|
||||
std::iota(buffer.begin(), buffer.end(), 0);
|
||||
std::random_device randdev;
|
||||
std::mt19937 generator(randdev());
|
||||
std::shuffle(buffer.begin(), buffer.end(), generator);
|
||||
auto handleRange = vtk::DataArrayValueRange<1>(handles);
|
||||
std::copy(buffer.begin(), buffer.end(), handleRange.begin());
|
||||
}
|
||||
|
||||
vtkIndexedImplicitBackend<int> backend(handles, baseArray);
|
||||
int res = LoopAndTest(handles, backend);
|
||||
|
||||
// and with multi component entries
|
||||
|
||||
vtkNew<vtkIntArray> baseMultiArray;
|
||||
baseMultiArray->SetNumberOfComponents(3);
|
||||
baseMultiArray->SetNumberOfTuples(100);
|
||||
auto multiRange = vtk::DataArrayValueRange<3>(baseMultiArray);
|
||||
std::iota(multiRange.begin(), multiRange.end(), 0);
|
||||
|
||||
vtkNew<vtkIntArray> multiHandles;
|
||||
multiHandles->SetNumberOfComponents(1);
|
||||
multiHandles->SetNumberOfTuples(300);
|
||||
{
|
||||
std::vector<vtkIdType> buffer(100);
|
||||
std::iota(buffer.begin(), buffer.end(), 0);
|
||||
std::random_device randdev;
|
||||
std::mt19937 generator(randdev());
|
||||
std::shuffle(buffer.begin(), buffer.end(), generator);
|
||||
for (vtkIdType idx = 0; idx < 100; idx++)
|
||||
{
|
||||
for (vtkIdType comp = 0; comp < 3; comp++)
|
||||
{
|
||||
multiHandles->SetValue(3 * idx + comp, 3 * buffer[idx] + comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vtkIndexedImplicitBackend<int> multiBackend(multiHandles, baseMultiArray);
|
||||
return LoopAndTest(multiHandles, multiBackend) == EXIT_SUCCESS ? res : EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int TestIndexedImplicitBackend(int, char*[])
|
||||
{
|
||||
int res = ::TestWithIDList();
|
||||
return ::TestWithDataArrayIndexing() == EXIT_SUCCESS ? res : EXIT_FAILURE;
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: Visualization Toolkit
|
||||
Module: vtkIndexedImplicitBackend.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 vtkIndexedImplicitBackend_h
|
||||
#define vtkIndexedImplicitBackend_h
|
||||
|
||||
#include "vtkCommonImplicitArraysModule.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
VTK_ABI_NAMESPACE_BEGIN
|
||||
class vtkDataArray;
|
||||
class vtkIdList;
|
||||
template <typename ValueType>
|
||||
class vtkIndexedImplicitBackend
|
||||
{
|
||||
public:
|
||||
///@{
|
||||
/**
|
||||
* Constructor
|
||||
* @param indexes list of indexes to use for indirection of the array
|
||||
* @param array base array of interest
|
||||
*/
|
||||
vtkIndexedImplicitBackend(vtkIdList* indexes, vtkDataArray* array);
|
||||
vtkIndexedImplicitBackend(vtkDataArray* indexes, vtkDataArray* array);
|
||||
///@}
|
||||
~vtkIndexedImplicitBackend();
|
||||
|
||||
/**
|
||||
* Indexing operation for the indexed array respecting the backend expectations of
|
||||
* `vtkImplicitArray`
|
||||
*/
|
||||
ValueType operator()(int idx) const;
|
||||
|
||||
private:
|
||||
struct Internals;
|
||||
std::unique_ptr<Internals> Internal;
|
||||
};
|
||||
VTK_ABI_NAMESPACE_END
|
||||
|
||||
#endif // vtkIndexedImplicitBackend_h
|
||||
|
||||
#ifdef VTK_INDEXED_BACKEND_INSTANTIATING
|
||||
#define VTK_INSTANTIATE_INDEXED_BACKEND(ValueType) \
|
||||
VTK_ABI_NAMESPACE_BEGIN \
|
||||
template class VTKCOMMONIMPLICITARRAYS_EXPORT vtkIndexedImplicitBackend<ValueType>; \
|
||||
VTK_ABI_NAMESPACE_END
|
||||
#endif
|
@ -0,0 +1,203 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: Visualization Toolkit
|
||||
Module: vtkIndexedImplicitBackend.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 "vtkIndexedImplicitBackend.h"
|
||||
|
||||
#include "vtkArrayDispatch.h"
|
||||
#include "vtkArrayDispatchImplicitArrayList.h"
|
||||
#include "vtkDataArrayRange.h"
|
||||
#include "vtkIdList.h"
|
||||
#include "vtkImplicitArray.h"
|
||||
#include "vtkTypeList.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace
|
||||
{
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
struct TypedArrayCache
|
||||
{
|
||||
virtual ValueType GetValue(int idx) const = 0;
|
||||
virtual ~TypedArrayCache() = default;
|
||||
};
|
||||
|
||||
template <typename ValueType, typename ArrayT>
|
||||
struct SpecializedCache : public TypedArrayCache<ValueType>
|
||||
{
|
||||
public:
|
||||
SpecializedCache(ArrayT* arr)
|
||||
: Array(arr)
|
||||
{
|
||||
}
|
||||
|
||||
ValueType GetValue(int idx) const override
|
||||
{
|
||||
return static_cast<ValueType>(this->Array->GetValue(idx));
|
||||
}
|
||||
|
||||
private:
|
||||
vtkSmartPointer<ArrayT> Array;
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
struct SpecializedCache<ValueType, vtkDataArray> : public TypedArrayCache<ValueType>
|
||||
{
|
||||
public:
|
||||
SpecializedCache(vtkDataArray* arr)
|
||||
: Array(arr)
|
||||
{
|
||||
}
|
||||
|
||||
ValueType GetValue(int idx) const override
|
||||
{
|
||||
int iTup = idx / this->Array->GetNumberOfComponents();
|
||||
int iComp = idx - iTup * this->Array->GetNumberOfComponents();
|
||||
return static_cast<ValueType>(this->Array->GetComponent(iTup, iComp));
|
||||
}
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkDataArray> Array;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
struct CacheDispatchWorker
|
||||
{
|
||||
template <typename ArrayT>
|
||||
void operator()(ArrayT* arr, std::shared_ptr<TypedArrayCache<ValueType>>& cache)
|
||||
{
|
||||
cache = std::make_shared<SpecializedCache<ValueType, ArrayT>>(arr);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ArrayList, typename ValueType>
|
||||
struct TypedCacheWrapper
|
||||
{
|
||||
TypedCacheWrapper(vtkDataArray* arr)
|
||||
{
|
||||
CacheDispatchWorker<ValueType> worker;
|
||||
if (!Dispatcher::Execute(arr, worker, this->Cache))
|
||||
{
|
||||
worker(arr, this->Cache);
|
||||
}
|
||||
}
|
||||
|
||||
ValueType operator()(int idx) const { return this->Cache->GetValue(idx); }
|
||||
|
||||
private:
|
||||
using Dispatcher = vtkArrayDispatch::DispatchByArray<ArrayList>;
|
||||
std::shared_ptr<TypedArrayCache<ValueType>> Cache = nullptr;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct IdListWrapper
|
||||
{
|
||||
IdListWrapper(vtkIdList* indexes)
|
||||
: Handles(indexes)
|
||||
{
|
||||
}
|
||||
|
||||
vtkIdType operator()(int idx) const { return this->Handles->GetId(idx); }
|
||||
|
||||
vtkSmartPointer<vtkIdList> Handles;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
VTK_ABI_NAMESPACE_BEGIN
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
struct vtkIndexedImplicitBackend<ValueType>::Internals
|
||||
{
|
||||
using InternalArrayList = vtkTypeList::Append<vtkArrayDispatch::AllArrays,
|
||||
vtkTypeList::Create<vtkImplicitArray<::IdListWrapper>>>::Result;
|
||||
|
||||
Internals(vtkIdList* indexes, vtkDataArray* array)
|
||||
{
|
||||
if (!indexes || !array)
|
||||
{
|
||||
vtkErrorWithObjectMacro(nullptr, "Either index array or array itself is nullptr");
|
||||
return;
|
||||
}
|
||||
vtkNew<vtkImplicitArray<::IdListWrapper>> newHandles;
|
||||
newHandles->SetBackend(std::make_shared<IdListWrapper>(indexes));
|
||||
newHandles->SetNumberOfComponents(1);
|
||||
newHandles->SetNumberOfTuples(indexes->GetNumberOfIds());
|
||||
this->Handles = this->TypeCacheArray<vtkIdType>(newHandles);
|
||||
this->Array = this->TypeCacheArray<ValueType>(array);
|
||||
}
|
||||
|
||||
Internals(vtkDataArray* indexes, vtkDataArray* array)
|
||||
{
|
||||
if (!indexes || !array)
|
||||
{
|
||||
vtkErrorWithObjectMacro(nullptr, "Either index array or array itself is nullptr");
|
||||
return;
|
||||
}
|
||||
if (indexes->GetNumberOfComponents() != 1)
|
||||
{
|
||||
vtkErrorWithObjectMacro(nullptr,
|
||||
"Passed a vtkDataArray with multiple components as indexing array to vtkIndexedArray");
|
||||
return;
|
||||
}
|
||||
this->Handles = this->TypeCacheArray<vtkIdType>(indexes);
|
||||
this->Array = this->TypeCacheArray<ValueType>(array);
|
||||
}
|
||||
|
||||
template <typename VT>
|
||||
static vtkSmartPointer<vtkImplicitArray<::TypedCacheWrapper<InternalArrayList, VT>>>
|
||||
TypeCacheArray(vtkDataArray* da)
|
||||
{
|
||||
vtkNew<vtkImplicitArray<::TypedCacheWrapper<InternalArrayList, VT>>> wrapped;
|
||||
wrapped->SetBackend(std::make_shared<::TypedCacheWrapper<InternalArrayList, VT>>(da));
|
||||
wrapped->SetNumberOfComponents(1);
|
||||
wrapped->SetNumberOfTuples(da->GetNumberOfTuples() * da->GetNumberOfComponents());
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkImplicitArray<::TypedCacheWrapper<InternalArrayList, ValueType>>> Array;
|
||||
vtkSmartPointer<vtkImplicitArray<::TypedCacheWrapper<InternalArrayList, vtkIdType>>> Handles;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
vtkIndexedImplicitBackend<ValueType>::vtkIndexedImplicitBackend(
|
||||
vtkIdList* indexes, vtkDataArray* array)
|
||||
: Internal(std::unique_ptr<Internals>(new Internals(indexes, array)))
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
vtkIndexedImplicitBackend<ValueType>::vtkIndexedImplicitBackend(
|
||||
vtkDataArray* indexes, vtkDataArray* array)
|
||||
: Internal(std::unique_ptr<Internals>(new Internals(indexes, array)))
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
vtkIndexedImplicitBackend<ValueType>::~vtkIndexedImplicitBackend()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template <typename ValueType>
|
||||
ValueType vtkIndexedImplicitBackend<ValueType>::operator()(int idx) const
|
||||
{
|
||||
return this->Internal->Array->GetValue(this->Internal->Handles->GetValue(idx));
|
||||
}
|
||||
VTK_ABI_NAMESPACE_END
|
@ -0,0 +1,19 @@
|
||||
/*=========================================================================
|
||||
|
||||
Program: Visualization Toolkit
|
||||
Module: vtkIndexedImplicitBackend.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_INDEXED_BACKEND_INSTANTIATING
|
||||
#include "vtkIndexedImplicitBackend.h"
|
||||
#include "vtkIndexedImplicitBackend.txx"
|
||||
|
||||
VTK_INSTANTIATE_INDEXED_BACKEND(@INSTANTIATION_VALUE_TYPE@)
|
Loading…
Reference in new issue