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.
 
 
 
 
 
 

429 lines
9.8 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkMCubesReader.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 "vtkMCubesReader.h"
#include "vtkByteSwap.h"
#include "vtkCellArray.h"
#include "vtkFloatArray.h"
#include "vtkMergePoints.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include <sys/types.h>
#include <sys/stat.h>
vtkCxxRevisionMacro(vtkMCubesReader, "$Revision: 1.65 $");
vtkStandardNewMacro(vtkMCubesReader);
// Construct object with FlipNormals turned off and Normals set to true.
vtkMCubesReader::vtkMCubesReader()
{
this->FileName = NULL;
this->LimitsFileName = NULL;
this->Locator = NULL;
#ifndef VTK_WORDS_BIGENDIAN
this->SwapBytes = 1;
#else
this->SwapBytes = 0;
#endif
this->HeaderSize = 0;
this->FlipNormals = 0;
this->Normals = 1;
this->SetNumberOfInputPorts(0);
}
vtkMCubesReader::~vtkMCubesReader()
{
if (this->FileName)
{
delete [] this->FileName;
}
if (this->LimitsFileName)
{
delete [] this->LimitsFileName;
}
if ( this->Locator )
{
this->Locator->UnRegister(this);
this->Locator = NULL;
}
}
int vtkMCubesReader::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()));
FILE *fp;
FILE *limitp;
vtkPoints *newPts;
vtkCellArray *newPolys;
vtkFloatArray *newNormals = NULL;
double bounds[6];
int i, j, k, numPts, numTris;
typedef struct {float x[3], n[3];} pointType;
pointType point;
struct stat buf;
int numDegenerate=0;
vtkIdType nodes[3];
float direction, n[3], dummy[2];
int byteOrder = this->GetDataByteOrder();
vtkDebugMacro(<<"Reading marching cubes file");
//
// Initialize
//
if ( this->FileName == NULL )
{
vtkErrorMacro(<< "Please specify input FileName");
return 0;
}
if ( (fp = fopen(this->FileName, "rb")) == NULL)
{
vtkErrorMacro(<< "File " << this->FileName << " not found");
return 0;
}
// Try to read limits file to get bounds. Otherwise, read data.
if ( this->LimitsFileName != NULL &&
(limitp = fopen (this->LimitsFileName, "rb")) != NULL &&
stat (this->FileName, &buf) == 0 )
{
// skip first three pairs
float fbounds[6];
fread (dummy, sizeof(float), 2, limitp);
fread (dummy, sizeof(float), 2, limitp);
fread (dummy, sizeof(float), 2, limitp);
// next three pairs are x, y, z limits
for (i = 0; i < 6; i++)
{
fread (&fbounds[i], sizeof (float), 1, limitp);
}
// do swapping if necc
if (byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN)
{
vtkByteSwap::Swap4BERange(fbounds,6);
}
else
{
vtkByteSwap::Swap4LERange(fbounds,6);
}
fclose (limitp);
bounds[0] = fbounds[0];
bounds[1] = fbounds[1];
bounds[2] = fbounds[2];
bounds[3] = fbounds[3];
bounds[4] = fbounds[4];
bounds[5] = fbounds[5];
// calculate the number of triangles and vertices from file size
numTris = buf.st_size / (18*sizeof(float)); //3 points + normals
numPts = numTris * 3;
}
else // read data to get bounds
{
fseek (fp, this->HeaderSize, 0);
// cannot use vtkMath uninitialze bounds for this computation
bounds[0] = bounds[2] = bounds[4] = VTK_FLOAT_MAX;
bounds[1] = bounds[3] = bounds[5] = -VTK_FLOAT_MAX;
for (i=0; fread(&point, sizeof(pointType), 1, fp); i++)
{
// swap bytes if necc
if (byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN)
{
vtkByteSwap::Swap4BERange((float *) (&point),6);
}
else
{
vtkByteSwap::Swap4LERange((float *) (&point),6);
}
for (j=0; j<3; j++)
{
bounds[2*j] = (bounds[2*j] < point.x[j] ? bounds[2*j] : point.x[j]);
bounds[2*j+1] = (bounds[2*j+1] > point.x[j] ? bounds[2*j+1] : point.x[j]);
}
if ( i && ((i % 10000) == 0) )
{
vtkDebugMacro(<<"Triangle vertices #" << i);
}
}
numTris = i / 3;
numPts = i;
}
//
// Now re-read and merge
//
rewind (fp);
fseek (fp, this->HeaderSize, 0);
newPts = vtkPoints::New();
newPts->Allocate(numPts/3,numPts/3);
newPolys = vtkCellArray::New();
newPolys->Allocate(newPolys->EstimateSize(numTris,3));
if ( this->Normals )
{
newNormals = vtkFloatArray::New();
newNormals->SetNumberOfComponents(3);
newNormals->Allocate(numPts,numPts);
}
if ( this->Locator == NULL )
{
this->CreateDefaultLocator();
}
this->Locator->InitPointInsertion (newPts, bounds);
direction = this->FlipNormals ? -1.0 : 1.0;
double dp[3];
for ( i=0; i<numTris; i++)
{
for (j=0; j<3; j++)
{
int val;
val = static_cast<int>(
fread (&point, static_cast<int>(sizeof(pointType)), 1, fp));
if (val != 1)
{
vtkErrorMacro(<<"Error reading triange " << i
<< " (" << numTris << "), point/normal " << j);
}
// swap bytes if necc
if (byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN)
{
vtkByteSwap::Swap4BERange((float *) (&point),6);
}
else
{
vtkByteSwap::Swap4LERange((float *) (&point),6);
}
dp[0] = point.x[0];
dp[1] = point.x[1];
dp[2] = point.x[2];
if ( this->Locator->InsertUniquePoint(dp, nodes[j]) )
{
if ( this->Normals )
{
for (k=0; k<3; k++)
{
n[k] = point.n[k] * direction;
}
newNormals->InsertTuple(nodes[j],n);
}
}
}
if ( nodes[0] != nodes[1] &&
nodes[0] != nodes[2] &&
nodes[1] != nodes[2] )
{
newPolys->InsertNextCell(3,nodes);
}
else
{
numDegenerate++;
}
}
vtkDebugMacro(<< "Read: "
<< newPts->GetNumberOfPoints() << " points, "
<< newPolys->GetNumberOfCells() << " triangles\n"
<< "(Removed " << numDegenerate << " degenerate triangles)");
fclose(fp);
//
// Update ourselves
//
output->SetPoints(newPts);
newPts->Delete();
output->SetPolys(newPolys);
newPolys->Delete();
if (this->Normals)
{
output->GetPointData()->SetNormals(newNormals);
newNormals->Delete();
}
output->Squeeze(); // might have merged stuff
if (this->Locator)
{
this->Locator->Initialize(); //free storage
}
return 1;
}
// Specify a spatial locator for merging points. By default,
// an instance of vtkMergePoints is used.
void vtkMCubesReader::SetLocator(vtkPointLocator *locator)
{
if ( this->Locator == locator )
{
return;
}
if ( this->Locator )
{
this->Locator->UnRegister(this);
this->Locator = NULL;
}
if ( locator )
{
locator->Register(this);
}
this->Locator = locator;
this->Modified();
}
void vtkMCubesReader::SetDataByteOrderToBigEndian()
{
#ifndef VTK_WORDS_BIGENDIAN
this->SwapBytesOn();
#else
this->SwapBytesOff();
#endif
}
void vtkMCubesReader::SetDataByteOrderToLittleEndian()
{
#ifdef VTK_WORDS_BIGENDIAN
this->SwapBytesOn();
#else
this->SwapBytesOff();
#endif
}
void vtkMCubesReader::SetDataByteOrder(int byteOrder)
{
if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN )
{
this->SetDataByteOrderToBigEndian();
}
else
{
this->SetDataByteOrderToLittleEndian();
}
}
int vtkMCubesReader::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 *vtkMCubesReader::GetDataByteOrderAsString()
{
#ifdef VTK_WORDS_BIGENDIAN
if ( this->SwapBytes )
{
return "LittleEndian";
}
else
{
return "BigEndian";
}
#else
if ( this->SwapBytes )
{
return "BigEndian";
}
else
{
return "LittleEndian";
}
#endif
}
void vtkMCubesReader::CreateDefaultLocator()
{
if ( this->Locator == NULL )
{
this->Locator = vtkMergePoints::New();
}
}
void vtkMCubesReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "File Name: "
<< (this->FileName ? this->FileName : "(none)") << "\n";
os << indent << "Limits File Name: "
<< (this->LimitsFileName ? this->LimitsFileName : "(none)") << "\n";
os << indent << "Normals: " << (this->Normals ? "On\n" : "Off\n");
os << indent << "FlipNormals: " << (this->FlipNormals ? "On\n" : "Off\n");
os << indent << "HeaderSize: " << this->HeaderSize << "\n";
os << indent << "Swap Bytes: " << (this->SwapBytes ? "On\n" : "Off\n");
if ( this->Locator )
{
os << indent << "Locator: " << this->Locator << "\n";
}
else
{
os << indent << "Locator: (none)\n";
}
}
unsigned long int vtkMCubesReader::GetMTime()
{
unsigned long mTime=this->Superclass::GetMTime();
unsigned long time;
if ( this->Locator != NULL )
{
time = this->Locator->GetMTime();
mTime = ( time > mTime ? time : mTime );
}
return mTime;
}