Commit 1cf71d57 authored by Jeff Baumes's avatar Jeff Baumes
Browse files

ENH: Added more types to vtkVariant, and moved the operator << to the header to fix link error.

ENH: In vtkTable, GetValue() returns vtkVariant of the appropriate type.
ENH: Rolled back workaround for TestDelimitedTextReader; hopefully the operator << fix worked.
ENH: Added two more infovis tests, Table and VariantArray.
parent c48b3df9
......@@ -103,40 +103,32 @@ vtkVariant::~vtkVariant()
}
}
vtkVariant::vtkVariant(vtkStdString value)
{
this->Data.String = new vtkStdString(value);
this->Valid = 1;
this->Type = VTK_STRING;
}
vtkVariant::vtkVariant(const char* value)
vtkVariant::vtkVariant(int value)
{
this->Data.String = new vtkStdString(value);
this->Data.Int = value;
this->Valid = 1;
this->Type = VTK_STRING;
this->Type = VTK_INT;
}
vtkVariant::vtkVariant(float value)
vtkVariant::vtkVariant(unsigned int value)
{
this->Data.Float = value;
this->Data.UnsignedInt = value;
this->Valid = 1;
this->Type = VTK_FLOAT;
this->Type = VTK_UNSIGNED_INT;
}
vtkVariant::vtkVariant(double value)
vtkVariant::vtkVariant(long value)
{
this->Data.Double = value;
this->Data.Long = value;
this->Valid = 1;
this->Type = VTK_DOUBLE;
this->Type = VTK_LONG;
}
vtkVariant::vtkVariant(int value)
vtkVariant::vtkVariant(unsigned long value)
{
this->Data.Int = value;
this->Data.UnsignedLong = value;
this->Valid = 1;
this->Type = VTK_INT;
this->Type = VTK_UNSIGNED_LONG;
}
#if defined(VTK_TYPE_USE___INT64)
......@@ -170,6 +162,34 @@ vtkVariant::vtkVariant(unsigned long long value)
}
#endif
vtkVariant::vtkVariant(float value)
{
this->Data.Float = value;
this->Valid = 1;
this->Type = VTK_FLOAT;
}
vtkVariant::vtkVariant(double value)
{
this->Data.Double = value;
this->Valid = 1;
this->Type = VTK_DOUBLE;
}
vtkVariant::vtkVariant(const char* value)
{
this->Data.String = new vtkStdString(value);
this->Valid = 1;
this->Type = VTK_STRING;
}
vtkVariant::vtkVariant(vtkStdString value)
{
this->Data.String = new vtkStdString(value);
this->Valid = 1;
this->Type = VTK_STRING;
}
vtkVariant::vtkVariant(vtkObjectBase* value)
{
value->Register(0);
......@@ -193,6 +213,9 @@ bool vtkVariant::IsNumeric() const
return this->IsFloat()
|| this->IsDouble()
|| this->IsInt()
|| this->IsUnsignedInt()
|| this->IsLong()
|| this->IsUnsignedLong()
|| this->Is__Int64()
|| this->IsUnsigned__Int64()
|| this->IsLongLong()
......@@ -214,6 +237,21 @@ bool vtkVariant::IsInt() const
return this->Type == VTK_INT;
}
bool vtkVariant::IsUnsignedInt() const
{
return this->Type == VTK_UNSIGNED_INT;
}
bool vtkVariant::IsLong() const
{
return this->Type == VTK_LONG;
}
bool vtkVariant::IsUnsignedLong() const
{
return this->Type == VTK_UNSIGNED_LONG;
}
bool vtkVariant::Is__Int64() const
{
return this->Type == VTK___INT64;
......@@ -304,6 +342,24 @@ vtkStdString vtkVariant::ToString() const
ostr << this->Data.Int;
return vtkStdString(ostr.str());
}
if (this->IsUnsignedInt())
{
vtksys_ios::ostringstream ostr;
ostr << this->Data.UnsignedInt;
return vtkStdString(ostr.str());
}
if (this->IsLong())
{
vtksys_ios::ostringstream ostr;
ostr << this->Data.Long;
return vtkStdString(ostr.str());
}
if (this->IsUnsignedLong())
{
vtksys_ios::ostringstream ostr;
ostr << this->Data.UnsignedLong;
return vtkStdString(ostr.str());
}
#if defined(VTK_TYPE_USE___INT64)
if (this->Is__Int64())
{
......@@ -343,6 +399,21 @@ int vtkVariant::ToInt(bool* valid) const
return this->ToNumeric(valid, (int *)0);
}
unsigned int vtkVariant::ToUnsignedInt(bool* valid) const
{
return this->ToNumeric(valid, (unsigned int *)0);
}
long vtkVariant::ToLong(bool* valid) const
{
return this->ToNumeric(valid, (long *)0);
}
unsigned long vtkVariant::ToUnsignedLong(bool* valid) const
{
return this->ToNumeric(valid, (unsigned long *)0);
}
#if defined(VTK_TYPE_USE___INT64)
__int64 vtkVariant::To__Int64(bool* valid) const
{
......@@ -385,12 +456,6 @@ vtkAbstractArray* vtkVariant::ToArray() const
return 0;
}
ostream& operator << (ostream& out, vtkVariant& v)
{
out << v.ToString();
return out;
}
template <typename T>
T vtkVariantStringToNumeric(vtkStdString str, bool* valid, T* vtkNotUsed(ignored) = 0)
{
......@@ -430,6 +495,18 @@ T vtkVariant::ToNumeric(bool* valid, T* vtkNotUsed(ignored)) const
{
return static_cast<T>(this->Data.Int);
}
if (this->IsUnsignedInt())
{
return static_cast<T>(this->Data.UnsignedInt);
}
if (this->IsLong())
{
return static_cast<T>(this->Data.Long);
}
if (this->IsUnsignedLong())
{
return static_cast<T>(this->Data.UnsignedLong);
}
#if defined(VTK_TYPE_USE___INT64)
if (this->Is__Int64())
{
......
......@@ -27,6 +27,7 @@
#include "vtkType.h" // To define type IDs and VTK_TYPE_USE_* flags
#include "vtkSystemIncludes.h" // To define ostream
#include "vtkSetGet.h" // For vtkNotUsed macro
#include "vtkStdString.h"
//
// The following should be eventually placed in vtkType.h
......@@ -73,24 +74,20 @@ public:
vtkVariant(const vtkVariant & other);
// Description:
// Create a string variant from a std string.
vtkVariant(vtkStdString value);
// Create an integer variant.
vtkVariant(int value);
// Description:
// Create a string variant from a const char*.
vtkVariant(const char* value);
// Create an unsigned integer variant.
vtkVariant(unsigned int value);
// Description:
// Create a float variant.
vtkVariant(float value);
// Create an long variant.
vtkVariant(long value);
// Description:
// Create a double variant.
vtkVariant(double value);
// Description:
// Create an integer variant.
vtkVariant(int value);
// Create an unsigned long variant.
vtkVariant(unsigned long value);
#if defined(VTK_TYPE_USE___INT64)
// Description:
......@@ -111,6 +108,22 @@ public:
vtkVariant(unsigned long long value);
#endif
// Description:
// Create a float variant.
vtkVariant(float value);
// Description:
// Create a double variant.
vtkVariant(double value);
// Description:
// Create a string variant from a const char*.
vtkVariant(const char* value);
// Description:
// Create a string variant from a std string.
vtkVariant(vtkStdString value);
// Description:
// Create a vtkObjectBase variant.
vtkVariant(vtkObjectBase* value);
......@@ -143,6 +156,18 @@ public:
// Get whether the variant is an int.
bool IsInt() const;
// Description:
// Get whether the variant is an unsigned int.
bool IsUnsignedInt() const;
// Description:
// Get whether the variant is an long.
bool IsLong() const;
// Description:
// Get whether the variant is an unsigned long.
bool IsUnsignedLong() const;
// Description:
// Get whether the variant is an __int64.
bool Is__Int64() const;
......@@ -190,6 +215,9 @@ public:
float ToFloat(bool* valid = 0) const;
double ToDouble(bool* valid = 0) const;
int ToInt(bool* valid = 0) const;
unsigned int ToUnsignedInt(bool* valid = 0) const;
long ToLong(bool* valid = 0) const;
unsigned long ToUnsignedLong(bool* valid = 0) const;
#if defined(VTK_TYPE_USE___INT64)
__int64 To__Int64(bool* valid = 0) const;
unsigned __int64 ToUnsigned__Int64(bool* valid = 0) const;
......@@ -221,6 +249,9 @@ private:
float Float;
double Double;
int Int;
unsigned int UnsignedInt;
long Long;
unsigned long UnsignedLong;
#if defined(VTK_TYPE_USE___INT64)
__int64 __Int64;
unsigned __int64 Unsigned__Int64;
......@@ -236,4 +267,10 @@ private:
unsigned char Type;
};
inline ostream& operator << (ostream& out, vtkVariant& v)
{
out << v.ToString();
return out;
}
#endif
......@@ -13,6 +13,7 @@
=========================================================================*/
#include "vtkArrayIteratorIncludes.h"
#include "vtkTable.h"
#include "vtkVariantArray.h"
#include <vtkFieldData.h>
......@@ -27,7 +28,7 @@
// Standard functions
//
vtkCxxRevisionMacro(vtkTable, "1.1");
vtkCxxRevisionMacro(vtkTable, "1.2");
vtkStandardNewMacro(vtkTable);
//----------------------------------------------------------------------------
......@@ -317,6 +318,15 @@ vtkVariant vtkTable::GetValue(vtkIdType row, vtkIdType col)
return this->GetValueByName(row, this->GetColumnName(column));
}
//----------------------------------------------------------------------------
template <typename iterT>
vtkVariant vtkTableGetVariantValue(iterT* it, vtkIdType row)
{
return vtkVariant(it->GetValue(row));
}
//----------------------------------------------------------------------------
vtkVariant vtkTable::GetValueByName(vtkIdType row, const char* col)
......@@ -325,18 +335,25 @@ vtkVariant vtkTable::GetValueByName(vtkIdType row, const char* col)
int comps = arr->GetNumberOfComponents();
if (arr->IsA("vtkDataArray"))
{
vtkDataArray* data = vtkDataArray::SafeDownCast(arr);
if (comps == 1)
{
return vtkVariant(data->GetTuple1(row));
vtkArrayIterator* iter = arr->NewIterator();
vtkVariant v;
switch(arr->GetDataType())
{
vtkArrayIteratorTemplateMacro(
v = vtkTableGetVariantValue(static_cast<VTK_TT*>(iter), row));
}
iter->Delete();
return v;
}
else
{
// Create a variant holding an array of the appropriate type
// with one tuple.
vtkDataArray* da = vtkDataArray::CreateDataArray(data->GetDataType());
vtkDataArray* da = vtkDataArray::CreateDataArray(arr->GetDataType());
da->SetNumberOfComponents(comps);
da->InsertNextTuple(row, data);
da->InsertNextTuple(row, arr);
vtkVariant v(da);
da->Delete();
return v;
......
......@@ -3,6 +3,8 @@ IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY)
SET(KIT Infovis)
# add tests that do not require data
SET(MyTests
Table
VariantArray
)
IF (VTK_DATA_ROOT)
# add tests that require data
......
#include "vtkTable.h"
#include "vtkIntArray.h"
#include "vtkStringArray.h"
#include "vtkDoubleArray.h"
#include "vtkVariantArray.h"
#include "vtkFieldData.h"
#include "vtkMath.h"
#include <time.h>
#include <vtkstd/vector>
using vtkstd::vector;
void CheckEqual(vtkTable* table, vector<vector<double> > & stdTable)
{
// Check sizes
if (table->GetNumberOfRows() != static_cast<vtkIdType>(stdTable[0].size()))
{
cout << "Number of rows is incorrect ("
<< table->GetNumberOfRows() << " != " << stdTable.size() << ")" << endl;
exit(1);
}
if (table->GetNumberOfColumns() != static_cast<vtkIdType>(stdTable.size()))
{
cout << "Number of columns is incorrect ("
<< table->GetNumberOfColumns() << " != " << stdTable.size() << ")" << endl;
exit(1);
}
// Use GetValue() and GetValueByName() to check
for (int i = 0; i < table->GetNumberOfRows(); i++)
{
for (int j = 0; j < table->GetNumberOfColumns(); j++)
{
double tableVal = table->GetValue(i, j).ToDouble();
double stdTableVal = stdTable[j][i];
if (stdTableVal && tableVal != stdTableVal)
{
cout << "Values not equal at row " << i << " column " << j << ": ";
cout << "(" << tableVal << " != " << stdTableVal << ")" << endl;
exit(1);
}
}
}
// Use GetColumn() and GetColumnByName() to check
for (int j = 0; j < table->GetNumberOfColumns(); j++)
{
vtkAbstractArray* arr;
if (vtkMath::Random() < 0.5)
{
arr = table->GetColumn(j);
}
else
{
arr = table->GetColumnByName(table->GetColumnName(j));
}
for (int i = 0; i < table->GetNumberOfRows(); i++)
{
double val;
if (arr->IsA("vtkVariantArray"))
{
val = vtkVariantArray::SafeDownCast(arr)->GetValue(i).ToDouble();
}
else if (arr->IsA("vtkStringArray"))
{
vtkVariant v(vtkStringArray::SafeDownCast(arr)->GetValue(i));
val = v.ToDouble();
}
else if (arr->IsA("vtkDataArray"))
{
val = vtkDataArray::SafeDownCast(arr)->GetTuple1(i);
}
else
{
cout << "Unknown array type" << endl;
exit(1);
}
double stdTableVal = stdTable[j][i];
if (stdTableVal && val != stdTableVal)
{
cout << "Values not equal at row " << i << " column " << j << ": ";
cout << "(" << val << " != " << stdTableVal << ")" << endl;
exit(1);
}
}
}
// Use GetRow() to check
for (int i = 0; i < table->GetNumberOfRows(); i++)
{
vtkVariantArray* arr = table->GetRow(i);
for (int j = 0; j < table->GetNumberOfColumns(); j++)
{
double val = arr->GetValue(j).ToDouble();
double stdTableVal = stdTable[j][i];
if (stdTableVal && val != stdTableVal)
{
cout << "Values not equal at row " << i << " column " << j << ": ";
cout << "(" << val << " != " << stdTableVal << ")" << endl;
exit(1);
}
}
arr->Delete();
}
}
int Table(int, char*[])
{
long seed = time(NULL);
cout << "Seed: " << seed << endl;
vtkMath::RandomSeed(seed);
// Make a table and a parallel vector of vectors
vtkTable* table = vtkTable::New();
vector<vector< double > > stdTable;
int size = 100;
double prob = 1.0 - 1.0 / size;
double highProb = 1.0 - 1.0 / (size*size);
cout << "Creating columns." << endl;
vtkIdType columnId = 0;
bool noColumns = true;
while (noColumns || vtkMath::Random() < prob)
{
noColumns = false;
stdTable.push_back(vector<double>());
double r = vtkMath::Random();
vtkVariant name(columnId);
vtkAbstractArray* arr;
if (r < 0.25)
{
arr = vtkIntArray::New();
arr->SetName((name.ToString() + " (vtkIntArray)").c_str());
}
else if (r < 0.5)
{
arr = vtkDoubleArray::New();
arr->SetName((name.ToString() + " (vtkDoubleArray)").c_str());
}
else if (r < 0.75)
{
arr = vtkStringArray::New();
arr->SetName((name.ToString() + " (vtkStringArray)").c_str());
}
else
{
arr = vtkVariantArray::New();
arr->SetName((name.ToString() + " (vtkVariantArray)").c_str());
}
table->AddColumn(arr);
arr->Delete();
columnId++;
}
cout << "Inserting empty rows." << endl;
bool noRows = true;
while (noRows || vtkMath::Random() < prob)
{
noRows = false;
table->InsertNextBlankRow();
for (unsigned int i = 0; i < stdTable.size(); i++)
{
stdTable[i].push_back(0.0);
}
}
cout << "Inserting full rows." << endl;
while (vtkMath::Random() < prob)
{
vtkVariantArray* rowArray = vtkVariantArray::New();
for (vtkIdType j = 0; j < table->GetNumberOfColumns(); j++)
{
rowArray->InsertNextValue(vtkVariant(j));
stdTable[j].push_back(j);
}
table->InsertNextRow(rowArray);
rowArray->Delete();
}
cout << "Performing all kinds of inserts." << endl;
int id = 0;
while (vtkMath::Random() < highProb)
{
vtkIdType row = static_cast<vtkIdType>(vtkMath::Random(0, table->GetNumberOfRows()));
vtkIdType col = static_cast<vtkIdType>(vtkMath::Random(0, table->GetNumberOfColumns()));
vtkVariant v;
if (vtkMath::Random() < 0.25)
{
vtkVariant temp(id);
v = vtkVariant(temp.ToString());
}
else if (vtkMath::Random() < 0.5)
{
v = vtkVariant(id);
}
else
{
v = vtkVariant(static_cast<double>(id));
}
if (vtkMath::Random() < 0.5)
{
table->SetValue(row, col, v);
}
else
{
table->SetValueByName(row, table->GetColumnName(col), v);
}
stdTable[col][row] = id;
id++;
}
cout << "Removing half of the rows." << endl;
int numRowsToRemove = table->GetNumberOfRows() / 2;
for (int i = 0; i < numRowsToRemove; i++)
{
vtkIdType row = static_cast<vtkIdType>(vtkMath::Random(0, table->GetNumberOfRows()));
table->RemoveRow(row);
for (unsigned int j = 0; j < stdTable.size(); j++)
{
vector<double>::iterator rowIt = stdTable[j].begin() + row;
stdTable[j].erase(rowIt);
}
}
cout << "Removing half of the columns." << endl;
int numColsToRemove = table->GetNumberOfColumns() / 2;
for (int i = 0; i < numColsToRemove; i++)
{
vtkIdType col = static_cast<vtkIdType>(vtkMath::Random(0, table->GetNumberOfColumns()));
if (vtkMath::Random() < 0.5)
{
table->RemoveColumn(col);
}
else
{
table->RemoveColumnByName(table->GetColumnName(col));