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.
313 lines
9.4 KiB
C
313 lines
9.4 KiB
C
|
3 weeks ago
|
/*=========================================================================
|
||
|
|
|
||
|
|
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 efficently 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 <vector>
|
||
|
|
#include <algorithm>
|
||
|
|
|
||
|
|
// 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() VTK_OVERRIDE //calm down some finicky compilers
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void Copy(vtkIdType inId, vtkIdType outId) VTK_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) VTK_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) VTK_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) VTK_OVERRIDE
|
||
|
|
{
|
||
|
|
for (int j=0; j < this->NumComp; ++j)
|
||
|
|
{
|
||
|
|
this->Output[outId*this->NumComp+j] = this->NullValue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Realloc(vtkIdType sze) VTK_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() VTK_OVERRIDE //calm down some finicky compilers
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void Copy(vtkIdType inId, vtkIdType outId) VTK_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) VTK_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) VTK_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) VTK_OVERRIDE
|
||
|
|
{
|
||
|
|
for (int j=0; j < this->NumComp; ++j)
|
||
|
|
{
|
||
|
|
this->Output[outId*this->NumComp+j] = this->NullValue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Realloc(vtkIdType sze) VTK_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,
|
||
|
|
bool promote=true);
|
||
|
|
|
||
|
|
// 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, bool 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);
|
||
|
|
bool 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 Arrays.size();
|
||
|
|
}
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
#include "vtkArrayListTemplate.txx"
|
||
|
|
|
||
|
|
#endif
|
||
|
|
// VTK-HeaderTest-Exclude: vtkArrayListTemplate.h
|