Commit fad86463 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit

ENH:

* vtkDataArray now has a new superclass-vtkAbstractArray.vtkAbstractArray
provides type-agnostic API to access array elements. vtkDataArray provides
a double API to access values -- such an API is deliberately missing from
vtkAbstractArray, since arrays like string arrays are not castable to doubles.

* vtkAbstractArray has the notion of components/tuples, but does not make
any assumptions about the arragment of these. It's up to the concrete
subclasses how the data is represented in memory.

* vtkFieldData used to provide tuple API to get/set values from data arrays
contained in it. However, now that FieldData can have arrays that are not
vtkDataArrays, this API is not longer valid.
The following are the methods that are no longer available:
double* GetTuple(const vtkIdType);
void SetTuple(const vtkIdType i, const double* tuple);
void GetTuple(const vtkIdType i, double* tuple);
void InsertTuple(const vtkIdType i, const double* tuple);
void InsertNextTuple(cons double*);
double GetComponent(const vtkIdType i, const int j);
void SetComponent(const vtkIdType i, const int j, const double c);
void InsertComponent(const vtkIdType i, const int j, const double c);
However, new API is provided to copy tuples arround from one field data to
another using:
void SetTuple(const vtkIdType i, const vtkIdType j, vtkFieldData* source);
void InsertTuple(const vtkIdType i, const vtkIdType j, vtkFieldData* source);
vtkIdType InsertNextTuple(const vtkIdType j, vtkFieldData* source);

* vtkFieldData provide a vtkDataArray* GetArray(int index) to retrieve arrays
in the field data. This function can will now return a NULL if the array
at the given index is not a data array. It provides
vtkAbstractArray* GetAbstractArray(int index);
to retrieve an array even if it isn't a vtkDataArray.

* Since vtkFieldData can contain arrays that aren't subclasses of
vtkDataArray, so can vtkDataSetAttributes. However, an attribute can only be
a vtkDataArray subclass i.e. one cannot set a vtkStringArray as the SCALARS
array for a Point Data, for example.

* String Array IO is only supported in XML file formats. If deemed important,
support may be added for lecacy file formats.

*** Array Iterators ***
Another addition to the VTK Arrays, is the notion of Array Iterator. A
vtkArrayIterator subclass is be provided for every vtkAbstractArray
subclass. The iterator is a random access iterator. The iterators are not
available in any of the wrapped languages, however, in C++ they can be used to
write templatized code to processes the array values without any implicit type
conversion and consequent loss of precision. vtkArrayIteratorTemplateMacro is
provided to simply switching between different types of the arrays. Examples of
use of this macro and the iterators can be found in
vtkXMLWriter.cxx / vtkXMLDataReader.cxx / vtkXMLStructuredDataReader.cxx.
parent d75ee0a4
......@@ -25,10 +25,12 @@ vtkAbstractTransform.cxx
vtkAmoebaMinimizer.cxx
vtkAnimationCue.cxx
vtkAnimationScene.cxx
vtkArrayIterator.cxx
vtkAssemblyNode.cxx
vtkAssemblyPath.cxx
vtkAssemblyPaths.cxx
vtkBitArray.cxx
vtkBitArrayIterator.cxx
vtkBox.cxx
vtkByteSwap.cxx
vtkCallbackCommand.cxx
......@@ -213,6 +215,8 @@ ENDFOREACH(t)
SET_SOURCE_FILES_PROPERTIES(
# vtkObjectBase is marked ABSTRACT so that instantiators are happy.
vtkAbstractArray
vtkArrayIterator
vtkArrayIteratorTemplate
vtkAbstractTransform
vtkCallbackCommand
vtkCommand
......@@ -238,6 +242,7 @@ ABSTRACT
)
SET_SOURCE_FILES_PROPERTIES(
vtkArrayIteratorTemplate.txx
vtkCallbackCommand.cxx
vtkCommand.cxx
vtkDebugLeaksManager.cxx
......@@ -283,6 +288,7 @@ INCLUDE(${VTK_CMAKE_DIR}/KitCommonBlock.cmake)
IF(NOT VTK_INSTALL_NO_DEVELOPMENT)
INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h
vtkArrayIteratorTemplate
vtkDataArrayTemplate
vtkIOStream
vtkIOStreamFwd
......@@ -325,6 +331,8 @@ IF(NOT VTK_INSTALL_NO_DEVELOPMENT)
ENDIF(VTK_WRAP_JAVA)
INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .txx
vtkArrayIteratorTemplate
vtkArrayIteratorTemplateImplicit
vtkDataArrayTemplate
vtkDataArrayTemplateImplicit
)
......
......@@ -16,6 +16,7 @@ IF(PYTHON_EXECUTABLE)
vtkAbstractIterator.h
vtkAbstractList.h
vtkAbstractMap.h
vtkArrayIteratorIncludes.h
vtkArrayMap.h
vtkArrayMapIterator.h
vtkAssemblyPaths.h
......
......@@ -65,11 +65,12 @@ int otherFieldData(int,char *[])
int arrayComp;
int a = fd->GetArrayContainingComponent(1, arrayComp);
if (a != 0)
if (a != 1)
{
return 1;
}
/* Obsolete API.
double tuple[10];
// initialize tuple before using it to set something
for (i = 0; i < 10; i++)
......@@ -82,7 +83,7 @@ int otherFieldData(int,char *[])
fd->InsertNextTuple(tuple);
fd->SetComponent(0,0, 1.0);
fd->InsertComponent(0,0, 1.0);
*/
fd2->Reset();
fd->Delete();
......
......@@ -118,7 +118,7 @@ int doStringArrayTest(ostream& strm, int size)
strm << "FAILED" << endl;
}
strm << "\tvtkAbstractArray::GetValues(vtkIdList)...";
strm << "\tvtkAbstractArray::GetTuples(vtkIdList)...";
vtkIdList *indices = vtkIdList::New();
indices->InsertNextId(10);
indices->InsertNextId(20);
......@@ -126,7 +126,7 @@ int doStringArrayTest(ostream& strm, int size)
vtkStringArray *newValues = vtkStringArray::New();
newValues->SetNumberOfValues(3);
ptr->GetValues(indices, newValues);
ptr->GetTuples(indices, newValues);
if (newValues->GetValue(0) == "string entry 10" &&
newValues->GetValue(1) == "string entry 20" &&
......@@ -148,9 +148,9 @@ int doStringArrayTest(ostream& strm, int size)
newValues->Reset();
strm << "\tvtkAbstractArray::GetValues(vtkIdType, vtkIdType)...";
strm << "\tvtkAbstractArray::GetTuples(vtkIdType, vtkIdType)...";
newValues->SetNumberOfValues(3);
ptr->GetValues(30, 32, newValues);
ptr->GetTuples(30, 32, newValues);
if (newValues->GetValue(0) == "string entry 30" &&
newValues->GetValue(1) == "string entry 31" &&
newValues->GetValue(2) == "string entry 32")
......@@ -163,8 +163,8 @@ int doStringArrayTest(ostream& strm, int size)
strm << "FAILED" << endl;
}
strm << "\tvtkAbstractArray::CopyValue...";
ptr->CopyValue(150, 2, newValues);
strm << "\tvtkAbstractArray::InsertTuple...";
ptr->InsertTuple(150, 2, newValues);
if (ptr->GetValue(150) == "string entry 32")
{
strm << "OK" << endl;
......@@ -183,66 +183,6 @@ int doStringArrayTest(ostream& strm, int size)
ptr->Delete();
delete [] strings;
strm << "\tvtkAbstractArray::ConvertToContiguous...";
vtkStringArray *srcArray = vtkStringArray::New();
vtkStringArray *destArray = vtkStringArray::New();
srcArray->InsertNextValue("First");
srcArray->InsertNextValue("Second");
srcArray->InsertNextValue("Third");
vtkDataArray *data;
vtkIdTypeArray *offsets;
srcArray->ConvertToContiguous(&data, &offsets);
char combinedString[] = "FirstSecondThird";
vtkCharArray *charData = vtkCharArray::SafeDownCast(data);
if (charData == NULL)
{
++errors;
strm << "FAILED: couldn't downcast data array" << endl;
}
else
{
for (int i = 0; i < static_cast<int>(strlen(combinedString)); ++i)
{
if (charData->GetValue(i) != combinedString[i])
{
strm << "FAILED: array element " << i << " is wrong. Expected "
<< combinedString[i] << ", got "
<< charData->GetValue(i) << endl;
++errors;
}
}
destArray->ConvertFromContiguous(data, offsets);
if (destArray->GetNumberOfValues() != srcArray->GetNumberOfValues())
{
++errors;
strm << "FAILED: reconstructed lengths don't match" << endl;
}
else
{
for (int i = 0; i < srcArray->GetNumberOfValues(); ++i)
{
if (destArray->GetValue(i) != srcArray->GetValue(i))
{
strm << "FAILED: element " << i << " doesn't match" << endl;
++errors;
}
}
}
}
srcArray->Delete();
destArray->Delete();
data->Delete();
offsets->Delete();
return errors;
}
......
......@@ -13,135 +13,105 @@
=========================================================================*/
#include "vtkAbstractArray.h"
#include "vtkIdList.h"
#include "vtkMath.h"
#include "vtkDataArray.h"
#include "vtkBitArray.h"
#include "vtkCharArray.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkIdList.h"
#include "vtkIntArray.h"
#include "vtkIdTypeArray.h"
#include "vtkLongArray.h"
#include "vtkShortArray.h"
#include "vtkSignedCharArray.h"
#include "vtkStringArray.h"
#include "vtkUnsignedCharArray.h"
#include "vtkUnsignedIntArray.h"
#include "vtkUnsignedLongArray.h"
#include "vtkUnsignedShortArray.h"
vtkCxxRevisionMacro(vtkAbstractArray, "1.5");
#if defined(VTK_TYPE_USE_LONG_LONG)
# include "vtkLongLongArray.h"
# include "vtkUnsignedLongLongArray.h"
#endif
#if defined(VTK_TYPE_USE___INT64)
# include "vtk__Int64Array.h"
# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE)
# include "vtkUnsigned__Int64Array.h"
# endif
#endif
vtkCxxRevisionMacro(vtkAbstractArray, "1.6");
//----------------------------------------------------------------------------
// Construct object with sane defaults.
vtkAbstractArray::vtkAbstractArray(vtkIdType vtkNotUsed(numComp))
{
this->Size = 0;
this->MaxId = -1;
this->NumberOfComponents = 1;
this->Name = NULL;
this->DataType = -1;
}
//----------------------------------------------------------------------------
vtkAbstractArray::~vtkAbstractArray()
{
if (this->Name != NULL)
{
delete [] this->Name;
}
this->Name = NULL;
this->SetName(NULL);
}
void vtkAbstractArray::SetName(const char* name)
//----------------------------------------------------------------------------
void vtkAbstractArray::GetTuples(vtkIdList* ptIds, vtkAbstractArray* aa)
{
if (this->Name != NULL)
if (aa->GetNumberOfComponents() != this->GetNumberOfComponents())
{
delete[] this->Name;
vtkWarningMacro("Number of components for input and output do not match.");
return;
}
this->Name = NULL;
if (name)
// Here we give the slowest implementation. Subclasses can override
// to use the knowledge about the data.
vtkIdType num = ptIds->GetNumberOfIds();
for (vtkIdType i = 0; i < num; i++)
{
int size = static_cast<int>(strlen(name));
this->Name = new char[size+1];
strcpy(this->Name, name);
aa->SetTuple(i, ptIds->GetId(i), this);
}
}
const char* vtkAbstractArray::GetName()
//----------------------------------------------------------------------------
void vtkAbstractArray::GetTuples(vtkIdType p1, vtkIdType p2,
vtkAbstractArray* aa)
{
return this->Name;
}
void vtkAbstractArray::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
const char* name = this->GetName();
if (name)
if (aa->GetNumberOfComponents() != this->GetNumberOfComponents())
{
os << indent << "Name: " << name << "\n";
vtkWarningMacro("Number of components for input and output do not match.");
return;
}
else
// Here we give the slowest implementation. Subclasses can override
// to use the knowledge about the data.
vtkIdType num = p2 - p1 + 1;
for (vtkIdType i = 0; i < num; i++)
{
os << indent << "Name: (none)\n";
aa->SetTuple(i, (p1+i), this);
}
os << indent << "Data type: " << this->GetDataTypeAsString();
os << indent << "Size: " << this->Size << "\n";
os << indent << "MaxId: " << this->MaxId << "\n";
}
//----------------------------------------------------------------------------
template <class T>
unsigned long vtkAbstractArrayGetDataTypeSize(T*)
{
return sizeof(T);
}
unsigned long vtkAbstractArray::GetDataTypeSize(int type)
{
switch (type)
{
vtkTemplateMacro(
return vtkAbstractArrayGetDataTypeSize(static_cast<VTK_TT*>(0))
);
case VTK_BIT:
return 1;
break;
case VTK_CHAR:
return sizeof(char);
break;
case VTK_UNSIGNED_CHAR:
return sizeof(unsigned char);
break;
case VTK_SHORT:
return sizeof(short);
break;
case VTK_UNSIGNED_SHORT:
return sizeof(unsigned short);
break;
case VTK_INT:
return sizeof(int);
break;
case VTK_UNSIGNED_INT:
return sizeof(unsigned int);
break;
case VTK_LONG:
return sizeof(long);
break;
case VTK_UNSIGNED_LONG:
return sizeof(unsigned long);
break;
case VTK_FLOAT:
return sizeof(float);
break;
case VTK_DOUBLE:
return sizeof(double);
break;
case VTK_ID_TYPE:
return sizeof(vtkIdType);
return 0;
break;
case VTK_STRING:
......@@ -156,8 +126,6 @@ unsigned long vtkAbstractArray::GetDataTypeSize(int type)
}
// ----------------------------------------------------------------------
#if 0
vtkAbstractArray* vtkAbstractArray::CreateArray(int dataType)
{
switch (dataType)
......@@ -168,6 +136,9 @@ vtkAbstractArray* vtkAbstractArray::CreateArray(int dataType)
case VTK_CHAR:
return vtkCharArray::New();
case VTK_SIGNED_CHAR:
return vtkSignedCharArray::New();
case VTK_UNSIGNED_CHAR:
return vtkUnsignedCharArray::New();
......@@ -189,6 +160,26 @@ vtkAbstractArray* vtkAbstractArray::CreateArray(int dataType)
case VTK_UNSIGNED_LONG:
return vtkUnsignedLongArray::New();
#if defined(VTK_TYPE_USE_LONG_LONG)
case VTK_LONG_LONG:
return vtkLongLongArray::New();
case VTK_UNSIGNED_LONG_LONG:
return vtkUnsignedLongLongArray::New();
#endif
#if defined(VTK_TYPE_USE___INT64)
case VTK___INT64:
return vtk__Int64Array::New();
break;
# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE)
case VTK_UNSIGNED___INT64:
return vtkUnsigned__Int64Array::New();
break;
# endif
#endif
case VTK_FLOAT:
return vtkFloatArray::New();
......@@ -197,10 +188,33 @@ vtkAbstractArray* vtkAbstractArray::CreateArray(int dataType)
case VTK_ID_TYPE:
return vtkIdTypeArray::New();
case VTK_STRING:
return vtkStringArray::New();
default:
vtkGenericWarningMacro(<<"Unsupported data type! Setting to VTK_DOUBLE");
vtkGenericWarningMacro("Unsupported data type " << dataType
<< "! Setting to VTK_DOUBLE");
return vtkDoubleArray::New();
}
}
#endif
//----------------------------------------------------------------------------
void vtkAbstractArray::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
const char* name = this->GetName();
if (name)
{
os << indent << "Name: " << name << "\n";
}
else
{
os << indent << "Name: (none)\n";
}
os << indent << "Data type: " << this->GetDataTypeAsString();
os << indent << "Size: " << this->Size << "\n";
os << indent << "MaxId: " << this->MaxId << "\n";
os << indent << "NumberOfComponents: " << this->NumberOfComponents << endl;
}
......@@ -46,8 +46,7 @@
class vtkIdList;
class vtkIdTypeArray;
class vtkDataArray;
#define VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES 11
class vtkArrayIterator;
class VTK_COMMON_EXPORT vtkAbstractArray : public vtkObject
{
......@@ -67,37 +66,15 @@ public:
// Description:
// Return the underlying data type. An integer indicating data type is
// returned as specified in vtkSetGet.h.
virtual int GetDataType() = 0;
virtual int GetDataType() =0;
// Description:
// Return the size of the underlying data type. For a bit, 0 is
// returned. XXX FIXME How will this method behave for
// variably-sized objects?
// Return the size of the underlying data type. For a bit, 1 is
// returned. For string 0 is returned. Arrays with variable length
// components return 0.
virtual int GetDataTypeSize() = 0;
static unsigned long GetDataTypeSize(int type);
// Description:
// Given a list of indices, return an array of values. The caller
// must ensure that enough room has been allocated within the output
// array to hold the data and that the data types match well enough
// to allow any necessary conversions.
virtual void GetValues(vtkIdList *indices, vtkAbstractArray *output) = 0;
// Description:
// Get the values for the range of indices specified (i.e., p1->p2
// inclusive). You must insure that the output array has been
// previously allocated with enough space to hold the data and that
// the type of the output array is compatible with the type of this
// array.
virtual void GetValues(vtkIdType p1, vtkIdType p2, vtkAbstractArray *output) = 0;
// Description:
// Return the number of components in a single element of the array.
// For vtkDataArray and its subclasses, this is the number of
// components in a tuple. Arrays with variable-length elements
// (such as vtkStringArray and vtkCellArray) should return 0.
virtual int GetNumberOfElementComponents() = 0;
// Description:
// Return the size, in bytes, of the lowest-level element of an
// array. For vtkDataArray and subclasses this is the size of the
......@@ -105,6 +82,52 @@ public:
// sizeof(vtkStdString::value_type), which winds up being
// sizeof(char).
virtual int GetElementComponentSize() = 0;
// Description:
// Set/Get the dimention (n) of the components. Must be >= 1. Make sure that
// this is set before allocation.
vtkSetClampMacro(NumberOfComponents, int, 1, VTK_LARGE_INTEGER);
int GetNumberOfComponents() { return this->NumberOfComponents; }
// Description:
// Set the number of tuples (a component group) in the array. Note that
// this may allocate space depending on the number of components.
virtual void SetNumberOfTuples(vtkIdType number) = 0;
// Description:
// Get the number of tuples (a component group) in the array.
vtkIdType GetNumberOfTuples()
{return (this->MaxId + 1)/this->NumberOfComponents;}
// Description:
// Set the tuple at the ith location using the jth tuple in the source array.
// This method assumes that the two arrays have the same type
// and structure. Note that range checking and memory allocation is not
// performed; use in conjunction with SetNumberOfTuples() to allocate space.
virtual void SetTuple(vtkIdType i, vtkIdType j, vtkAbstractArray* source) = 0;
// Description:
// Insert the jth tuple in the source array, at ith location in this array.
// Note that memory allocation is performed as necessary to hold the data.
virtual void InsertTuple(vtkIdType i, vtkIdType j, vtkAbstractArray* source) = 0;
// Description:
// Insert the jth tuple in the source array, at the end in this array.
// Note that memory allocation is performed as necessary to hold the data.
// Returns the location at which the data was inserted.
virtual vtkIdType InsertNextTuple(vtkIdType j, vtkAbstractArray* source) = 0;
// Description:
// Given a list of point ids, return an array of tuples.
// You must insure that the output array has been previously
// allocated with enough space to hold the data.
virtual void GetTuples(vtkIdList *ptIds, vtkAbstractArray* output);
// Description:
// Get the tuples for the range of points ids specified
// (i.e., p1->p2 inclusive). You must insure that the output array has
// been previously allocated with enough space to hold the data.
virtual void GetTuples(vtkIdType p1, vtkIdType p2, vtkAbstractArray *output);
// Description:
// Return a void pointer. For image pipeline interface and other
......@@ -118,10 +141,25 @@ public:
virtual void DeepCopy(vtkAbstractArray *da) = 0;
// Description:
// Copy an element from one array into an element on this array.
virtual void CopyValue(int toIndex, int fromIndex,
vtkAbstractArray *sourceArray) = 0;
// Set the ith tuple in this array as the interpolated tuple value,
// given the ptIndices in the source array and associated
// interpolation weights.
// This method assumes that the two arrays are of the same type
// and strcuture.
virtual void InterpolateTuple(vtkIdType i, vtkIdList *ptIndices,
vtkAbstractArray* source, double* weights) = 0;
// Description
// Insert the ith tuple in this array as interpolated from the two values,
// p1 and p2, and an interpolation factor, t.
// The interpolation factor ranges from (0,1),
// with t=0 located at p1. This method assumes that the three arrays are of
// the same type. p1 is value at index id1 in source1, while, p2 is
// value at index id2 in source2.
virtual void InterpolateTuple(vtkIdType i,
vtkIdType id1, vtkAbstractArray* source1,
vtkIdType id2, vtkAbstractArray* source2, double t) =0;
// Description:
// Free any unnecessary memory.
// Description:
......@@ -129,7 +167,8 @@ public:
virtual void Squeeze() = 0;
// Description:
// Resize the array while conserving the data.
// Resize the array while conserving the data. Returns 1 if
// resizing succeeded and 0 otherwise.
virtual int Resize(vtkIdType numTuples) = 0;
// Description:
......@@ -156,7 +195,13 @@ public:
// from the supplied array.
virtual void SetVoidArray(void *vtkNotUsed(array),