An update will be applied December 9th, between 12PM and 1:00PM EST (UTC -5:00). The site may be slow during that time.

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
......@@ -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