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.

391 lines
11 KiB

2 years ago
/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkFacetReader.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 "vtkFacetReader.h"
#include "vtkPolyData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkErrorCode.h"
#include "vtkCellType.h"
#include "vtkCellArray.h"
#include "vtkGarbageCollector.h"
#include "vtkAppendPolyData.h"
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkUnsignedIntArray.h"
#include "vtkDoubleArray.h"
#include "vtkSmartPointer.h"
#include <sys/stat.h>
#include <vtkstd/string>
#include <vtkstd/vector>
vtkCxxRevisionMacro(vtkFacetReader, "$Revision: 1.3 $");
vtkStandardNewMacro(vtkFacetReader);
//------------------------------------------------------------------------------
// Due to a buggy stream library on the HP and another on Mac OSX, we
// need this very carefully written version of getline. Returns true
// if any data were read before the end-of-file was reached.
//
static bool GetLineFromStream(istream& is,
vtkstd::string& line, bool *has_newline = 0)
{
const int bufferSize = 1024;
char buffer[bufferSize];
line = "";
bool haveData = false;
if ( has_newline )
{
*has_newline = false;
}
// If no characters are read from the stream, the end of file has
// been reached.
while((is.getline(buffer, bufferSize), is.gcount() > 0))
{
haveData = true;
line.append(buffer);
// If newline character was read, the gcount includes the
// character, but the buffer does not. The end of line has been
// reached.
if(strlen(buffer) < static_cast<size_t>(is.gcount()))
{
if ( has_newline )
{
*has_newline = true;
}
break;
}
// The fail bit may be set. Clear it.
is.clear(is.rdstate() & ~ios::failbit);
}
return haveData;
}
//----------------------------------------------------------------------------
vtkFacetReader::vtkFacetReader()
{
this->FileName = NULL;
this->SetNumberOfInputPorts(0);
}
//----------------------------------------------------------------------------
vtkFacetReader::~vtkFacetReader()
{
if (this->FileName)
{
delete [] this->FileName;
}
}
//----------------------------------------------------------------------------
int vtkFacetReader::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *outputVector)
{
// get the info object
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the ouptut
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
if ( !this->FileName )
{
vtkErrorMacro("No filename specified");
return 1;
}
struct stat fs;
if ( stat(this->FileName, &fs) )
{
this->SetErrorCode(vtkErrorCode::FileNotFoundError);
vtkErrorMacro("Specified filename not found");
return 1;
}
ifstream ifs(this->FileName, ios::in);
if (!ifs)
{
this->SetErrorCode(vtkErrorCode::FileNotFoundError);
vtkErrorMacro("Specified filename not found");
return 1;
}
vtkDebugMacro( << "Reading Facet file");
vtkstd::string line;
// Read first row
if ( !GetLineFromStream(ifs, line) )
{
vtkErrorMacro("Cannot read file comment");
return 1;
}
// Read number of parts
int num_parts = 0;
if ( !GetLineFromStream(ifs, line) ||
sscanf(line.c_str(), "%d", &num_parts) != 1 ||
num_parts < 0 )
{
vtkErrorMacro("Bad number of parts line");
return 1;
}
vtkDebugMacro("Number of parts is: " << num_parts);
// Buffers for various information from file
vtkstd::vector<vtkIdType> pointList;
vtkstd::vector<char> stringBuffer;
// We will need append individual parts together. Once multiblock is
// supported, this should go out.
vtkSmartPointer<vtkAppendPolyData> appendPtr = vtkSmartPointer<vtkAppendPolyData>::New();
// Block garbage collection so that appends will not take too long.
vtkGarbageCollector::DeferredCollectionPush();
int part;
int error = 0;
// Loop thrugh individual parts
for ( part = 0; part < num_parts || error; part ++ )
{
vtkstd::string partName;
vtkDebugMacro("Reading part: " << part);
// Read part name
if ( !GetLineFromStream(ifs, partName) )
{
vtkErrorMacro("Cannot read part name");
error = 1;
break;
}
vtkDebugMacro("Part name: " << partName.c_str());
// Read cell/point index and geometry information including the number of
// points. cell/point index for points is always 0
int cell_point_index = -1;
int numpts = -1, tmp;
if ( !GetLineFromStream(ifs, line) ||
sscanf(line.c_str(), "%d", &cell_point_index) != 1 ||
cell_point_index != 0 ||
!GetLineFromStream(ifs, line) ||
sscanf(line.c_str(), "%d %d %d", &numpts, &tmp, &tmp) != 3 ||
numpts < 0 )
{
vtkErrorMacro("Problem reading number of points");
error = 1;
break;
}
vtkIdType num_points = numpts;
vtkIdType point;
vtkSmartPointer<vtkPoints> myPointsPtr = vtkSmartPointer<vtkPoints>::New();
// Read individual points
for ( point = 0; point < num_points; point ++ )
{
// Read point
double x = 0, y = 0, z = 0;
if ( !GetLineFromStream(ifs, line) ||
sscanf(line.c_str(), "%lf %lf %lf", &x, &y, &z) != 3 )
{
vtkErrorMacro("Problem reading point: " << point);
error = 1;
break;
}
myPointsPtr->InsertNextPoint(x, y, z);
}
if ( error )
{
break;
}
// Read cell point index
if ( !GetLineFromStream(ifs, line) ||
sscanf(line.c_str(), "%d", &cell_point_index) != 1 ||
cell_point_index != 1 )
{
vtkErrorMacro("Cannot read cell/point index or it is not 1");
error = 1;
break;
}
// Read part name
if ( !GetLineFromStream(ifs, line) ||
partName != line )
{
vtkErrorMacro("Cannot read part name or the part name does not match");
error = 1;
break;
}
// Read topology information
int numcells = -1, numpointpercell = -1;
if ( !GetLineFromStream(ifs, line) ||
sscanf(line.c_str(), "%d %d", &numcells, &numpointpercell) != 2 ||
numcells < 0 || numpointpercell < 0 )
{
vtkErrorMacro("Problem reading number of cells and points per cell");
error = 1;
break;
}
vtkIdType num_cells = numcells;
vtkIdType num_points_per_cell = numpointpercell;
if ( pointList.size() < static_cast<size_t>(num_points_per_cell) )
{
pointList.resize(num_points_per_cell);
}
// We need arrays to store material and part number
vtkSmartPointer<vtkUnsignedIntArray> materialArrayPtr = vtkSmartPointer<vtkUnsignedIntArray>::New();
materialArrayPtr->SetName("Material");
materialArrayPtr->SetNumberOfComponents(1);
materialArrayPtr->SetNumberOfTuples(num_cells);
vtkSmartPointer<vtkUnsignedIntArray> relativePartArrayPtr = vtkSmartPointer<vtkUnsignedIntArray>::New();
relativePartArrayPtr->SetName("RelativePartNumber");
relativePartArrayPtr->SetNumberOfComponents(1);
relativePartArrayPtr->SetNumberOfTuples(num_cells);
vtkSmartPointer<vtkCellArray> myCellsPtr = vtkSmartPointer<vtkCellArray>::New();
// Read cells
vtkIdType cell;
for ( cell = 0; cell < num_cells; cell ++ )
{
// Read cell
if ( !GetLineFromStream(ifs, line) )
{
vtkErrorMacro("Cannot read cell: " << cell);
error = 1;
break;
}
// Read specified number of points from cell information
if ( stringBuffer.size() < line.size()+1 )
{
stringBuffer.resize(line.size()+1);
}
char* strPtr = &(*stringBuffer.begin());
strcpy(strPtr, line.c_str());
istrstream lineStream(strPtr);
vtkIdType kk;
int material = -1, relativePartNumber = -1;
for ( kk = 0; kk < num_points_per_cell; kk ++ )
{
int val;
if ( !(lineStream >> val) )
{
vtkErrorMacro("Cannot extract cell points for cell: " << cell);
error = 1;
break;
}
// point indices start with 0, while cell descriptions have point
// indices starting with 1
pointList[kk] = val -1;
}
// Extract material and part number
if ( !(lineStream >> material >> relativePartNumber) )
{
vtkErrorMacro("Cannot extract cell material and part for cell: "
<< cell);
error = 1;
break;
}
materialArrayPtr->SetTuple1(cell, material);
relativePartArrayPtr->SetTuple1(cell, relativePartNumber);
myCellsPtr->InsertNextCell(num_points_per_cell, &(*pointList.begin()));
}
if ( error )
{
break;
}
vtkIdType cc;
// Create another array with absolute part number
vtkUnsignedIntArray* partNumberArray = vtkUnsignedIntArray::New();
partNumberArray->SetName("PartNumber");
partNumberArray->SetNumberOfComponents(1);
partNumberArray->SetNumberOfTuples(num_cells);
for ( cc = 0; cc < partNumberArray->GetNumberOfTuples(); cc ++ )
{
partNumberArray->SetTuple1(cc, part);
}
// Create part and store it
vtkPolyData* partGrid = vtkPolyData::New();
switch ( num_points_per_cell )
{
case 1:
partGrid->SetVerts(myCellsPtr);
break;
case 2:
partGrid->SetLines(myCellsPtr);
break;
case 3:
partGrid->SetPolys(myCellsPtr);
break;
default:
partGrid->SetPolys(myCellsPtr);
break;
}
partGrid->SetPoints(myPointsPtr);
partGrid->GetCellData()->AddArray(partNumberArray);
partGrid->GetCellData()->AddArray(materialArrayPtr);
partGrid->GetCellData()->AddArray(relativePartArrayPtr);
partGrid->GetCellData()->SetScalars(materialArrayPtr);
appendPtr->AddInput(partGrid);
partNumberArray->Delete();
partGrid->Delete();
}
if ( !error )
{
// If everything ok, use append.
appendPtr->Update();
output->ShallowCopy(appendPtr->GetOutput());
}
// Release garbage collection
vtkGarbageCollector::DeferredCollectionPop();
vtkDebugMacro("Done reading file: " << this->FileName);
return 1;
}
//----------------------------------------------------------------------------
void vtkFacetReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "File Name: "
<< (this->FileName ? this->FileName : "(none)") << "\n";
}