/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkOFFReader.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 "vtkOFFReader.h" #include "vtkCellArray.h" #include "vtkFloatArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkTriangle.h" #include "vtkQuad.h" #include <sstream> #include <fstream> vtkStandardNewMacro(vtkOFFReader); // Description: // Instantiate object with NULL filename. vtkOFFReader::vtkOFFReader() { this->FileName = NULL; this->SetNumberOfInputPorts(0); } vtkOFFReader::~vtkOFFReader() { if (this->FileName) { delete[] this->FileName; this->FileName = NULL; } } /*-------------------------------------------------------- This is only partial support for the OFF format, which is quite complicated. To find a full specification, search the net for "OFF format", eg.: http://people.sc.fsu.edu/~burkardt/data/off/off.html We support only vertices and faces composed of 3 vertices. ---------------------------------------------------------*/ // a replacement for isspace() int is_whitespace(char c) { if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f') return 1; else return 0; } int vtkOFFReader::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(<< "A FileName must be specified."); return 0; } std::ifstream in(this->FileName); if (!in) { vtkErrorMacro(<< "File " << this->FileName << " not found"); return 0; } vtkDebugMacro(<< "Reading file"); // intialise some structures to store the file contents in vtkPoints *points = vtkPoints::New(); vtkCellArray *polys = vtkCellArray::New(); // -- work through the file line by line, assigning into the above structures as appropriate -- float xyz[3]; std::string line; getline(in, line); // throw the 1st line away, it always says "OFF" // Read until we get to the first line that is not a comment or a blank line. // This line second states the number of vertices, faces, and edges. while (getline(in, line)) { // std::cout << line << std::endl; if (line.size() == 0) continue; if (line[0] == '#') continue; // if we get to here, this is the info line break; } // std::cout << "Found info line." << std::endl; // At this point, the line were are interested in is stored in 'line' // We are only interested in vertices and faces. std::stringstream ss; ss << line; unsigned int NumberOfVertices, NumberOfFaces; ss >> NumberOfVertices >> NumberOfFaces; // std::cout << "Vertices: " << NumberOfVertices << " Faces: " << NumberOfFaces << std::endl; // Now we can start to read the vertices unsigned int VertexCounter = 0; while (getline(in, line) && VertexCounter < NumberOfVertices) { if (line.size() == 0) // skip blank lines (they should only occur before the vertices start) continue; std::stringstream ssVertex; ssVertex << line; float x, y, z; ssVertex >> x >> y >> z; points->InsertNextPoint(x, y, z); // std::cout << "adding vertex: " << x << " " << y << " " << z << std::endl; VertexCounter++; } // (end of vertex while loop) unsigned int FaceCounter = 0; // read faces do { std::stringstream ssFace; ssFace << line; unsigned int NumFaceVerts, Vert0, Vert1, Vert2, Vert3; ssFace >> NumFaceVerts >> Vert0 >> Vert1 >> Vert2 >> Vert3; if (NumFaceVerts == 3) { std::cout << "adding triangle: " << Vert0 << " " << Vert1 << " " << Vert2 << std::endl; vtkTriangle *triangle = vtkTriangle::New(); triangle->GetPointIds()->SetId(0, Vert0); triangle->GetPointIds()->SetId(1, Vert1); triangle->GetPointIds()->SetId(2, Vert2); polys->InsertNextCell(triangle); triangle->Delete(); FaceCounter++; } else if (NumFaceVerts == 4) { // ssFace >> Vert3; std::cout << "adding quad: " << Vert0 << " " << Vert1 << " " << Vert2 << " " << Vert3 << std::endl; vtkQuad *quad = vtkQuad::New(); quad->GetPointIds()->SetId(0, Vert0); quad->GetPointIds()->SetId(1, Vert1); quad->GetPointIds()->SetId(2, Vert2); quad->GetPointIds()->SetId(3, Vert3); polys->InsertNextCell(quad); quad->Delete(); FaceCounter++; } /** * * std::stringstream ssFace; ssFace << line; unsigned int NumFaceVerts, Vert0, Vert1, Vert2; ssFace >> NumFaceVerts >> Vert0 >> Vert1 >> Vert2; if (NumFaceVerts != 3) { vtkErrorMacro(<< "File " << this->FileName << " contains a face with >3 (" << NumFaceVerts << ") vertices."); return 0; } // std::cout << "adding triangle: " << Vert0 << " " << Vert1 << " " << Vert2 << std::endl; vtkTriangle *triangle = vtkTriangle::New(); triangle->GetPointIds()->SetId(0, Vert0); triangle->GetPointIds()->SetId(1, Vert1); triangle->GetPointIds()->SetId(2, Vert2); polys->InsertNextCell(triangle); triangle->Delete(); FaceCounter++; * */ } while (getline(in, line) && FaceCounter < NumberOfFaces); // we have finished with the file in.close(); output->SetPoints(points); output->SetPolys(polys); points->Delete(); polys->Delete(); return 1; } void vtkOFFReader::PrintSelf(ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "File Name: " << (this->FileName ? this->FileName : "(none)") << "\n"; }