Commit b6bf3c31 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit Committed by David C. Lonie
Browse files

Implementing most of vtkDataArray API for vtkAgnosticArray.

parent 97377770
Pipeline #8800 passed with stage
......@@ -240,8 +240,9 @@ SET(Module_SRCS
set(${vtk-module}_HDRS
vtkABI.h
vtkAgnosticArray.h
vtkAgnosticArray.txx
vtkAgnosticArrayLookupHelper.h
vtkAgnosticArrayTupleIterator.h
vtkAgnosticArray.txx
vtkAngularPeriodicDataArray.h
vtkArrayInterpolate.h
vtkArrayInterpolate.txx
......
......@@ -18,30 +18,32 @@
#ifndef vtkAgnosticArray_h
#define vtkAgnosticArray_h
#include "vtkAgnosticArrayHelpers.h"
#include "vtkAgnosticArrayTupleIterator.h"
#include "vtkDataArray.h"
#include "vtkSmartPointer.h"
#include "vtkTypeTemplate.h"
#include "vtkTypeTraits.h"
#include "vtkAgnosticArrayLookupHelper.h"
#include "vtkAgnosticArrayHelpers.h"
#include "vtkAgnosticArrayTupleIterator.h"
#include <cassert>
template<class DerivedT,
class ScalarTypeT,
class TupleTypeT,
class TupleIteratorT=vtkAgnosticArrayTupleIterator<DerivedT>,
class TupleIteratorTypeT=vtkAgnosticArrayTupleIterator<DerivedT>,
class ScalarReturnTypeT=ScalarTypeT&>
class vtkAgnosticArray : public vtkTypeTemplate<
vtkAgnosticArray<DerivedT, ScalarTypeT, TupleTypeT, TupleIteratorT, ScalarReturnTypeT>,
vtkAgnosticArray<DerivedT, ScalarTypeT, TupleTypeT, TupleIteratorTypeT, ScalarReturnTypeT>,
vtkDataArray>
{
typedef
vtkAgnosticArray<DerivedT, ScalarTypeT, TupleTypeT, TupleIteratorT, ScalarReturnTypeT> SelfType;
vtkAgnosticArray<DerivedT, ScalarTypeT, TupleTypeT, TupleIteratorTypeT, ScalarReturnTypeT> SelfType;
public:
typedef ScalarTypeT ScalarType;
typedef TupleTypeT TupleType;
typedef TupleIteratorT TupleIteratorType;
typedef ScalarReturnTypeT ScalarReturnType;
typedef ScalarTypeT ScalarType;
typedef ScalarReturnTypeT ScalarReturnType;
typedef TupleTypeT TupleType;
typedef TupleIteratorTypeT TupleIteratorType;
inline TupleIteratorType Begin(vtkIdType pos=0) const
{ return TupleIteratorType(*static_cast<const DerivedT*>(this), pos); }
......@@ -62,19 +64,25 @@ public:
}
//----------------------------------------------------------------------------
// Currently unhandled methods.
virtual void *GetVoidPointer(vtkIdType id) { return NULL; }
virtual void SetVoidArray(void*, vtkIdType, int) {}
virtual vtkArrayIterator* NewIterator() { return NULL; }
virtual vtkIdType LookupValue(vtkVariant value) { return -1; }
virtual void LookupValue(vtkVariant value, vtkIdList* ids) {}
virtual void SetVariantValue(vtkIdType idx, vtkVariant value) {}
virtual void DataChanged() {}
virtual void ClearLookup() {}
virtual double *GetTuple(vtkIdType i);
virtual void GetTuple(vtkIdType i, double * tuple);
virtual void RemoveTuple(vtkIdType id);
virtual void* WriteVoidPointer(vtkIdType id, vtkIdType number) {return NULL;}
// Pointer access methods.
// These are considered legacy and are not implemented. New arrays types keep
// on supporting filters that use this API should override these methods to
// provide appropriate implementations.
// Description:
// Default implementation raises a runtime error. If subclasses are keep on
// supporting this API, they should override this method.
virtual void *GetVoidPointer(vtkIdType id);
// Description:
// Implementation provided simply raises a runtime error. If subclasses are
// keep on supporting this API, they should override the method.
virtual void SetVoidArray(void*, vtkIdType, int);
// Description:
// Implementation provided simply raises a runtime error. If subclasses are
// keep on supporting this API, they should override the method.
virtual void* WriteVoidPointer(vtkIdType id, vtkIdType number);
//----------------------------------------------------------------------------
// Methods relating to memory allocated for this array.
......@@ -167,6 +175,8 @@ public:
}
virtual void SetNumberOfTuples(vtkIdType number)
{
// XXX: We should change this to not release memory when shrinking, should
// we?
this->Resize(number);
}
virtual void Initialize()
......@@ -215,38 +225,65 @@ public:
virtual void InsertTuples(vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, vtkAbstractArray* source);
//----------------------------------------------------------------------------
// Set* methods.
virtual void SetTuple(vtkIdType i, vtkIdType j, vtkAbstractArray *source)
{
vtkAgnosticArrayHelpers::SetTuple(this, i, source, j);
this->DataChanged();
}
virtual void SetTuple(vtkIdType i, const float *source)
// SetTuple methods.
virtual void SetTuple(vtkIdType i, vtkIdType j, vtkAbstractArray *source);
virtual void SetTuple(vtkIdType i, const float *source);
virtual void SetTuple(vtkIdType i, const double *source);
//----------------------------------------------------------------------------
// GetTuple methods.
virtual double *GetTuple(vtkIdType i);
virtual void GetTuple(vtkIdType i, double * tuple);
//----------------------------------------------------------------------------
// Description:
// Removes a tuple at the given index. Default implementation uses
// TupleIteratorType to iterate over tuples to move elements. Subclasses are
// encouraged to reimplemented this method to support faster implementations,
// if needed.
virtual void RemoveTuple(vtkIdType id);
//----------------------------------------------------------------------------
// Set Value methods. Note the index for all these methods is a "value" index
// or component index assuming traditional VTK style memory layout for tuples
// and components.
virtual void SetVariantValue(vtkIdType idx, vtkVariant value);
//----------------------------------------------------------------------------
// All the lookup related methods We provide a default implementation that works
// using the iterator. Since these methods are virtual, a subclass can override
// these to provide faster alternatives.
virtual vtkIdType LookupValue(vtkVariant value);
virtual vtkIdType LookupTypedValue(ScalarType value);
virtual void LookupValue(vtkVariant value, vtkIdList* ids);
virtual void LookupTypedValue(ScalarType value, vtkIdList* ids);
virtual void ClearLookup()
{
for (int cc=0, max=this->GetNumberOfComponents(); cc < max; ++cc)
{
this->Begin(i)[cc] = static_cast<ScalarType>(source[cc]);
}
this->DataChanged();
this->Lookup.ClearLookup();
}
virtual void SetTuple(vtkIdType i, const double *source)
virtual void DataChanged()
{
for (int cc=0, max=this->GetNumberOfComponents(); cc < max; ++cc)
{
this->Begin(i)[cc] = static_cast<ScalarType>(source[cc]);
}
this->DataChanged();
this->Lookup.ClearLookup();
}
//----------------------------------------------------------------------------
// All the lookup related methods that we'll implement eventually. We should
// provide a default implementation that works using the iterator. Since these
// methods are virtual, a subclass can override these to provide faster
// alternatives.
// vtkArrayIterator API. This provides the generic vtkArrayIterator. Code
// using vtkDataArray should stick to using the TupleIteratorType based
// API when iterating over tuples as that is typically faster.
// TODO:
virtual vtkArrayIterator* NewIterator() { return NULL;}
protected:
vtkAgnosticArray() { }
virtual ~vtkAgnosticArray() { }
vtkAgnosticArray()
: Lookup(*this)
{
}
virtual ~vtkAgnosticArray()
{
}
// This method resizes the array if needed so that the given tuple index is
// valid/accessible.
......@@ -260,6 +297,8 @@ protected:
}
return true;
}
vtkAgnosticArrayLookupHelper<SelfType> Lookup;
private:
vtkAgnosticArray(const vtkAgnosticArray&); // Not implemented.
void operator=(const vtkAgnosticArray&); // Not implemented.
......
......@@ -16,6 +16,7 @@
#include "vtkObjectFactory.h"
#include "vtkIdList.h"
#include "vtkAgnosticArrayHelpers.h"
#include "vtkVariantCast.h"
#define vtkAgnosticArrayT(returnType) \
template <class D, class S, class T, class TI, class SR> \
......@@ -25,12 +26,17 @@
vtkAgnosticArrayT(void)::InsertTuples(
vtkIdList *dstIds, vtkIdList *srcIds, vtkAbstractArray *source)
{
// XXX Should these be implemented in vtkDataArray?
if (this->GetDataType() != source->GetDataType())
{
vtkErrorMacro("Input and output array data types do not match.");
return;
}
if (vtkDataArray::SafeDownCast(source) == NULL)
{
vtkErrorMacro("Input array is not a vtkDataArray subclass!");
return;
}
if (this->NumberOfComponents != source->GetNumberOfComponents())
{
vtkErrorMacro("Input and output component sizes do not match.");
......@@ -56,49 +62,64 @@ vtkAgnosticArrayT(void)::InsertTuples(
return;
}
//// Copy directly into our array if the source has supporting API:
//if (vtkTypedDataArray<T> *typedSource =
// vtkTypedDataArray<T>::FastDownCast(source))
// {
// for (vtkIdType idIndex = 0; idIndex < numIds; ++idIndex)
// {
// typedSource->GetTupleValue(srcIds->GetId(idIndex),
// this->GetPointer(dstIds->GetId(idIndex)
// * this->NumberOfComponents));
// }
// }
//else if (vtkDataArray *dataSource = vtkDataArray::FastDownCast(source))
// {
// // Otherwise use the double interface
// for (vtkIdType idIndex = 0; idIndex < numIds; ++idIndex)
// {
// this->SetTuple(dstIds->GetId(idIndex),
// dataSource->GetTuple(srcIds->GetId(idIndex)));
// }
// }
//else
// {
// vtkWarningMacro("Input array is not a vtkDataArray subclass!");
// return;
// }
//vtkIdType maxId = maxSize - 1;
//if (maxId > this->MaxId)
// {
// this->MaxId = maxId;
// }
//this->DataChanged();
for (vtkIdType cc=0; cc < numIds; ++cc)
{
vtkAgnosticArrayHelpers::SetTuple(this, dstIds->GetId(cc), source, srcIds->GetId(cc));
}
this->DataChanged();
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::InsertTuples(vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, vtkAbstractArray* source)
vtkAgnosticArrayT(void)::InsertTuples(vtkIdType dstStart, vtkIdType n,
vtkIdType srcStart, vtkAbstractArray* source)
{
// XXX Should these be implemented in vtkDataArray?
if (n < 0)
{
vtkErrorMacro("Number of tuples to insert cannot be negative!");
return;
}
if (this->GetDataType() != source->GetDataType())
{
vtkErrorMacro("Input and output array data types do not match.");
return;
}
if (vtkDataArray::SafeDownCast(source) == NULL)
{
vtkErrorMacro("Input array is not a vtkDataArray subclass!");
return;
}
if (this->NumberOfComponents != source->GetNumberOfComponents())
{
vtkErrorMacro("Input and output component sizes do not match.");
return;
}
if (source->GetNumberOfTuples() < (srcStart + n))
{
vtkErrorMacro("Input does not have enough data to copy from. "
<< "Expected at least " << (srcStart+n) << " tuples, got "
<< source->GetNumberOfTuples() << " tuples.");
return;
}
// Find maximum destination id and resize if needed
if (!this->EnsureAccessToTuple(dstStart+n-1))
{
vtkErrorMacro("Failed to allocate memory.");
return;
}
for (vtkIdType cc=0; cc < n; ++cc)
{
vtkAgnosticArrayHelpers::SetTuple(this, dstStart + cc, source, srcStart + cc);
}
this->DataChanged();
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(double *)::GetTuple(vtkIdType i)
{
// XXX Should these be implemented in vtkDataArray?
this->LegacyTuple.resize(this->GetNumberOfComponents());
vtkAgnosticArrayHelpers::GetTuple(this, i, &this->LegacyTuple[0]);
return &this->LegacyTuple[0];
......@@ -107,11 +128,143 @@ vtkAgnosticArrayT(double *)::GetTuple(vtkIdType i)
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::GetTuple(vtkIdType i, double * tuple)
{
// XXX Should these be implemented in vtkDataArray?
vtkAgnosticArrayHelpers::GetTuple(this, i, tuple);
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::SetTuple(vtkIdType i, vtkIdType j, vtkAbstractArray *source)
{
// XXX Should these be implemented in vtkDataArray?
vtkAgnosticArrayHelpers::SetTuple(this, i, source, j);
this->DataChanged();
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::SetTuple(vtkIdType i, const float *source)
{
// XXX Should these be implemented in vtkDataArray?
for (int cc=0, max=this->GetNumberOfComponents(); cc < max; ++cc)
{
this->Begin(i)[cc] = static_cast<ScalarType>(source[cc]);
}
this->DataChanged();
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::SetTuple(vtkIdType i, const double *source)
{
// XXX Should these be implemented in vtkDataArray?
for (int cc=0, max=this->GetNumberOfComponents(); cc < max; ++cc)
{
this->Begin(i)[cc] = static_cast<ScalarType>(source[cc]);
}
this->DataChanged();
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::RemoveTuple(vtkIdType id)
{
// XXX: abort!
if (id < 0 || id >= this->GetNumberOfTuples())
{
// Nothing to be done
return;
}
if (id == (this->GetNumberOfTuples() - 1))
{
// To remove last item, just decrease the size by one
this->RemoveLastTuple();
return;
}
// This is a very slow implementation since it uses generic API. Subclasses
// are encouraged to provide a faster implementation.
const vtkIdType len = (this->GetNumberOfTuples() - id) - 1;
assert(len > 0);
int numComps = this->GetNumberOfComponents();
TupleIteratorType from = this->Begin(id+1);
TupleIteratorType to = this->Begin(id);
TupleIteratorType end = this->End();
for (; from != end; ++to, ++from)
{
for (int cc=0; cc < numComps; ++cc)
{
to[cc] = from[cc];
}
}
this->SetNumberOfTuples(this->GetNumberOfTuples() - 1);
this->DataChanged();
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::SetVoidArray(void*, vtkIdType, int)
{
vtkErrorMacro("SetVoidArray is not supported by this class.");
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void*)::WriteVoidPointer(vtkIdType id, vtkIdType number)
{
vtkErrorMacro("WriteVoidPointer is not supported by this class.");
return NULL;
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void*)::GetVoidPointer(vtkIdType)
{
vtkErrorMacro("GetVoidPointer is not supported by this class.");
return NULL;
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(vtkIdType)::LookupValue(vtkVariant valueVariant)
{
bool valid = true;
ScalarType value = vtkVariantCast<ScalarType>(valueVariant, &valid);
if (valid)
{
return this->LookupTypedValue(value);
}
return -1;
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(vtkIdType)::LookupTypedValue(ScalarType value)
{
return this->Lookup.LookupValue(value);
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::LookupValue(vtkVariant valueVariant, vtkIdList* ids)
{
ids->Reset();
bool valid = true;
ScalarType value = vtkVariantCast<ScalarType>(valueVariant, &valid);
if (valid)
{
this->LookupTypedValue(value, ids);
}
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::LookupTypedValue(ScalarType value, vtkIdList* ids)
{
ids->Reset();
this->Lookup.LookupValue(value, ids);
}
//-----------------------------------------------------------------------------
vtkAgnosticArrayT(void)::SetVariantValue(vtkIdType idx, vtkVariant valueVariant)
{
bool valid = true;
ScalarType value = vtkVariantCast<ScalarType>(valueVariant, &valid);
if (valid)
{
vtkIdType tupleIndex = static_cast<vtkIdType>(idx / this->NumberOfComponents);
int comp = static_cast<int>(idx % this->NumberOfComponents);
this->Begin(tupleIndex)[comp] = value;
}
}
#undef vtkAgnosticArrayT
/*=========================================================================
Program: Visualization Toolkit
Module: vtkAgnosticArrayLookupHelper.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.
=========================================================================*/
// .NAME vtkAgnosticArrayLookupHelper - internal class used by
// vtkAgnosticArray to support LookupValue.
// .SECTION Description
#ifndef vtkAgnosticArrayLookupHelper_h
#define vtkAgnosticArrayLookupHelper_h
#include <algorithm>
#include "vtkIdList.h"
namespace detail
{
// this can be removed when C++11 is required.
template< class T > struct remove_const { typedef T type; };
template< class T > struct remove_const<const T> { typedef T type; };
}
template <class ArrayTypeT>
class vtkAgnosticArrayLookupHelper
{
public:
typedef ArrayTypeT ArrayType;
typedef typename ArrayType::ScalarType ScalarType;
typedef typename ArrayType::TupleIteratorType TupleIteratorType;
// Constructor.
vtkAgnosticArrayLookupHelper(ArrayType& associatedArray)
: AssociatedArray(associatedArray),
SortedArray(NULL)
{
}
~vtkAgnosticArrayLookupHelper()
{
this->ClearLookup();
}
vtkIdType LookupValue(ScalarType elem)
{
this->UpdateLookup();
ValueWithIndex temp;
temp.Value = elem;
ValueWithIndex* pos =
std::lower_bound(this->SortedArray, this->SortedArray + this->SortedArraySize, temp);
if (pos == (this->SortedArray + this->SortedArraySize))
{
return -1;
}
if (pos->Value != elem)
{
return -1;
}
return pos->Index;
}
void LookupValue(ScalarType elem, vtkIdList* ids)
{
this->UpdateLookup();
ValueWithIndex temp;
temp.Value = elem;
std::pair<ValueWithIndex*, ValueWithIndex*> range =
std::equal_range(this->SortedArray, this->SortedArray + this->SortedArraySize, temp);
while (range.first != range.second)
{
// assert(range.first->Value == elem);
ids->InsertNextId(range.first->Index);
++range.first;
}
}
// Description:
// Release any allocated memory for internal data-structures.
void ClearLookup()
{
free(this->SortedArray);
this->SortedArray = NULL;
this->SortedArraySize = 0;
}
private:
vtkAgnosticArrayLookupHelper(const vtkAgnosticArrayLookupHelper&); // Not implemented.
void operator=(const vtkAgnosticArrayLookupHelper&); // Not implemented.
struct ValueWithIndex
{
typename detail::remove_const<ScalarType>::type Value;
vtkIdType Index;
inline bool operator<(const ValueWithIndex& other) const
{
return this->Value < other.Value;
}
};
void UpdateLookup()
{
if (this->SortedArray) { return; }
int numComps = this->AssociatedArray.GetNumberOfComponents();
this->SortedArraySize = this->AssociatedArray.GetNumberOfTuples() * numComps;
if (this->SortedArraySize == 0) { return; }
this->SortedArray = reinterpret_cast<ValueWithIndex*>(malloc(this->SortedArraySize * sizeof(ValueWithIndex)));
for (TupleIteratorType iter = this->AssociatedArray.Begin(); iter != this->AssociatedArray.End(); ++iter)
{
for (int cc=0; cc < numComps; ++cc)
{
ValueWithIndex& item = this->SortedArray[iter.GetIndex()*numComps+cc];
item.Value = iter[cc];
item.Index = iter.GetIndex();
// not preserving component index for now.
}
}
std::sort(this->SortedArray, this->SortedArray + this->SortedArraySize);
}
ArrayTypeT& AssociatedArray;
ValueWithIndex* SortedArray;
vtkIdType SortedArraySize;
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment