Commit d63a636a authored by David Thompson's avatar David Thompson
Browse files

ENH: Add a vtkInformation pointer to vtkAbstractArray.

MGMT: Move vtkInformation classes from Filtering to Common to accomodate
      change above.
ENH: Add test of new vtkInformation pointer to TestDataArray
ENH: Move component range information out of vtkDataArray and into
     the array's vtkInformation object. New keys PER_COMPONENT,
     COMPONENT_RANGE, and L2_NORM_RANGE accomplish this.
parent f7dcccc1
......@@ -36,6 +36,7 @@ vtkCharArray.cxx
vtkCollection.cxx
vtkCollectionIterator.cxx
vtkCommand.cxx
vtkCommonInformationKeyManager.cxx
vtkContourValues.cxx
vtkCriticalSection.cxx
vtkCylindricalTransform.cxx
......@@ -71,6 +72,26 @@ vtkIdentityTransform.cxx
vtkImplicitFunction.cxx
vtkImplicitFunctionCollection.cxx
vtkIndent.cxx
vtkInformation.cxx
vtkInformationDataObjectKey.cxx
vtkInformationDoubleKey.cxx
vtkInformationDoubleVectorKey.cxx
vtkInformationExecutivePortKey.cxx
vtkInformationExecutivePortVectorKey.cxx
vtkInformationIdTypeKey.cxx
vtkInformationInformationKey.cxx
vtkInformationInformationVectorKey.cxx
vtkInformationIntegerKey.cxx
vtkInformationIntegerPointerKey.cxx
vtkInformationIntegerVectorKey.cxx
vtkInformationIterator.cxx
vtkInformationKey.cxx
vtkInformationKeyVectorKey.cxx
vtkInformationObjectBaseKey.cxx
vtkInformationRequestKey.cxx
vtkInformationStringKey.cxx
vtkInformationUnsignedLongKey.cxx
vtkInformationVector.cxx
vtkInitialValueProblemSolver.cxx
vtkInstantiator.cxx
vtkIntArray.cxx
......@@ -223,11 +244,29 @@ vtkArrayIteratorTemplate
vtkAbstractTransform
vtkCallbackCommand
vtkCommand
vtkCommonInformationKeyManager
vtkDataArray
vtkEventForwarderCommand
vtkFunctionSet
vtkHomogeneousTransform
vtkImplicitFunction
vtkInformationDataObjectKey
vtkInformationDoubleKey
vtkInformationDoubleVectorKey
vtkInformationExecutivePortKey
vtkInformationExecutivePortVectorKey
vtkInformationIdTypeKey
vtkInformationInformationKey
vtkInformationInformationVectorKey
vtkInformationIntegerKey
vtkInformationIntegerPointerKey
vtkInformationIntegerVectorKey
vtkInformationKey
vtkInformationKeyVectorKey
vtkInformationObjectBaseKey
vtkInformationRequestKey
vtkInformationStringKey
vtkInformationUnsignedLongKey
vtkInitialValueProblemSolver
vtkLinearTransform
vtkObjectBase
......@@ -249,6 +288,7 @@ SET_SOURCE_FILES_PROPERTIES(
vtkBoundingBox.cxx
vtkCallbackCommand.cxx
vtkCommand.cxx
vtkCommonInformationKeyManager.cxx
vtkDebugLeaksManager.cxx
vtkErrorCode.cxx
vtkEventForwarderCommand.cxx
......
......@@ -25,6 +25,7 @@ IF(PYTHON_EXECUTABLE)
vtkByteSwap.h
vtkCallbackCommand.h
vtkCommand.h
vtkCommonInformationKeyManager.h
vtkContainer.h
vtkDataArrayCollection.h
vtkDataArrayTemplate.h
......@@ -42,6 +43,7 @@ IF(PYTHON_EXECUTABLE)
vtkIOStream.h
vtkIOStreamFwd.h
vtkIndent.h
vtkInformationInternals.h
vtkJavaAwt.h
vtkJavaUtil.h
vtkLargeInteger.h
......
......@@ -3,23 +3,66 @@
int TestDataArray(int,char *[])
{
double range[2];
vtkIntArray* array = vtkIntArray::New();
array->GetRange( range, 0 );
if ( range[0] != VTK_DOUBLE_MAX || range[1] != VTK_DOUBLE_MIN )
{
cerr
<< "Getting range of empty array failed, min: "
<< range[0] << " max: " << range[1] << "\n";
array->Delete();
return 1;
}
int cc;
for ( cc = 0; cc < 10; cc ++ )
{
array->InsertNextTuple1(cc);
}
array->GetRange( range, 0 ); // Range is now 0-9. Used to check MTimes.
array->RemoveFirstTuple();
array->RemoveTuple(3);
array->RemoveTuple(4);
array->GetRange( range, 0 );
if ( range[0] != 0 || range[1] != 9 )
{
cerr
<< "Getting range (" << range[0] << "-" << range[1]
<< ") of array not marked as modified caused recomputation of range!";
array->Delete();
return 1;
}
array->Modified(); // Now mark array so range gets recomputed
array->GetRange( range, 0 );
if ( range[0] != 1. || range[1] != 9. )
{
cerr
<< "Getting range of array {1,2,3,5,7,8,9} failed, min: "
<< range[0] << " max: " << range[1] << "\n";
array->Delete();
return 1;
}
array->RemoveLastTuple();
array->Modified();
array->GetRange( range, 0 );
if ( range[0] != 1. || range[1] != 8. )
{
cerr
<< "Getting range of array {1,2,3,5,7,8} failed, min: "
<< range[0] << " max: " << range[1] << "\n";
array->Delete();
return 1;
}
int ca[] = { 1, 2, 3, 5, 7, 8 };
cout << "Array:";
for ( cc = 0; cc < array->GetNumberOfTuples(); ++cc )
{
if ( array->GetTuple1(cc) != ca[cc] )
{
cerr << "Problem with array: " << array->GetTuple1(cc) << " <> " << ca[cc] << endl;
cerr
<< "Problem with array: " << array->GetTuple1(cc)
<< " <> " << ca[cc] << endl;
array->Delete();
return 1;
}
cout << " " << array->GetTuple1(cc);
......@@ -50,6 +93,7 @@ int TestDataArray(int,char *[])
if (fa[i] != fc[i])
{
cerr << "Problem with array: " << fa[i] << " <> " << fc[i] << endl;
farray->Delete();
return 1;
}
}
......
......@@ -29,6 +29,7 @@
#include "vtkUnsignedIntArray.h"
#include "vtkUnsignedLongArray.h"
#include "vtkUnsignedShortArray.h"
#include "vtkInformation.h"
#if defined(VTK_TYPE_USE_LONG_LONG)
# include "vtkLongLongArray.h"
......@@ -41,7 +42,11 @@
# include "vtkUnsigned__Int64Array.h"
# endif
#endif
vtkCxxRevisionMacro(vtkAbstractArray, "1.9");
vtkCxxRevisionMacro(vtkAbstractArray, "1.10");
vtkCxxSetObjectMacro(vtkAbstractArray,Information,vtkInformation);
//----------------------------------------------------------------------------
// Construct object with sane defaults.
vtkAbstractArray::vtkAbstractArray(vtkIdType vtkNotUsed(numComp))
......@@ -50,12 +55,14 @@ vtkAbstractArray::vtkAbstractArray(vtkIdType vtkNotUsed(numComp))
this->MaxId = -1;
this->NumberOfComponents = 1;
this->Name = NULL;
this->Information = NULL;
}
//----------------------------------------------------------------------------
vtkAbstractArray::~vtkAbstractArray()
{
this->SetName(NULL);
this->SetInformation(NULL);
}
//----------------------------------------------------------------------------
......@@ -94,6 +101,27 @@ void vtkAbstractArray::GetTuples(vtkIdType p1, vtkIdType p2,
}
}
//----------------------------------------------------------------------------
void vtkAbstractArray::DeepCopy( vtkAbstractArray* da )
{
if ( da && da->Information && da != this )
{
vtkInformation* info = this->GetInformation(); // may create new instance
info->Copy( da->Information, 1 /* deep */ );
}
}
//----------------------------------------------------------------------------
vtkInformation* vtkAbstractArray::GetInformation()
{
if ( ! this->Information )
{
vtkInformation* info = vtkInformation::New();
this->SetInformation( info );
info->FastDelete();
}
return this->Information;
}
//----------------------------------------------------------------------------
template <class T>
......@@ -219,4 +247,9 @@ void vtkAbstractArray::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "Size: " << this->Size << "\n";
os << indent << "MaxId: " << this->MaxId << "\n";
os << indent << "NumberOfComponents: " << this->NumberOfComponents << endl;
os << indent << "Information: " << this->Information << endl;
if ( this->Information )
{
this->Information->PrintSelf( os, indent.GetNextIndent() );
}
}
......@@ -44,10 +44,11 @@
#include "vtkObject.h"
#include "vtkVariant.h" // for variant arguments
class vtkArrayIterator;
class vtkDataArray;
class vtkIdList;
class vtkIdTypeArray;
class vtkDataArray;
class vtkArrayIterator;
class vtkInformation;
class VTK_COMMON_EXPORT vtkAbstractArray : public vtkObject
{
......@@ -139,7 +140,10 @@ public:
// Deep copy of data. Implementation left to subclasses, which
// should support as many type conversions as possible given the
// data type.
virtual void DeepCopy(vtkAbstractArray *da) = 0;
//
// Subclasses should call vtkAbstractArray::DeepCopy() so that the
// information object (if one exists) is copied from \a da.
virtual void DeepCopy(vtkAbstractArray* da);
// Description:
// Set the ith tuple in this array as the interpolated tuple value,
......@@ -279,12 +283,24 @@ public:
// bool includeMin = true, bool includeMax = true) = 0;
//virtual void LookupGreaterThan(vtkVariant min, vtkIdList* ids, bool includeMin = false) = 0;
//virtual void LookupLessThan(vtkVariant max, vtkIdList* ids, bool includeMax = false) = 0;
// Description:
// Get an information object that can be used to annotate the array.
// This is NULL by default; you are responsible for allocating an information object
// if none already exists.
vtkInformation* GetInformation();
protected:
// Construct object with default tuple dimension (number of components) of 1.
vtkAbstractArray(vtkIdType numComp=1);
~vtkAbstractArray();
// Description:
// Set an information object that can be used to annotate the array.
// This is NULL by default; you are responsible for allocating an information object
// if none already exists.
virtual void SetInformation( vtkInformation* );
vtkIdType Size; // allocated size of data
vtkIdType MaxId; // maximum index inserted thus far
int NumberOfComponents; // the number of components per tuple
......@@ -293,6 +309,8 @@ protected:
bool RebuildArray; // whether to rebuild the fast lookup data structure.
vtkInformation* Information;
private:
vtkAbstractArray(const vtkAbstractArray&); // Not implemented.
void operator=(const vtkAbstractArray&); // Not implemented.
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCommonInformationKeyManager.cxx
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.
=========================================================================*/
#include "vtkCommonInformationKeyManager.h"
#include "vtkInformationKey.h"
#include <vtkstd/vector>
// Subclass vector so we can directly call constructor. This works
// around problems on Borland C++.
struct vtkCommonInformationKeyManagerKeysType:
public vtkstd::vector<vtkInformationKey*>
{
typedef vtkstd::vector<vtkInformationKey*> Superclass;
typedef Superclass::iterator iterator;
};
//----------------------------------------------------------------------------
// Must NOT be initialized. Default initialization to zero is
// necessary.
static unsigned int vtkCommonInformationKeyManagerCount;
static vtkCommonInformationKeyManagerKeysType* vtkCommonInformationKeyManagerKeys;
//----------------------------------------------------------------------------
vtkCommonInformationKeyManager::vtkCommonInformationKeyManager()
{
if(++vtkCommonInformationKeyManagerCount == 1)
{
vtkCommonInformationKeyManager::ClassInitialize();
}
}
//----------------------------------------------------------------------------
vtkCommonInformationKeyManager::~vtkCommonInformationKeyManager()
{
if(--vtkCommonInformationKeyManagerCount == 0)
{
vtkCommonInformationKeyManager::ClassFinalize();
}
}
//----------------------------------------------------------------------------
void vtkCommonInformationKeyManager::Register(vtkInformationKey* key)
{
// Register this instance for deletion by the singleton.
vtkCommonInformationKeyManagerKeys->push_back(key);
}
//----------------------------------------------------------------------------
void vtkCommonInformationKeyManager::ClassInitialize()
{
// Allocate the singleton storing pointers to information keys.
// This must be a malloc/free pair instead of new/delete to work
// around problems on MachO (Mac OSX) runtime systems that do lazy
// symbol loading. Calling operator new here causes static
// initialization to occur in other translation units immediately,
// which then may try to access the vector before it is set here.
void* keys = malloc(sizeof(vtkCommonInformationKeyManagerKeysType));
vtkCommonInformationKeyManagerKeys =
new (keys) vtkCommonInformationKeyManagerKeysType;
}
//----------------------------------------------------------------------------
void vtkCommonInformationKeyManager::ClassFinalize()
{
if(vtkCommonInformationKeyManagerKeys)
{
// Delete information keys.
for(vtkCommonInformationKeyManagerKeysType::iterator i =
vtkCommonInformationKeyManagerKeys->begin();
i != vtkCommonInformationKeyManagerKeys->end(); ++i)
{
vtkInformationKey* key = *i;
delete key;
}
// Delete the singleton storing pointers to information keys. See
// ClassInitialize above for why this is a free instead of a
// delete.
vtkCommonInformationKeyManagerKeys->~vtkCommonInformationKeyManagerKeysType();
free(vtkCommonInformationKeyManagerKeys);
vtkCommonInformationKeyManagerKeys = 0;
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCommonInformationKeyManager.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 vtkCommonInformationKeyManager - Manages key types in vtkCommon.
// .SECTION Description
// vtkCommonInformationKeyManager is included in the header of any
// subclass of vtkInformationKey defined in the vtkCommon library.
// It makes sure that the table of keys is created before and
// destroyed after it is used.
#ifndef __vtkCommonInformationKeyManager_h
#define __vtkCommonInformationKeyManager_h
#include "vtkSystemIncludes.h"
#include "vtkDebugLeaksManager.h" // DebugLeaks exists longer than info keys.
class vtkInformationKey;
class VTK_FILTERING_EXPORT vtkCommonInformationKeyManager
{
public:
vtkCommonInformationKeyManager();
~vtkCommonInformationKeyManager();
// Description:
// Called by constructors of vtkInformationKey subclasses defined in
// vtkCommon to register themselves with the manager. The
// instances will be deleted when vtkCommon is unloaded on
// program exit.
static void Register(vtkInformationKey* key);
private:
static void ClassInitialize();
static void ClassFinalize();
};
// This instance will show up in any translation unit that uses key
// types defined in vtkCommon or that has a singleton. It will
// make sure vtkCommonInformationKeyManager's vector of keys is
// initialized before and destroyed after it is used.
static vtkCommonInformationKeyManager vtkCommonInformationKeyManagerInstance;
#endif
......@@ -18,8 +18,12 @@
#include "vtkCriticalSection.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkIntArray.h"
#include "vtkInformation.h"
#include "vtkInformationDoubleVectorKey.h"
#include "vtkInformationInformationVectorKey.h"
#include "vtkInformationVector.h"
#include "vtkIdTypeArray.h"
#include "vtkIntArray.h"
#include "vtkIdList.h"
#include "vtkLookupTable.h"
#include "vtkLongArray.h"
......@@ -31,9 +35,11 @@
#include "vtkUnsignedLongArray.h"
#include "vtkUnsignedShortArray.h"
vtkInformationKeyMacro(vtkDataArray, PER_COMPONENT, InformationVector);
vtkInformationKeyRestrictedMacro(vtkDataArray, COMPONENT_RANGE, DoubleVector, 2);
vtkInformationKeyRestrictedMacro(vtkDataArray, L2_NORM_RANGE, DoubleVector, 2);
vtkCxxRevisionMacro(vtkDataArray, "1.79");
vtkCxxRevisionMacro(vtkDataArray, "1.80");
//----------------------------------------------------------------------------
// Construct object with default tuple dimension (number of components) of 1.
......@@ -129,6 +135,8 @@ void vtkDataArray::DeepCopy(vtkDataArray *da)
if ( this != da )
{
this->Superclass::DeepCopy( da ); // copy Information object
int numTuples = da->GetNumberOfTuples();
this->NumberOfComponents = da->NumberOfComponents;
this->SetNumberOfTuples(numTuples);
......@@ -976,59 +984,95 @@ void vtkDataArray::ComputeRange(int comp)
{
double s,t;
vtkIdType numTuples;
vtkInformation* info = this->GetInformation();
if (comp < 0 && this->NumberOfComponents == 1)
{
comp = 0;
}
int idx = comp;
idx = (idx<0)?(this->NumberOfComponents):(idx);
if (idx >= VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES ||
(this->GetMTime() > this->ComponentRangeComputeTime[idx]) )
vtkInformationDoubleVectorKey* rkey;
if ( comp < 0 )
{
numTuples=this->GetNumberOfTuples();
this->Range[0] = VTK_DOUBLE_MAX;
this->Range[1] = VTK_DOUBLE_MIN;
for (vtkIdType i=0; i<numTuples; i++)
rkey = L2_NORM_RANGE();
}
else
{
vtkInformationVector* infoVec;
if ( ! info->Has( PER_COMPONENT() ) )
{
if (comp >= 0)
infoVec = vtkInformationVector::New();
info->Set( PER_COMPONENT(), infoVec );
}
else
{
infoVec = info->Get( PER_COMPONENT() );
}
int vlen = infoVec->GetNumberOfInformationObjects();
if ( vlen < this->NumberOfComponents )
{
infoVec->SetNumberOfInformationObjects( this->NumberOfComponents );
double rtmp[2];
rtmp[0] = VTK_DOUBLE_MAX;
rtmp[1] = VTK_DOUBLE_MIN;
// Since the MTime() of these new keys will be newer than this->MTime(), we must
// be sure that their ranges are marked "invalid" so that we know they must be
// computed.
for ( int i = vlen; i < this->NumberOfComponents; ++i )
{
s = this->GetComponent(i,comp);
infoVec->GetInformationObject( i )->Set( COMPONENT_RANGE(), rtmp, 2 );
}
else
{ // Compute range of vector magnitude.
s = 0.0;
for (int j=0; j < this->NumberOfComponents; ++j)
{
t = this->GetComponent(i,j);
s += t*t;
}
s = sqrt(s);
}
if ( s < this->Range[0] )
}
info = infoVec->GetInformationObject( comp );
rkey = COMPONENT_RANGE();
}
if ( info->Has( rkey ) )
{
if ( this->GetMTime() <= info->GetMTime() )
{
info->Get( rkey, this->Range );
if ( this->Range[0] != VTK_DOUBLE_MAX && this->Range[1] != VTK_DOUBLE_MIN )
{
this->Range[0] = s;
// Only accept these values if they are reasonable. Otherwise, it is an
// indication that they've never been computed before.
return;
}
if ( s > this->Range[1] )
}
}
// If we got here, we need to compute the range.
numTuples=this->GetNumberOfTuples();
this->Range[0] = VTK_DOUBLE_MAX;
this->Range[1] = VTK_DOUBLE_MIN;
for (vtkIdType i=0; i<numTuples; i++)
{
if (comp >= 0)
{
s = this->GetComponent(i,comp);
}
else
{ // Compute range of vector magnitude.
s = 0.0;
for (int j=0; j < this->NumberOfComponents; ++j)
{
this->Range[1] = s;
t = this->GetComponent(i,j);
s += t*t;
}
s = sqrt(s);
}
if (idx < VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES)
if ( s < this->Range[0] )
{
this->ComponentRangeComputeTime[idx].Modified();
this->ComponentRange[idx][0] = this->Range[0];
this->ComponentRange[idx][1] = this->Range[1];
this->Range[0] = s;
}
if ( s > this->Range[1] )
{
this->Range[1] = s;
}
}
else
{
this->Range[0] = this->ComponentRange[idx][0];
this->Range[1] = this->ComponentRange[idx][1];
}
info->Set( rkey, this->Range, 2 );
}
//----------------------------------------------------------------------------
......
......@@ -37,10 +37,10 @@
#include "vtkAbstractArray.h"
class vtkDoubleArray