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.
1029 lines
25 KiB
1029 lines
25 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkParticleReader.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 "vtkParticleReader.h"
|
|
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkByteSwap.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPoints.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkFloatArray.h"
|
|
|
|
#include <vtkstd/algorithm>
|
|
#include <vtkstd/vector>
|
|
#include <vtkstd/string>
|
|
|
|
vtkCxxRevisionMacro(vtkParticleReader, "$Revision: 1.28 $");
|
|
vtkStandardNewMacro(vtkParticleReader);
|
|
|
|
namespace {
|
|
// .NAME ParseLine - Read a line of four values of type T filtering out comments.
|
|
// .SECTION Description
|
|
// The ParseLine operator scans a string and returns 0 if it finds a
|
|
// comment symbol. Otherwise it returns 1 and four values corresponding
|
|
// to the position of the particle (x,y,z) and a scalar s asociated with
|
|
// the particle. It is a good idea to set the values of val to some
|
|
// predefined value before calling the operator.
|
|
template < typename T >
|
|
class ParseLine
|
|
{
|
|
public:
|
|
ParseLine (): LookForEndString(false) {};
|
|
int operator () (vtkstd::string &s, T val[4])
|
|
{
|
|
// Skip over comment lines.
|
|
vtkstd::string::iterator itr;
|
|
vtkstd::string tgt("/*");
|
|
itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end());
|
|
if ( itr != s.end() )
|
|
{
|
|
LookForEndString = true;
|
|
//continue;
|
|
}
|
|
if ( LookForEndString )
|
|
{
|
|
tgt = "*/";
|
|
itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end());
|
|
if ( itr != s.end() )
|
|
{
|
|
LookForEndString = false;
|
|
}
|
|
//continue;
|
|
return 0;
|
|
}
|
|
|
|
tgt = "//";
|
|
itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end());
|
|
if ( itr != s.end() )
|
|
{
|
|
return 0;
|
|
}
|
|
tgt = "%";
|
|
itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end());
|
|
if ( itr != s.end() )
|
|
{
|
|
return 0;
|
|
}
|
|
tgt = "#";
|
|
itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end());
|
|
if ( itr != s.end() )
|
|
{
|
|
return 0;
|
|
}
|
|
// If comma delimited, replace with tab
|
|
vtkstd::replace(s.begin(),s.end(),',','\t');
|
|
|
|
// We have data.
|
|
strstream is;
|
|
is << s.c_str() << ends;// no istringstream in VTK
|
|
is >> val[0] >> val[1] >> val[2] >> val[3];
|
|
|
|
return 1;
|
|
}
|
|
|
|
private:
|
|
bool LookForEndString;
|
|
|
|
};
|
|
|
|
// The number of times we output a progress message.
|
|
int const quantum = 20;
|
|
// The ratio of high ASCII characters to low ASCII characeters.
|
|
double hiToLowASCII = 0.1;
|
|
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
vtkParticleReader::vtkParticleReader() :
|
|
FileName(NULL)
|
|
, File(NULL)
|
|
, HasScalar(1)
|
|
, FileType(FILE_TYPE_IS_UNKNOWN)
|
|
, DataType(VTK_FLOAT)
|
|
, Alliquot(0)
|
|
, Count(0)
|
|
, SwapBytes(0)
|
|
, NumberOfPoints(0)
|
|
{
|
|
this->SetNumberOfInputPorts(0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkParticleReader::~vtkParticleReader()
|
|
{
|
|
if (this->File)
|
|
{
|
|
this->File->close();
|
|
delete this->File;
|
|
this->File = NULL;
|
|
}
|
|
|
|
if (this->FileName)
|
|
{
|
|
delete [] this->FileName;
|
|
this->FileName = NULL;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkParticleReader::OpenFile()
|
|
{
|
|
if (!this->FileName)
|
|
{
|
|
vtkErrorMacro(<<"FileName must be specified.");
|
|
return;
|
|
}
|
|
|
|
// If the file was open close it.
|
|
if (this->File)
|
|
{
|
|
this->File->close();
|
|
delete this->File;
|
|
this->File = NULL;
|
|
}
|
|
|
|
// Open the new file.
|
|
vtkDebugMacro(<< "Initialize: opening file " << this->FileName);
|
|
#ifdef _WIN32
|
|
this->File = new ifstream(this->FileName, ios::in | ios::binary);
|
|
#else
|
|
this->File = new ifstream(this->FileName, ios::in);
|
|
#endif
|
|
if (! this->File || this->File->fail())
|
|
{
|
|
vtkErrorMacro(<< "Initialize: Could not open file " <<
|
|
this->FileName);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::RequestInformation(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
|
|
-1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::RequestData(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
if (!this->FileName)
|
|
{
|
|
vtkErrorMacro(<<"FileName must be specified.");
|
|
return 0;
|
|
}
|
|
|
|
this->OpenFile();
|
|
int ft = this->FileType;
|
|
if ( ft == FILE_TYPE_IS_UNKNOWN )
|
|
{
|
|
ft = DetermineFileType();
|
|
if ( ft == FILE_TYPE_IS_UNKNOWN )
|
|
{
|
|
vtkErrorMacro(<< "File type cannot be determined.");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
switch ( ft )
|
|
{
|
|
case FILE_TYPE_IS_TEXT:
|
|
switch ( this->DataType )
|
|
{
|
|
case VTK_FLOAT:
|
|
return ProduceOutputFromTextFileFloat(outputVector);
|
|
break;
|
|
case VTK_DOUBLE:
|
|
return ProduceOutputFromTextFileDouble(outputVector);
|
|
break;
|
|
default:
|
|
{
|
|
vtkErrorMacro(<<"Only float or double data can be processed.");
|
|
return 0;
|
|
}
|
|
}
|
|
case FILE_TYPE_IS_BINARY:
|
|
switch ( this->DataType )
|
|
{
|
|
case VTK_FLOAT:
|
|
return ProduceOutputFromBinaryFileFloat(outputVector);
|
|
break;
|
|
case VTK_DOUBLE:
|
|
return ProduceOutputFromBinaryFileDouble(outputVector);
|
|
break;
|
|
default:
|
|
{
|
|
vtkErrorMacro(<<"Only float or double data can be processed.");
|
|
return 0;
|
|
}
|
|
}
|
|
default:
|
|
{
|
|
vtkErrorMacro(<<"The file type was not able to be determined.");
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::DetermineFileType()
|
|
{
|
|
// This function assumes that the file has been opened.
|
|
|
|
this->File->seekg(0,ios::end);
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro("Could not seek to end of file.");
|
|
return FILE_TYPE_IS_UNKNOWN;
|
|
}
|
|
size_t fileLength = this->File->tellg();
|
|
if ( fileLength == 0 )
|
|
{
|
|
vtkErrorMacro("File is empty.");
|
|
return FILE_TYPE_IS_UNKNOWN;
|
|
}
|
|
|
|
this->File->seekg(0,ios::beg);
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro("Could not seek to start of file.");
|
|
return FILE_TYPE_IS_UNKNOWN;
|
|
}
|
|
|
|
size_t sampleSize = fileLength < 5000 ? fileLength: 5000;
|
|
// cout << "File length: " << fileLength << " Sample size: " << sampleSize << endl;
|
|
vtkstd::vector <unsigned char> s;
|
|
for ( size_t i = 0; i < sampleSize; ++i )
|
|
{
|
|
char c;
|
|
this->File->read(&c,sizeof(char));
|
|
s.push_back(c);
|
|
}
|
|
// If read terminated prematurely then it may have detected
|
|
// a premature EOF character in the data.
|
|
// Assume that the file type is undetermined in this case.
|
|
if ( s.size() != sampleSize )
|
|
{
|
|
// cout << "Premature termination" << endl;
|
|
return FILE_TYPE_IS_UNKNOWN;
|
|
}
|
|
|
|
size_t zero = 0;
|
|
size_t conventionalASCII = 0;
|
|
size_t extendedASCII = 0;
|
|
size_t controlASCII = 0;
|
|
size_t otherASCII = 0;
|
|
for ( size_t j = 0; j < s.size(); ++j )
|
|
{
|
|
if ( s[j] == '\0' )
|
|
{
|
|
zero++;
|
|
continue;
|
|
}
|
|
// Conventional ASCII characters.
|
|
if ( s[j] > 0x1f && s[j] < 0x80 )
|
|
{
|
|
conventionalASCII++;
|
|
continue;
|
|
}
|
|
// Extended ASCII characters may have been used.
|
|
if ( s[j] > 0x7f )
|
|
{
|
|
extendedASCII++;
|
|
continue;
|
|
}
|
|
// Control characters.
|
|
if ( s[j] == '\n' || s[j] == '\r' || s[j] == '\t' || s[j] == '\f' )
|
|
{
|
|
controlASCII++;
|
|
continue;
|
|
}
|
|
otherASCII++;
|
|
}
|
|
|
|
// NULL shouldn't ever appear in a text file.
|
|
if ( zero != 0 || otherASCII > 0 || conventionalASCII == 0 )
|
|
{
|
|
return FILE_TYPE_IS_BINARY;
|
|
}
|
|
if ( (double)extendedASCII / (double) conventionalASCII < hiToLowASCII )
|
|
{
|
|
return FILE_TYPE_IS_TEXT;
|
|
}
|
|
|
|
return FILE_TYPE_IS_BINARY;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::ProduceOutputFromTextFileDouble(vtkInformationVector *outputVector)
|
|
{
|
|
// Get the size of the file.
|
|
this->File->seekg(0,ios::end);
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro("Could not seek to end of file.");
|
|
return 0;
|
|
}
|
|
|
|
size_t fileLength = (unsigned long)this->File->tellg();
|
|
size_t bytesRead = 0;
|
|
|
|
vtkstd::string s;
|
|
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
points->SetDataTypeToDouble();
|
|
points->Reset();
|
|
|
|
vtkSmartPointer<vtkDoubleArray> scalars = vtkSmartPointer<vtkDoubleArray>::New();
|
|
scalars->Reset();
|
|
scalars->SetName("Scalar");
|
|
|
|
this->File->seekg(0,ios::beg);
|
|
|
|
this->Alliquot = fileLength / quantum;
|
|
this->Count = 1;
|
|
ParseLine<double> pl;
|
|
char buffer[256];
|
|
while ( this->File->getline(buffer,256,'\n') )
|
|
{
|
|
s = buffer;
|
|
if ( s.size() != 0 )
|
|
{
|
|
bytesRead += s.size();
|
|
this->DoProgressUpdate( bytesRead, fileLength );
|
|
double val[4];
|
|
val[0]=val[1]=val[2]=val[3]=0;
|
|
if ( pl(s,val) )
|
|
{
|
|
points->InsertNextPoint(val[0], val[1], val[2]);
|
|
if ( this->HasScalar)
|
|
{
|
|
scalars->InsertNextValue(val[3]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New();
|
|
vertices->Reset();
|
|
|
|
this->NumberOfPoints = points->GetNumberOfPoints();
|
|
for( vtkIdType j = 0; j < (vtkIdType)this->NumberOfPoints; ++j )
|
|
{
|
|
vertices->InsertNextCell( 1 );
|
|
vertices->InsertCellPoint( j );
|
|
}
|
|
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
// get the ouptut
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
output->SetPoints(points);
|
|
output->SetVerts(vertices);
|
|
if ( this->HasScalar )
|
|
output->GetPointData()->SetScalars(scalars);
|
|
|
|
output->Modified();
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::ProduceOutputFromTextFileFloat(vtkInformationVector *outputVector)
|
|
{
|
|
// Get the size of the file.
|
|
this->File->seekg(0,ios::end);
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro("Could not seek to end of file.");
|
|
return 0;
|
|
}
|
|
|
|
size_t fileLength = (unsigned long)this->File->tellg();
|
|
size_t bytesRead = 0;
|
|
|
|
vtkstd::string s;
|
|
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
points->SetDataTypeToFloat();
|
|
points->Reset();
|
|
|
|
vtkSmartPointer<vtkFloatArray> scalars = vtkSmartPointer<vtkFloatArray>::New();
|
|
scalars->Reset();
|
|
scalars->SetName("Scalar");
|
|
|
|
this->File->seekg(0,ios::beg);
|
|
|
|
this->Alliquot = fileLength / quantum;
|
|
this->Count = 1;
|
|
ParseLine<float> pl;
|
|
char buffer[256];
|
|
while ( this->File->getline(buffer,256,'\n') )
|
|
{
|
|
s = buffer;
|
|
if ( s.size() != 0 )
|
|
{
|
|
bytesRead += s.size();
|
|
this->DoProgressUpdate( bytesRead, fileLength );
|
|
|
|
float val[4];
|
|
val[0]=val[1]=val[2]=val[3]=0;
|
|
if ( pl(s,val) )
|
|
{
|
|
points->InsertNextPoint(val[0], val[1], val[2]);
|
|
if ( this->HasScalar)
|
|
{
|
|
scalars->InsertNextValue(val[3]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New();
|
|
vertices->Reset();
|
|
|
|
this->NumberOfPoints = points->GetNumberOfPoints();
|
|
for( vtkIdType j = 0; j < (vtkIdType)this->NumberOfPoints; ++j )
|
|
{
|
|
vertices->InsertNextCell( 1 );
|
|
vertices->InsertCellPoint( j );
|
|
}
|
|
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
// get the ouptut
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
output->SetPoints(points);
|
|
output->SetVerts(vertices);
|
|
if ( this->HasScalar )
|
|
{
|
|
output->GetPointData()->SetScalars(scalars);
|
|
}
|
|
|
|
output->Modified();
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::ProduceOutputFromBinaryFileDouble(vtkInformationVector *outputVector)
|
|
{
|
|
|
|
unsigned long fileLength, start, next, length, ptIdx, cellPtIdx;
|
|
unsigned long cellLength;
|
|
int piece, numPieces;
|
|
double *data, *ptr;
|
|
|
|
if (!this->FileName)
|
|
{
|
|
vtkErrorMacro(<<"FileName must be specified.");
|
|
return 0;
|
|
}
|
|
|
|
this->OpenFile();
|
|
|
|
// Get the size of the header from the size of the image
|
|
this->File->seekg(0,ios::end);
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro("Could not seek to end of file.");
|
|
return 0;
|
|
}
|
|
|
|
fileLength = (unsigned long)this->File->tellg();
|
|
if ( this->HasScalar )
|
|
{
|
|
this->NumberOfPoints = fileLength / (4 * sizeof(double));
|
|
}
|
|
else
|
|
{
|
|
this->NumberOfPoints = fileLength / (3 * sizeof(double));
|
|
}
|
|
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
piece =
|
|
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
|
|
numPieces =
|
|
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
|
|
|
|
if ((unsigned long)numPieces > this->NumberOfPoints)
|
|
{
|
|
numPieces = (int)(this->NumberOfPoints);
|
|
}
|
|
if (numPieces <= 0 || piece < 0 || piece >= numPieces)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
start = piece * this->NumberOfPoints / numPieces;
|
|
next = (piece+1) * this->NumberOfPoints / numPieces;
|
|
|
|
length = next - start;
|
|
|
|
if ( this->HasScalar )
|
|
{
|
|
data = new double[length * 4];
|
|
}
|
|
else
|
|
{
|
|
data = new double[length * 3];
|
|
}
|
|
|
|
// Seek to the first point in the file.
|
|
if ( this->HasScalar )
|
|
{
|
|
this->File->seekg(start*4*sizeof(double), ios::beg);
|
|
}
|
|
else
|
|
{
|
|
this->File->seekg(start*3*sizeof(double), ios::beg);
|
|
}
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro(<< "File operation failed: Seeking to " << start*4);
|
|
delete [] data;
|
|
return 0;
|
|
}
|
|
|
|
// Read the data.
|
|
if ( this->HasScalar )
|
|
{
|
|
this->File->read((char *)data, length*4*sizeof(double));
|
|
if ( static_cast<unsigned long>(this->File->gcount()) !=
|
|
static_cast<unsigned long>(length*4*sizeof(double))
|
|
// On apple read to eof returns fail
|
|
#ifndef __APPLE_CC__
|
|
|| this->File->fail()
|
|
#endif // __APPLE_CC__
|
|
)
|
|
{
|
|
vtkErrorMacro("Could not read points: " << start
|
|
<< " to " << next-1);
|
|
delete [] data;
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->File->read((char *)data, length*3*sizeof(double));
|
|
if ( static_cast<unsigned long>(this->File->gcount()) !=
|
|
static_cast<unsigned long>(length*3*sizeof(double))
|
|
// On apple read to eof returns fail
|
|
#ifndef __APPLE_CC__
|
|
|| this->File->fail()
|
|
#endif // __APPLE_CC__
|
|
)
|
|
{
|
|
vtkErrorMacro("Could not read points: " << start
|
|
<< " to " << next-1);
|
|
delete [] data;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Swap bytes if necessary.
|
|
if (this->GetSwapBytes())
|
|
{
|
|
if ( this->HasScalar )
|
|
{
|
|
vtkByteSwap::SwapVoidRange(data, length*4, sizeof(double));
|
|
}
|
|
else
|
|
{
|
|
vtkByteSwap::SwapVoidRange(data, length*3, sizeof(double));
|
|
}
|
|
}
|
|
|
|
this->UpdateProgress(0.5);
|
|
|
|
ptr = data;
|
|
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
points->SetNumberOfPoints(length);
|
|
vtkSmartPointer<vtkFloatArray> array = vtkSmartPointer<vtkFloatArray>::New();
|
|
array->SetName("Scalar");
|
|
vtkSmartPointer<vtkCellArray> verts = vtkSmartPointer<vtkCellArray>::New();
|
|
|
|
// Each cell will have 1000 points. Leave a little extra space just in case.
|
|
// We break up the cell this way so that the render will check for aborts
|
|
// at a reasonable rate.
|
|
verts->Allocate((int)((float)length * 1.002));
|
|
// Keep adding cells until we run out of points.
|
|
ptIdx = 0;
|
|
int cnt = 1;
|
|
double len = length;
|
|
while (length > 0)
|
|
{
|
|
if ( cnt % 10 == 0 )
|
|
{
|
|
this->UpdateProgress(0.5+((cnt * 1000.0)/len)/2.0);
|
|
}
|
|
cnt++;
|
|
cellLength = 1000;
|
|
if (cellLength > length)
|
|
{
|
|
cellLength = length;
|
|
}
|
|
length = length - cellLength;
|
|
verts->InsertNextCell((int)cellLength);
|
|
for (cellPtIdx = 0; cellPtIdx < cellLength; ++cellPtIdx)
|
|
{
|
|
points->SetPoint(ptIdx, ptr[0], ptr[1], ptr[2]);
|
|
if ( this->HasScalar )
|
|
{
|
|
array->InsertNextValue(ptr[3]);
|
|
ptr += 4;
|
|
}
|
|
else
|
|
{
|
|
ptr += 3;
|
|
}
|
|
verts->InsertCellPoint(ptIdx);
|
|
++ptIdx;
|
|
}
|
|
}
|
|
delete [] data;
|
|
|
|
// get the ouptut
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
output->SetPoints(points);
|
|
output->SetVerts(verts);
|
|
if ( this->HasScalar )
|
|
{
|
|
output->GetPointData()->SetScalars(array);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::ProduceOutputFromBinaryFileFloat(vtkInformationVector *outputVector)
|
|
{
|
|
|
|
unsigned long fileLength, start, next, length, ptIdx, cellPtIdx;
|
|
unsigned long cellLength;
|
|
int piece, numPieces;
|
|
float *data, *ptr;
|
|
|
|
if (!this->FileName)
|
|
{
|
|
vtkErrorMacro(<<"FileName must be specified.");
|
|
return 0;
|
|
}
|
|
|
|
this->OpenFile();
|
|
|
|
// Get the size of the header from the size of the image
|
|
this->File->seekg(0,ios::end);
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro("Could not seek to end of file.");
|
|
return 0;
|
|
}
|
|
|
|
fileLength = (unsigned long)this->File->tellg();
|
|
if ( this->HasScalar )
|
|
{
|
|
this->NumberOfPoints = fileLength / (4 * sizeof(float));
|
|
}
|
|
else
|
|
{
|
|
this->NumberOfPoints = fileLength / (3 * sizeof(float));
|
|
}
|
|
|
|
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
piece =
|
|
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
|
|
numPieces =
|
|
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
|
|
|
|
if ((unsigned long)numPieces > this->NumberOfPoints)
|
|
{
|
|
numPieces = (int)(this->NumberOfPoints);
|
|
}
|
|
if (numPieces <= 0 || piece < 0 || piece >= numPieces)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
start = piece * this->NumberOfPoints / numPieces;
|
|
next = (piece+1) * this->NumberOfPoints / numPieces;
|
|
|
|
length = next - start;
|
|
|
|
if ( this->HasScalar )
|
|
{
|
|
data = new float[length * 4];
|
|
}
|
|
else
|
|
{
|
|
data = new float[length * 3];
|
|
}
|
|
|
|
|
|
// Seek to the first point in the file.
|
|
if ( this->HasScalar )
|
|
{
|
|
this->File->seekg(start*4*sizeof(float), ios::beg);
|
|
}
|
|
else
|
|
{
|
|
this->File->seekg(start*3*sizeof(float), ios::beg);
|
|
}
|
|
if (this->File->fail())
|
|
{
|
|
vtkErrorMacro(<< "File operation failed: Seeking to " << start*4);
|
|
delete [] data;
|
|
return 0;
|
|
}
|
|
|
|
// Read the data.
|
|
if ( this->HasScalar )
|
|
{
|
|
this->File->read((char *)data, length*4*sizeof(float));
|
|
if ( static_cast<unsigned long>(this->File->gcount()) !=
|
|
static_cast<unsigned long>(length*4*sizeof(float))
|
|
// On apple read to eof returns fail
|
|
#ifndef __APPLE_CC__
|
|
|| this->File->fail()
|
|
#endif // __APPLE_CC__
|
|
)
|
|
{
|
|
vtkErrorMacro("Could not read points: " << start
|
|
<< " to " << next-1);
|
|
delete [] data;
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->File->read((char *)data, length*3*sizeof(float));
|
|
if ( static_cast<unsigned long>(this->File->gcount()) !=
|
|
static_cast<unsigned long>(length*3*sizeof(float))
|
|
// On apple read to eof returns fail
|
|
#ifndef __APPLE_CC__
|
|
|| this->File->fail()
|
|
#endif // __APPLE_CC__
|
|
)
|
|
{
|
|
vtkErrorMacro("Could not read points: " << start
|
|
<< " to " << next-1);
|
|
delete [] data;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Swap bytes if necessary.
|
|
if (this->GetSwapBytes())
|
|
{
|
|
if ( this->HasScalar )
|
|
{
|
|
vtkByteSwap::SwapVoidRange(data, length*4, sizeof(float));
|
|
}
|
|
else
|
|
{
|
|
vtkByteSwap::SwapVoidRange(data, length*3, sizeof(float));
|
|
}
|
|
}
|
|
|
|
this->UpdateProgress(0.5);
|
|
|
|
ptr = data;
|
|
|
|
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
|
|
points->SetNumberOfPoints(length);
|
|
vtkSmartPointer<vtkFloatArray> array = vtkSmartPointer<vtkFloatArray>::New();
|
|
array->SetName("Scalar");
|
|
vtkSmartPointer<vtkCellArray> verts = vtkSmartPointer<vtkCellArray>::New();
|
|
|
|
// Each cell will have 1000 points. Leave a little extra space just in case.
|
|
// We break up the cell this way so that the render will check for aborts
|
|
// at a reasonable rate.
|
|
verts->Allocate((int)((float)length * 1.002));
|
|
// Keep adding cells until we run out of points.
|
|
ptIdx = 0;
|
|
int cnt = 1;
|
|
double len = length;
|
|
while (length > 0)
|
|
{
|
|
if ( cnt % 10 == 0 )
|
|
{
|
|
this->UpdateProgress(0.5+((cnt * 1000.0)/len)/2.0);
|
|
}
|
|
cnt++;
|
|
cellLength = 1000;
|
|
if (cellLength > length)
|
|
{
|
|
cellLength = length;
|
|
}
|
|
length = length - cellLength;
|
|
verts->InsertNextCell((int)cellLength);
|
|
for (cellPtIdx = 0; cellPtIdx < cellLength; ++cellPtIdx)
|
|
{
|
|
points->SetPoint(ptIdx, ptr[0], ptr[1], ptr[2]);
|
|
if ( this->HasScalar )
|
|
{
|
|
array->InsertNextValue(ptr[3]);
|
|
ptr += 4;
|
|
}
|
|
else
|
|
{
|
|
ptr += 3;
|
|
}
|
|
verts->InsertCellPoint(ptIdx);
|
|
++ptIdx;
|
|
}
|
|
}
|
|
delete [] data;
|
|
|
|
// get the ouptut
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
output->SetPoints(points);
|
|
output->SetVerts(verts);
|
|
if ( this->HasScalar )
|
|
{
|
|
output->GetPointData()->SetScalars(array);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkParticleReader::DoProgressUpdate( size_t & bytesRead, size_t & fileLength )
|
|
{
|
|
if ( bytesRead > this->Alliquot )
|
|
{
|
|
this->UpdateProgress( bytesRead/(double)fileLength );
|
|
this->Count++;
|
|
this->Alliquot = fileLength / quantum * this->Count;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkParticleReader::SetDataByteOrderToBigEndian()
|
|
{
|
|
#ifndef VTK_WORDS_BIGENDIAN
|
|
this->SwapBytesOn();
|
|
#else
|
|
this->SwapBytesOff();
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkParticleReader::SetDataByteOrderToLittleEndian()
|
|
{
|
|
#ifdef VTK_WORDS_BIGENDIAN
|
|
this->SwapBytesOn();
|
|
#else
|
|
this->SwapBytesOff();
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkParticleReader::SetDataByteOrder(int byteOrder)
|
|
{
|
|
if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN )
|
|
{
|
|
this->SetDataByteOrderToBigEndian();
|
|
}
|
|
else
|
|
{
|
|
this->SetDataByteOrderToLittleEndian();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkParticleReader::GetDataByteOrder()
|
|
{
|
|
#ifdef VTK_WORDS_BIGENDIAN
|
|
if ( this->SwapBytes )
|
|
{
|
|
return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN;
|
|
}
|
|
else
|
|
{
|
|
return VTK_FILE_BYTE_ORDER_BIG_ENDIAN;
|
|
}
|
|
#else
|
|
if ( this->SwapBytes )
|
|
{
|
|
return VTK_FILE_BYTE_ORDER_BIG_ENDIAN;
|
|
}
|
|
else
|
|
{
|
|
return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const char *vtkParticleReader::GetDataByteOrderAsString()
|
|
{
|
|
#ifdef VTK_WORDS_BIGENDIAN
|
|
if ( this->SwapBytes )
|
|
{
|
|
return "LittleEndian";
|
|
}
|
|
else
|
|
{
|
|
return "BigEndian";
|
|
}
|
|
#else
|
|
if ( this->SwapBytes )
|
|
{
|
|
return "BigEndian";
|
|
}
|
|
else
|
|
{
|
|
return "LittleEndian";
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkParticleReader::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "FileName: " <<
|
|
(this->FileName ? this->FileName : "(none)") << "\n";
|
|
os << indent << "Swap Bytes: " << (this->SwapBytes ? "On\n" : "Off\n");
|
|
os << indent << "Has Scalar: " << (this->HasScalar ? "On\n" : "Off\n");
|
|
switch ( this->FileType )
|
|
{
|
|
case FILE_TYPE_IS_UNKNOWN:
|
|
os << indent << "File type is unknown (The class automatically determines the file type).\n";
|
|
break;
|
|
case FILE_TYPE_IS_TEXT:
|
|
os << indent << "File type is text.\n";
|
|
break;
|
|
case FILE_TYPE_IS_BINARY:
|
|
os << indent << "File type is binary.\n";
|
|
break;
|
|
default:
|
|
os << indent << "File type should never have this value: " << this->FileType << "\n";
|
|
break;
|
|
}
|
|
switch ( this->DataType )
|
|
{
|
|
case VTK_FLOAT:
|
|
os << indent << "Data type is float.\n";
|
|
break;
|
|
case VTK_DOUBLE:
|
|
os << indent << "Data type is double.\n";
|
|
break;
|
|
default:
|
|
os << indent << "Data type should never have this value: " << this->DataType << "\n";
|
|
break;
|
|
}
|
|
os << indent << "NumberOfPoints: " << this->NumberOfPoints << "\n";
|
|
os << indent << "Alliquot: " << (unsigned int)this->Alliquot << "\n";
|
|
os << indent << "Count: " << (unsigned int)this->Count << "\n";
|
|
|
|
}
|
|
|