You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
9.4 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkArrayListTemplate.h
Copyright (c) Kitware, Inc.
All rights reserved.
See LICENSE file 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.
=========================================================================*/
/**
* @class vtkArrayListTemplate
* @brief thread-safe and efficient data attribute manipulation
*
*
* vtkArrayListTemplate supplements the vtkDataSetAttributes class to provide
* threaded processing of data arrays. It is also more efficient for certain
* interpolation operations. The expectation is that it will be replaced one
* day once vtkPointData, vtkCellData, vtkDataSetAttributes, and vtkFieldData
* properly support multithreading and/or are redesigned. Note that this
* implementation does not support incremental operations (like InsertNext()).
*
* Generally the way this helper class is used is to first invoke
* vtkDataSetAttributes::CopyInterpolate() or InterpolateAllocate() which
* performs the initial magic of constructing input and output arrays. Then
* the input attributes, and output attributes, are passed to initialize the
* internal structures. Essentially these internal structures are pairs of
* arrays of the same type, which can be efficiently accessed and
* assigned. The operations on these array pairs (e.g., interpolation) occur
* using a typeless, virtual dispatch base class.
*
* @sa
* vtkFieldData vtkDataSetAttributes vtkPointData vtkCellData
*/
#ifndef vtkArrayListTemplate_h
#define vtkArrayListTemplate_h
#include "vtkDataArray.h"
#include "vtkDataSetAttributes.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include <algorithm>
#include <vector>
// Create a generic class supporting virtual dispatch to type-specific
// subclasses.
struct BaseArrayPair
{
vtkIdType Num;
int NumComp;
vtkSmartPointer<vtkDataArray> OutputArray;
BaseArrayPair(vtkIdType num, int numComp, vtkDataArray* outArray)
: Num(num)
, NumComp(numComp)
, OutputArray(outArray)
{
}
virtual ~BaseArrayPair() {}
virtual void Copy(vtkIdType inId, vtkIdType outId) = 0;
virtual void Interpolate(
int numWeights, const vtkIdType* ids, const double* weights, vtkIdType outId) = 0;
virtual void InterpolateEdge(vtkIdType v0, vtkIdType v1, double t, vtkIdType outId) = 0;
virtual void AssignNullValue(vtkIdType outId) = 0;
virtual void Realloc(vtkIdType sze) = 0;
};
// Type specific interpolation on a matched pair of data arrays
template <typename T>
struct ArrayPair : public BaseArrayPair
{
T* Input;
T* Output;
T NullValue;
ArrayPair(T* in, T* out, vtkIdType num, int numComp, vtkDataArray* outArray, T null)
: BaseArrayPair(num, numComp, outArray)
, Input(in)
, Output(out)
, NullValue(null)
{
}
~ArrayPair() override // calm down some finicky compilers
{
}
void Copy(vtkIdType inId, vtkIdType outId) override
{
for (int j = 0; j < this->NumComp; ++j)
{
this->Output[outId * this->NumComp + j] = this->Input[inId * this->NumComp + j];
}
}
void Interpolate(
int numWeights, const vtkIdType* ids, const double* weights, vtkIdType outId) override
{
for (int j = 0; j < this->NumComp; ++j)
{
double v = 0.0;
for (vtkIdType i = 0; i < numWeights; ++i)
{
v += weights[i] * static_cast<double>(this->Input[ids[i] * this->NumComp + j]);
}
this->Output[outId * this->NumComp + j] = static_cast<T>(v);
}
}
void InterpolateEdge(vtkIdType v0, vtkIdType v1, double t, vtkIdType outId) override
{
double v;
vtkIdType numComp = this->NumComp;
for (int j = 0; j < numComp; ++j)
{
v = this->Input[v0 * numComp + j] +
t * (this->Input[v1 * numComp + j] - this->Input[v0 * numComp + j]);
this->Output[outId * numComp + j] = static_cast<T>(v);
}
}
void AssignNullValue(vtkIdType outId) override
{
for (int j = 0; j < this->NumComp; ++j)
{
this->Output[outId * this->NumComp + j] = this->NullValue;
}
}
void Realloc(vtkIdType sze) override
{
this->OutputArray->WriteVoidPointer(0, sze * this->NumComp);
this->Output = static_cast<T*>(this->OutputArray->GetVoidPointer(0));
}
};
// Type specific interpolation on a pair of data arrays with different types, where the
// output type is expected to be a real type (i.e., float or double).
template <typename TInput, typename TOutput>
struct RealArrayPair : public BaseArrayPair
{
TInput* Input;
TOutput* Output;
TOutput NullValue;
RealArrayPair(
TInput* in, TOutput* out, vtkIdType num, int numComp, vtkDataArray* outArray, TOutput null)
: BaseArrayPair(num, numComp, outArray)
, Input(in)
, Output(out)
, NullValue(null)
{
}
~RealArrayPair() override // calm down some finicky compilers
{
}
void Copy(vtkIdType inId, vtkIdType outId) override
{
for (int j = 0; j < this->NumComp; ++j)
{
this->Output[outId * this->NumComp + j] =
static_cast<TOutput>(this->Input[inId * this->NumComp + j]);
}
}
void Interpolate(
int numWeights, const vtkIdType* ids, const double* weights, vtkIdType outId) override
{
for (int j = 0; j < this->NumComp; ++j)
{
double v = 0.0;
for (vtkIdType i = 0; i < numWeights; ++i)
{
v += weights[i] * static_cast<double>(this->Input[ids[i] * this->NumComp + j]);
}
this->Output[outId * this->NumComp + j] = static_cast<TOutput>(v);
}
}
void InterpolateEdge(vtkIdType v0, vtkIdType v1, double t, vtkIdType outId) override
{
double v;
vtkIdType numComp = this->NumComp;
for (int j = 0; j < numComp; ++j)
{
v = this->Input[v0 * numComp + j] +
t * (this->Input[v1 * numComp + j] - this->Input[v0 * numComp + j]);
this->Output[outId * numComp + j] = static_cast<TOutput>(v);
}
}
void AssignNullValue(vtkIdType outId) override
{
for (int j = 0; j < this->NumComp; ++j)
{
this->Output[outId * this->NumComp + j] = this->NullValue;
}
}
void Realloc(vtkIdType sze) override
{
this->OutputArray->WriteVoidPointer(0, sze * this->NumComp);
this->Output = static_cast<TOutput*>(this->OutputArray->GetVoidPointer(0));
}
};
// Forward declarations. This makes working with vtkTemplateMacro easier.
struct ArrayList;
template <typename T>
void CreateArrayPair(
ArrayList* list, T* inData, T* outData, vtkIdType numTuples, int numComp, T nullValue);
// A list of the arrays to interpolate, and a method to invoke interpolation on the list
struct ArrayList
{
// The list of arrays, and the arrays not to process
std::vector<BaseArrayPair*> Arrays;
std::vector<vtkDataArray*> ExcludedArrays;
// Add the arrays to interpolate here (from attribute data)
void AddArrays(vtkIdType numOutPts, vtkDataSetAttributes* inPD, vtkDataSetAttributes* outPD,
double nullValue = 0.0, vtkTypeBool promote = true);
// Add an array that interpolates from its own attribute values
void AddSelfInterpolatingArrays(
vtkIdType numOutPts, vtkDataSetAttributes* attr, double nullValue = 0.0);
// Add a pair of arrays (manual insertion). Returns the output array created,
// if any. No array may be created if \c inArray was previously marked as
// excluded using ExcludeArray().
vtkDataArray* AddArrayPair(vtkIdType numTuples, vtkDataArray* inArray, vtkStdString& outArrayName,
double nullValue, vtkTypeBool promote);
// Any array excluded here is not added by AddArrays() or AddArrayPair, hence not
// processed. Also check whether an array is excluded.
void ExcludeArray(vtkDataArray* da);
vtkTypeBool IsExcluded(vtkDataArray* da);
// Loop over the array pairs and copy data from one to another
void Copy(vtkIdType inId, vtkIdType outId)
{
for (std::vector<BaseArrayPair*>::iterator it = Arrays.begin(); it != Arrays.end(); ++it)
{
(*it)->Copy(inId, outId);
}
}
// Loop over the arrays and have them interpolate themselves
void Interpolate(int numWeights, const vtkIdType* ids, const double* weights, vtkIdType outId)
{
for (std::vector<BaseArrayPair*>::iterator it = Arrays.begin(); it != Arrays.end(); ++it)
{
(*it)->Interpolate(numWeights, ids, weights, outId);
}
}
// Loop over the arrays perform edge interpolation
void InterpolateEdge(vtkIdType v0, vtkIdType v1, double t, vtkIdType outId)
{
for (std::vector<BaseArrayPair*>::iterator it = Arrays.begin(); it != Arrays.end(); ++it)
{
(*it)->InterpolateEdge(v0, v1, t, outId);
}
}
// Loop over the arrays and assign the null value
void AssignNullValue(vtkIdType outId)
{
for (std::vector<BaseArrayPair*>::iterator it = Arrays.begin(); it != Arrays.end(); ++it)
{
(*it)->AssignNullValue(outId);
}
}
// Extend (realloc) the arrays
void Realloc(vtkIdType sze)
{
for (std::vector<BaseArrayPair*>::iterator it = Arrays.begin(); it != Arrays.end(); ++it)
{
(*it)->Realloc(sze);
}
}
// Only you can prevent memory leaks!
~ArrayList()
{
for (std::vector<BaseArrayPair*>::iterator it = Arrays.begin(); it != Arrays.end(); ++it)
{
delete (*it);
}
}
// Return the number of arrays
vtkIdType GetNumberOfArrays() { return static_cast<vtkIdType>(Arrays.size()); }
};
#include "vtkArrayListTemplate.txx"
#endif
// VTK-HeaderTest-Exclude: vtkArrayListTemplate.h