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.
 
 
 
 
 
 

442 lines
11 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkSTLReader.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 "vtkSTLReader.h"
#include "vtkByteSwap.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkFloatArray.h"
#include "vtkMergePoints.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <ctype.h>
vtkCxxRevisionMacro(vtkSTLReader, "$Revision: 1.71 $");
vtkStandardNewMacro(vtkSTLReader);
#define VTK_ASCII 0
#define VTK_BINARY 1
// Construct object with merging set to true.
vtkSTLReader::vtkSTLReader()
{
this->FileName = NULL;
this->Merging = 1;
this->ScalarTags = 0;
this->Locator = NULL;
this->SetNumberOfInputPorts(0);
}
vtkSTLReader::~vtkSTLReader()
{
if (this->FileName)
{
delete [] this->FileName;
}
if ( this->Locator )
{
this->Locator->UnRegister(this);
this->Locator = NULL;
}
}
// Overload standard modified time function. If locator is modified,
// then this object is modified as well.
unsigned long vtkSTLReader::GetMTime()
{
unsigned long mTime1=this->Superclass::GetMTime();
unsigned long mTime2;
if (this->Locator)
{
mTime2 = this->Locator->GetMTime();
mTime1 = ( mTime1 > mTime2 ? mTime1 : mTime2 );
}
return mTime1;
}
int vtkSTLReader::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;
vtkPoints *newPts, *mergedPts;
vtkCellArray *newPolys, *mergedPolys;
vtkFloatArray *newScalars=0, *mergedScalars=0;
// All of the data in the first piece.
if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
{
return 0;
}
if (!this->FileName)
{
vtkErrorMacro(<<"A FileName must be specified.");
return 0;
}
// Initialize
//
if ((fp = fopen(this->FileName, "r")) == NULL)
{
vtkErrorMacro(<< "File " << this->FileName << " not found");
return 0;
}
newPts = vtkPoints::New();
newPts->Allocate(5000,10000);
newPolys = vtkCellArray::New();
newPolys->Allocate(10000,20000);
// Depending upon file type, read differently
//
if ( this->GetSTLFileType(fp) == VTK_ASCII )
{
if (ScalarTags)
{
newScalars = vtkFloatArray::New();
newScalars->Allocate(5000,10000);
}
if ( this->ReadASCIISTL(fp,newPts,newPolys,newScalars) )
{
return 1;
}
}
else
{
fclose(fp);
fp = fopen(this->FileName, "rb");
if ( this->ReadBinarySTL(fp,newPts,newPolys) )
{
return 1;
}
}
vtkDebugMacro(<< "Read: "
<< newPts->GetNumberOfPoints() << " points, "
<< newPolys->GetNumberOfCells() << " triangles");
fclose(fp);
//
// If merging is on, create hash table and merge points/triangles.
//
if ( this->Merging )
{
int i;
vtkIdType *pts = 0;
vtkIdType nodes[3];
vtkIdType npts;
double x[3];
int nextCell=0;
mergedPts = vtkPoints::New();
mergedPts->Allocate(newPts->GetNumberOfPoints()/2);
mergedPolys = vtkCellArray::New();
mergedPolys->Allocate(newPolys->GetSize());
if (newScalars)
{
mergedScalars = vtkFloatArray::New();
mergedScalars->Allocate(newPolys->GetSize());
}
if ( this->Locator == NULL )
{
this->CreateDefaultLocator();
}
this->Locator->InitPointInsertion (mergedPts, newPts->GetBounds());
for (newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); )
{
for (i=0; i < 3; i++)
{
newPts->GetPoint(pts[i],x);
this->Locator->InsertUniquePoint(x, nodes[i]);
}
if ( nodes[0] != nodes[1] &&
nodes[0] != nodes[2] &&
nodes[1] != nodes[2] )
{
mergedPolys->InsertNextCell(3,nodes);
if (newScalars)
{
mergedScalars->InsertNextValue(newScalars->GetValue(nextCell));
}
}
nextCell++;
}
newPts->Delete();
newPolys->Delete();
if (newScalars)
{
newScalars->Delete();
}
vtkDebugMacro(<< "Merged to: "
<< mergedPts->GetNumberOfPoints() << " points, "
<< mergedPolys->GetNumberOfCells() << " triangles");
}
else
{
mergedPts = newPts;
mergedPolys = newPolys;
mergedScalars = newScalars;
}
//
// Update ourselves
//
output->SetPoints(mergedPts);
mergedPts->Delete();
output->SetPolys(mergedPolys);
mergedPolys->Delete();
if (mergedScalars)
{
output->GetCellData()->SetScalars(mergedScalars);
mergedScalars->Delete();
}
if (this->Locator)
{
this->Locator->Initialize(); //free storage
}
output->Squeeze();
return 1;
}
int vtkSTLReader::ReadBinarySTL(FILE *fp, vtkPoints *newPts,
vtkCellArray *newPolys)
{
int i, numTris;
vtkIdType pts[3];
unsigned long ulint;
unsigned short ibuff2;
char header[81];
typedef struct {float n[3], v1[3], v2[3], v3[3];} facet_t;
facet_t facet;
vtkDebugMacro(<< " Reading BINARY STL file");
// File is read to obtain raw information as well as bounding box
//
fread (header, 1, 80, fp);
fread (&ulint, 1, 4, fp);
vtkByteSwap::Swap4LE(&ulint);
// Many .stl files contain bogus count. Hence we will ignore and read
// until end of file.
//
if ( (numTris = (int) ulint) <= 0 )
{
vtkDebugMacro(<< "Bad binary count: attempting to correct ("
<< numTris << ")");
}
for ( i=0; fread(&facet,48,1,fp) > 0; i++ )
{
fread(&ibuff2,2,1,fp); //read extra junk
vtkByteSwap::Swap4LE (facet.n);
vtkByteSwap::Swap4LE (facet.n+1);
vtkByteSwap::Swap4LE (facet.n+2);
vtkByteSwap::Swap4LE (facet.v1);
vtkByteSwap::Swap4LE (facet.v1+1);
vtkByteSwap::Swap4LE (facet.v1+2);
pts[0] = newPts->InsertNextPoint(facet.v1);
vtkByteSwap::Swap4LE (facet.v2);
vtkByteSwap::Swap4LE (facet.v2+1);
vtkByteSwap::Swap4LE (facet.v2+2);
pts[1] = newPts->InsertNextPoint(facet.v2);
vtkByteSwap::Swap4LE (facet.v3);
vtkByteSwap::Swap4LE (facet.v3+1);
vtkByteSwap::Swap4LE (facet.v3+2);
pts[2] = newPts->InsertNextPoint(facet.v3);
newPolys->InsertNextCell(3,pts);
if ( (i % 5000) == 0 && i != 0 )
{
vtkDebugMacro(<< "triangle# " << i);
this->UpdateProgress((i%50000)/50000.0);
}
}
return 0;
}
int vtkSTLReader::ReadASCIISTL(FILE *fp, vtkPoints *newPts,
vtkCellArray *newPolys, vtkFloatArray *scalars)
{
char line[256];
float x[3];
vtkIdType pts[3];
int done;
int currentSolid = 0;
vtkDebugMacro(<< " Reading ASCII STL file");
// Ingest header and junk to get to first vertex
//
fgets (line, 255, fp);
done = (fscanf(fp,"%s %*s %f %f %f\n", line, x, x+1, x+2)==EOF);
// Go into loop, reading facet normal and vertices
//
// while (fscanf(fp,"%*s %*s %f %f %f\n", x, x+1, x+2)!=EOF)
while (!done)
{
//if (ctr>=253840) {
// fprintf(stdout, "Reading record %d\n", ctr);
//}
//ctr += 7;
fgets (line, 255, fp);
fscanf (fp, "%*s %f %f %f\n", x,x+1,x+2);
pts[0] = newPts->InsertNextPoint(x);
fscanf (fp, "%*s %f %f %f\n", x,x+1,x+2);
pts[1] = newPts->InsertNextPoint(x);
fscanf (fp, "%*s %f %f %f\n", x,x+1,x+2);
pts[2] = newPts->InsertNextPoint(x);
fgets (line, 255, fp); // end loop
fgets (line, 255, fp); // end facet
newPolys->InsertNextCell(3,pts);
if (scalars)
{
scalars->InsertNextValue(currentSolid);
}
if ( (newPolys->GetNumberOfCells() % 5000) == 0 )
{
vtkDebugMacro(<< "triangle# " << newPolys->GetNumberOfCells());
this->UpdateProgress((newPolys->GetNumberOfCells()%50000)/50000.0);
}
done = (fscanf(fp,"%s", line)==EOF);
if ((strcmp(line, "ENDSOLID") == 0) || (strcmp(line, "endsolid") == 0))
{
currentSolid++;
fgets(line, 255, fp);
done = feof(fp);
while ((strstr(line, "SOLID") == 0) && (strstr(line, "solid") == 0) && !done)
{
fgets(line, 255, fp);
done = feof(fp);
}
done = (fscanf(fp,"%s", line)==EOF);
}
if (!done) {
done = (fscanf(fp,"%*s %f %f %f\n", x, x+1, x+2)==EOF);
}
}
//fprintf(stdout, "Maximum ctr val %d\n", ctr);
return 0;
}
int vtkSTLReader::GetSTLFileType(FILE *fp)
{
unsigned char header[256];
int type, i;
int numChars;
// Read a little from the file to figure what type it is.
//
// skip 255 characters so we are past any first line comment */
numChars = static_cast<int>(fread ((unsigned char *)header, 1, 255, fp));
for (i = 0, type=VTK_ASCII; i< numChars && type == VTK_ASCII; i++) // don't test \0
{
if (header[i] > 127)
{
type = VTK_BINARY;
}
}
// Reset file for reading
//
rewind (fp);
return type;
}
// Specify a spatial locator for merging points. By
// default an instance of vtkMergePoints is used.
void vtkSTLReader::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 vtkSTLReader::CreateDefaultLocator()
{
if ( this->Locator == NULL )
{
this->Locator = vtkMergePoints::New();
this->Locator->Register(this);
this->Locator->Delete();
}
}
void vtkSTLReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "File Name: "
<< (this->FileName ? this->FileName : "(none)") << "\n";
os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n");
os << indent << "ScalarTags: " << (this->ScalarTags ? "On\n" : "Off\n");
if ( this->Locator )
{
os << indent << "Locator: " << this->Locator << "\n";
}
else
{
os << indent << "Locator: (none)\n";
}
}