Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

525 lines
13 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkCommunicator.cxx,v $
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 "vtkCommunicator.h"
#include "vtkCharArray.h"
#include "vtkDataSetReader.h"
#include "vtkDataSetWriter.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkIdTypeArray.h"
#include "vtkImageClip.h"
#include "vtkIntArray.h"
#include "vtkStructuredPoints.h"
#include "vtkStructuredPointsReader.h"
#include "vtkStructuredPointsWriter.h"
#include "vtkUnsignedCharArray.h"
#include "vtkUnsignedLongArray.h"
vtkCxxRevisionMacro(vtkCommunicator, "$Revision: 1.28 $");
template <class T>
int SendDataArray(T* data, int length, int handle, int tag, vtkCommunicator *self)
{
self->Send(data, length, handle, tag);
return 1;
}
vtkCommunicator::vtkCommunicator()
{
this->MarshalString = 0;
this->MarshalStringLength = 0;
this->MarshalDataLength = 0;
}
vtkCommunicator::~vtkCommunicator()
{
this->DeleteAndSetMarshalString(0, 0);
}
int vtkCommunicator::UseCopy = 0;
void vtkCommunicator::SetUseCopy(int useCopy)
{
vtkCommunicator::UseCopy = useCopy;
}
void vtkCommunicator::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Marshal string: ";
if ( this->MarshalString )
{
os << this->MarshalString << endl;
}
else
{
os << "(None)" << endl;
}
os << indent << "Marshal string length: " << this->MarshalStringLength
<< endl;
os << indent << "Marshal data length: " << this->MarshalDataLength
<< endl;
}
//----------------------------------------------------------------------------
// Internal method. Assumes responsibility for deleting the string
void vtkCommunicator::DeleteAndSetMarshalString(char *str, int strLength)
{
// delete any previous string
if (this->MarshalString)
{
delete [] this->MarshalString;
this->MarshalString = 0;
this->MarshalStringLength = 0;
this->MarshalDataLength = 0;
}
this->MarshalString = str;
this->MarshalStringLength = strLength;
}
// Need to add better error checking
int vtkCommunicator::Send(vtkDataObject* data, int remoteHandle,
int tag)
{
if (data == NULL)
{
this->MarshalDataLength = 0;
this->Send( &this->MarshalDataLength, 1,
remoteHandle, tag);
return 1;
}
if (this->WriteObject(data))
{
this->Send( &this->MarshalDataLength, 1,
remoteHandle, tag);
// then send the string.
this->Send( this->MarshalString, this->MarshalDataLength,
remoteHandle, tag);
return 1;
}
// could not marshal data
return 0;
}
int vtkCommunicator::Send(vtkDataArray* data, int remoteHandle, int tag)
{
int type = -1;
if (data == NULL)
{
this->MarshalDataLength = 0;
this->Send( &type, 1, remoteHandle, tag);
return 1;
}
// send array type
type = data->GetDataType();
this->Send( &type, 1, remoteHandle, tag);
// send array size
vtkIdType size = data->GetSize();
this->Send( &size, 1, remoteHandle, tag);
// send number of components in array
int numComponents = data->GetNumberOfComponents();
this->Send( &numComponents, 1, remoteHandle, tag);
const char* name = data->GetName();
int len = 0;
if (name)
{
len = static_cast<int>(strlen(name)) + 1;
}
// send length of name
this->Send( &len, 1, remoteHandle, tag);
if (len > 0)
{
// send name
this->Send( const_cast<char*>(name), len, remoteHandle, tag);
}
// now send the raw array
switch (type)
{
case VTK_CHAR:
return SendDataArray(static_cast<char*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
case VTK_UNSIGNED_CHAR:
return SendDataArray(static_cast<unsigned char*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
case VTK_INT:
return SendDataArray(static_cast<int*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
case VTK_UNSIGNED_LONG:
return SendDataArray(static_cast<unsigned long*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
case VTK_FLOAT:
return SendDataArray(static_cast<float*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
case VTK_DOUBLE:
return SendDataArray(static_cast<double*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
case VTK_ID_TYPE:
return SendDataArray(static_cast<vtkIdType*>(data->GetVoidPointer(0)),
size, remoteHandle, tag, this);
default:
vtkErrorMacro(<<"Unsupported data type!");
return 0; // could not marshal data
}
}
int vtkCommunicator::Receive(vtkDataObject* data, int remoteHandle,
int tag)
{
int dataLength;
// First receive the data length.
if (!this->Receive( &dataLength, 1, remoteHandle, tag))
{
vtkErrorMacro("Could not receive data!");
return 0;
}
if (dataLength < 0)
{
vtkErrorMacro("Bad data length");
return 0;
}
if (dataLength == 0)
{ // This indicates a NULL object was sent. Do nothing.
return 1;
}
// if we cannot reuse the string, allocate a new one.
if (dataLength > this->MarshalStringLength)
{
char *str = new char[dataLength + 10]; // maybe a little extra?
this->DeleteAndSetMarshalString(str, dataLength + 10);
}
// Receive the string
this->Receive(this->MarshalString, dataLength,
remoteHandle, tag);
this->MarshalDataLength = dataLength;
this->ReadObject(data);
// we should really look at status to determine success
return 1;
}
int vtkCommunicator::Receive(vtkDataArray* data, int remoteHandle,
int tag)
{
vtkIdType size;
int type;
int numComponents;
int nameLength;
char *c = 0;
unsigned char *uc = 0;
int *i = 0;
unsigned long *ul = 0;
float *f = 0;
double *d = 0;
vtkIdType *idt = 0;
// First receive the data type.
if (!this->Receive( &type, 1, remoteHandle, tag))
{
vtkErrorMacro("Could not receive data!");
return 0;
}
if (type == -1)
{ // This indicates a NULL object was sent. Do nothing.
return 1;
}
// Next receive the data length.
if (!this->Receive( &size, 1, remoteHandle, tag))
{
vtkErrorMacro("Could not receive data!");
return 0;
}
// Next receive the number of components.
this->Receive( &numComponents, 1, remoteHandle, tag);
// Next receive the length of the name.
this->Receive( &nameLength, 1, remoteHandle, tag);
if ( nameLength > 0 )
{
char *str = new char[nameLength];
this->DeleteAndSetMarshalString(str, nameLength);
// Receive the name
this->Receive(this->MarshalString, nameLength, remoteHandle, tag);
this->MarshalDataLength = nameLength;
}
if (size < 0)
{
vtkErrorMacro("Bad data length");
return 0;
}
if (size == 0)
{ // This indicates a NULL object was sent. Do nothing.
return 1;
}
// Receive the raw data array
switch (type)
{
case VTK_CHAR:
c = new char[size];
this->Receive(c, size, remoteHandle, tag);
static_cast<vtkCharArray*>(data)->SetArray(c, size, 0);
break;
case VTK_UNSIGNED_CHAR:
uc = new unsigned char[size];
this->Receive(uc, size, remoteHandle, tag);
static_cast<vtkUnsignedCharArray*>(data)->SetArray(uc, size, 0);
break;
case VTK_INT:
i = new int[size];
this->Receive(i, size, remoteHandle, tag);
static_cast<vtkIntArray*>(data)->SetArray(i, size, 0);
break;
case VTK_UNSIGNED_LONG:
ul = new unsigned long[size];
this->Receive(ul, size, remoteHandle, tag);
static_cast<vtkUnsignedLongArray*>(data)->SetArray(ul, size, 0);
break;
case VTK_FLOAT:
f = new float[size];
this->Receive(f, size, remoteHandle, tag);
static_cast<vtkFloatArray*>(data)->SetArray(f, size, 0);
break;
case VTK_DOUBLE:
d = new double[size];
this->Receive(d, size, remoteHandle, tag);
static_cast<vtkDoubleArray*>(data)->SetArray(d, size, 0);
break;
case VTK_ID_TYPE:
idt = new vtkIdType[size];
this->Receive(idt, size, remoteHandle, tag);
static_cast<vtkIdTypeArray*>(data)->SetArray(idt, size, 0);
break;
default:
vtkErrorMacro(<<"Unsupported data type!");
return 0; // could not marshal data
}
if (nameLength > 0)
{
data->SetName(this->MarshalString);
}
else
{
data->SetName(0);
}
data->SetNumberOfComponents(numComponents);
return 1;
}
int vtkCommunicator::WriteObject(vtkDataObject *data)
{
if (strcmp(data->GetClassName(), "vtkPolyData") == 0 ||
strcmp(data->GetClassName(), "vtkUnstructuredGrid") == 0 ||
strcmp(data->GetClassName(), "vtkStructuredGrid") == 0 ||
strcmp(data->GetClassName(), "vtkRectilinearGrid") == 0 ||
strcmp(data->GetClassName(), "vtkStructuredPoints") == 0)
{
return this->WriteDataSet((vtkDataSet*)data);
}
if (strcmp(data->GetClassName(), "vtkImageData") == 0)
{
return this->WriteImageData((vtkImageData*)data);
}
vtkErrorMacro("Cannot marshal object of type "
<< data->GetClassName());
return 0;
}
int vtkCommunicator::ReadObject(vtkDataObject *data)
{
if (strcmp(data->GetClassName(), "vtkPolyData") == 0 ||
strcmp(data->GetClassName(), "vtkUnstructuredGrid") == 0 ||
strcmp(data->GetClassName(), "vtkStructuredGrid") == 0 ||
strcmp(data->GetClassName(), "vtkRectilinearGrid") == 0 ||
strcmp(data->GetClassName(), "vtkStructuredPoints") == 0)
{
return this->ReadDataSet((vtkDataSet*)data);
}
if (strcmp(data->GetClassName(), "vtkImageData") == 0)
{
return this->ReadImageData((vtkImageData*)data);
}
vtkErrorMacro("Cannot marshal object of type "
<< data->GetClassName());
return 1;
}
int vtkCommunicator::WriteImageData(vtkImageData *data)
{
vtkImageClip *clip;
vtkStructuredPointsWriter *writer;
int size;
// keep Update from propagating
vtkImageData *tmp = vtkImageData::New();
tmp->ShallowCopy(data);
clip = vtkImageClip::New();
clip->SetInput(tmp);
clip->SetOutputWholeExtent(data->GetExtent());
writer = vtkStructuredPointsWriter::New();
writer->SetFileTypeToBinary();
writer->WriteToOutputStringOn();
writer->SetInput(clip->GetOutput());
writer->Write();
size = writer->GetOutputStringLength();
this->DeleteAndSetMarshalString(writer->RegisterAndGetOutputString(), size);
this->MarshalDataLength = size;
clip->Delete();
writer->Delete();
tmp->Delete();
return 1;
}
int vtkCommunicator::ReadImageData(vtkImageData *object)
{
vtkStructuredPointsReader *reader = vtkStructuredPointsReader::New();
if (this->MarshalString == NULL || this->MarshalStringLength <= 0)
{
return 0;
}
reader->ReadFromInputStringOn();
vtkCharArray* mystring = vtkCharArray::New();
// mystring should not delete the string when it's done,
// that's our job.
mystring->SetArray(this->MarshalString, this->MarshalDataLength, 1);
reader->SetInputArray(mystring);
mystring->Delete();
reader->GetOutput()->Update();
object->ShallowCopy(reader->GetOutput());
reader->Delete();
return 1;
}
int vtkCommunicator::WriteDataSet(vtkDataSet *data)
{
vtkDataSet *copy;
unsigned long size;
vtkDataSetWriter *writer = vtkDataSetWriter::New();
copy = data->NewInstance();
copy->ShallowCopy(data);
// There is a problem with binary files with no data.
if (copy->GetNumberOfCells() + copy->GetNumberOfPoints() > 0)
{
writer->SetFileTypeToBinary();
}
writer->WriteToOutputStringOn();
writer->SetInput(copy);
writer->Write();
size = writer->GetOutputStringLength();
this->DeleteAndSetMarshalString(writer->RegisterAndGetOutputString(), size);
this->MarshalDataLength = size;
writer->Delete();
copy->Delete();
return 1;
}
int vtkCommunicator::ReadDataSet(vtkDataSet *object)
{
vtkDataSetReader *reader = vtkDataSetReader::New();
if (this->MarshalString == NULL || this->MarshalStringLength <= 0)
{
return 0;
}
reader->ReadFromInputStringOn();
vtkCharArray* mystring = vtkCharArray::New();
// mystring should not delete the string when it's done,
// that's our job.
mystring->SetArray(this->MarshalString, this->MarshalDataLength, 1);
reader->SetInputArray(mystring);
mystring->Delete();
reader->Update();
object->ShallowCopy(reader->GetOutput());
reader->Delete();
return 1;
}