1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkUGFacetReader.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkUGFacetReader.h"
16 
17 #include "vtkByteSwap.h"
18 #include "vtkCellArray.h"
19 #include "vtkFloatArray.h"
20 #include "vtkMergePoints.h"
21 #include "vtkInformation.h"
22 #include "vtkInformationVector.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPointData.h"
25 #include "vtkPolyData.h"
26 #include "vtkShortArray.h"
27 #include "vtkIncrementalPointLocator.h"
28 
29 vtkStandardNewMacro(vtkUGFacetReader);
30 
31 // Construct object to extract all parts, and with point merging
32 // turned on.
vtkUGFacetReader()33 vtkUGFacetReader::vtkUGFacetReader()
34 {
35   this->FileName = NULL;
36   this->PartColors = NULL;
37   this->PartNumber = (-1); //extract all parts
38 
39   this->Merging = 1;
40   this->Locator = NULL;
41 
42   this->SetNumberOfInputPorts(0);
43 }
44 
~vtkUGFacetReader()45 vtkUGFacetReader::~vtkUGFacetReader()
46 {
47   delete [] this->FileName;
48 
49   if ( this->PartColors )
50     {
51     this->PartColors->Delete();
52     }
53   if (this->Locator != NULL)
54     {
55     this->Locator->UnRegister(this);
56     this->Locator = NULL;
57     }
58 }
59 
60 // Overload standard modified time function. If locator is modified,
61 // then this object is modified as well.
GetMTime()62 unsigned long vtkUGFacetReader::GetMTime()
63 {
64   unsigned long mTime1=this->Superclass::GetMTime();
65   unsigned long mTime2;
66 
67   if (this->Locator)
68     {
69     mTime2 = this->Locator->GetMTime();
70     mTime1 = ( mTime1 > mTime2 ? mTime1 : mTime2 );
71     }
72 
73   return mTime1;
74 }
75 
76 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)77 int vtkUGFacetReader::RequestData(
78   vtkInformation *vtkNotUsed(request),
79   vtkInformationVector **vtkNotUsed(inputVector),
80   vtkInformationVector *outputVector)
81 {
82   // get the info object
83   vtkInformation *outInfo = outputVector->GetInformationObject(0);
84 
85   // get the ouptut
86   vtkPolyData *output = vtkPolyData::SafeDownCast(
87     outInfo->Get(vtkDataObject::DATA_OBJECT()));
88 
89   FILE *fp;
90   char header[36];
91   struct {float  v1[3], v2[3], v3[3], n1[3], n2[3], n3[3];} facet;
92   vtkIdType ptId[3];
93   short ugiiColor, direction;
94   int numberTris, numFacetSets, setNumber, facetNumber;
95   vtkPoints *newPts, *mergedPts;
96   vtkFloatArray *newNormals, *mergedNormals;
97   vtkCellArray *newPolys, *mergedPolys;
98   fpos_t pos;
99   int triEstimate;
100 
101   vtkDebugMacro(<<"Reading UG facet file...");
102   if ( this->FileName == NULL || strlen(this->FileName) == 0)
103     {
104     vtkErrorMacro(<<"No FileName specified...please specify one.");
105     return 0;
106     }
107 
108   // open the file
109   if ( (fp = fopen(this->FileName, "rb")) == NULL)
110     {
111     vtkErrorMacro(<<"Cannot open file specified.");
112     return 0;
113     }
114 
115   // read the header stuff
116   if ( fread (header, 1, 2, fp) <= 0 ||
117   fread (&numFacetSets, 4, 1, fp) <= 0 ||
118   fread (header, 1, 36, fp) <= 0 )
119     {
120     vtkErrorMacro(<<"File ended prematurely");
121     fclose(fp);
122     return 0;
123     }
124 
125   // swap bytes since this is a binary file format
126   vtkByteSwap::Swap4BE(&numFacetSets);
127 
128   // Estimate how much space we need - find out the size of the
129   // file and divide by 72 bytes per triangle
130   fgetpos( fp, &pos );
131   fseek( fp, 0L, SEEK_END );
132   triEstimate = ftell( fp ) / 72;
133   fsetpos( fp, &pos );
134 
135   // allocate memory
136   if ( ! this->PartColors )
137     {
138     this->PartColors = vtkShortArray::New();
139     this->PartColors->Allocate(100);
140     }
141   else
142     {
143     this->PartColors->Reset();
144     }
145 
146   newPts = vtkPoints::New();
147   newPts->Allocate(triEstimate,triEstimate);
148   newNormals = vtkFloatArray::New();
149   newNormals->SetNumberOfComponents(3);
150   newNormals->Allocate(3*triEstimate,3*triEstimate);
151   newPolys = vtkCellArray::New();
152   newPolys->Allocate(newPolys->EstimateSize(triEstimate,3),triEstimate);
153 
154   // loop over all facet sets, extracting triangles
155   for (setNumber=0; setNumber < numFacetSets; setNumber++)
156     {
157 
158     if ( fread (&ugiiColor, 2, 1, fp) <= 0 ||
159     fread (&direction, 2, 1, fp) <= 0 ||
160     fread (&numberTris, 4, 1, fp) <= 0 )
161       {
162       vtkErrorMacro(<<"File ended prematurely");
163       break;
164       }
165 
166     // swap bytes if necc
167     vtkByteSwap::Swap4BE(&numberTris);
168     vtkByteSwap::Swap2BERange(&ugiiColor,1);
169     vtkByteSwap::Swap2BERange(&direction,1);
170 
171     this->PartColors->InsertNextValue(ugiiColor);
172 
173     for (facetNumber=0; facetNumber < numberTris; facetNumber++)
174       {
175       if ( fread(&facet,72,1,fp) <= 0 )
176         {
177         vtkErrorMacro(<<"File ended prematurely");
178         break;
179         }
180 
181       // swap bytes if necc
182       vtkByteSwap::Swap4BERange((float *)(&facet),18);
183 
184       if ( this->PartNumber == -1 || this->PartNumber == setNumber )
185         {
186         ptId[0] = newPts->InsertNextPoint(facet.v1);
187         ptId[1] = newPts->InsertNextPoint(facet.v2);
188         ptId[2] = newPts->InsertNextPoint(facet.v3);
189 
190         newNormals->InsertTuple(ptId[0],facet.n1);
191         newNormals->InsertTuple(ptId[1],facet.n2);
192         newNormals->InsertTuple(ptId[2],facet.n3);
193 
194         newPolys->InsertNextCell(3,ptId);
195         }//if appropriate part
196       }//for all facets in this set
197     }//for this facet set
198 
199   // update output
200   vtkDebugMacro(<<"Read "
201                 << newPts->GetNumberOfPoints() << " points, "
202                 << newPolys->GetNumberOfCells() << " triangles.");
203 
204   fclose(fp);
205 
206   //
207   // Merge points/triangles if requested
208   //
209   if ( this->Merging )
210     {
211     int i;
212     vtkIdType *pts = 0;
213     vtkIdType nodes[3];
214     vtkIdType npts;
215     double *x;
216 
217     mergedPts = vtkPoints::New();
218     mergedPts->Allocate(newPts->GetNumberOfPoints()/3);
219     mergedNormals = vtkFloatArray::New();
220     mergedNormals->SetNumberOfComponents(3);
221     mergedNormals->Allocate(newNormals->GetNumberOfTuples());
222     mergedPolys = vtkCellArray::New();
223     mergedPolys->Allocate(newPolys->GetSize());
224 
225     if ( this->Locator == NULL )
226       {
227       this->CreateDefaultLocator();
228       }
229     this->Locator->InitPointInsertion (mergedPts, newPts->GetBounds());
230 
231     for (newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); )
232       {
233       for (i=0; i < 3; i++)
234         {
235         x = newPts->GetPoint(pts[i]);
236         if ( this->Locator->InsertUniquePoint(x, nodes[i]) )
237           {
238           mergedNormals->InsertTuple(nodes[i],newNormals->GetTuple(pts[i]));
239           }
240         }
241 
242       if ( nodes[0] != nodes[1] && nodes[0] != nodes[2] &&
243       nodes[1] != nodes[2] )
244         {
245         mergedPolys->InsertNextCell(3,nodes);
246         }
247       }
248 
249       newPts->Delete();
250       newNormals->Delete();
251       newPolys->Delete();
252 
253       vtkDebugMacro(<< "Merged to: "
254                    << mergedPts->GetNumberOfPoints() << " points, "
255                    << mergedPolys->GetNumberOfCells() << " triangles");
256     }
257   else
258     {
259     mergedPts = newPts;
260     mergedNormals = newNormals;
261     mergedPolys = newPolys;
262     }
263 //
264 // Update ourselves
265 //
266   output->SetPoints(mergedPts);
267   mergedPts->Delete();
268 
269   output->GetPointData()->SetNormals(mergedNormals);
270   mergedNormals->Delete();
271 
272   output->SetPolys(mergedPolys);
273   mergedPolys->Delete();
274 
275   if (this->Locator)
276     {
277     this->Locator->Initialize(); //free storage
278     }
279 
280   output->Squeeze();
281 
282   return 1;
283 }
284 
GetNumberOfParts()285 int vtkUGFacetReader::GetNumberOfParts()
286 {
287   char header[36];
288   FILE *fp;
289   int numberOfParts;
290 
291   if ( this->FileName == NULL || strlen(this->FileName) == 0)
292     {
293     vtkErrorMacro(<<"No FileName specified...please specify one.");
294     return 0;
295     }
296 
297   // open the file
298   if ( (fp = fopen(this->FileName, "rb")) == NULL)
299     {
300     vtkErrorMacro(<<"Cannot open file specified.");
301     return 0;
302     }
303 
304   // read the header stuff
305   if ( fread (header, 1, 2, fp) <= 0 ||
306   fread (&numberOfParts, 4, 1, fp) <= 0 ||
307   fread (header, 1, 36, fp) <= 0 )
308     {
309     vtkErrorMacro(<<"File ended prematurely");
310     fclose(fp);
311     return 0;
312     }
313 
314   // swap bytes if necc
315   vtkByteSwap::Swap4BE(&numberOfParts);
316 
317   fclose(fp);
318   return numberOfParts;
319 }
320 
321 // Retrieve color index for the parts in the file.
GetPartColorIndex(int partId)322 short vtkUGFacetReader::GetPartColorIndex(int partId)
323 {
324   if ( this->PartColors == NULL )
325     {
326     this->Update();
327     }
328 
329   if ( !this->PartColors ||
330   partId < 0 || partId > this->PartColors->GetMaxId() )
331     {
332     return 0;
333     }
334   else
335     {
336     return this->PartColors->GetValue(partId);
337     }
338 }
339 
340 // Specify a spatial locator for merging points. By
341 // default an instance of vtkMergePoints is used.
SetLocator(vtkIncrementalPointLocator * locator)342 void vtkUGFacetReader::SetLocator(vtkIncrementalPointLocator *locator)
343 {
344   if ( this->Locator == locator )
345     {
346     return;
347     }
348   if (this->Locator != NULL)
349     {
350     this->Locator->UnRegister(this);
351     this->Locator = NULL;
352     }
353   if (locator != NULL)
354     {
355     locator->Register(this);
356     }
357   this->Locator = locator;
358   this->Modified();
359 }
360 
CreateDefaultLocator()361 void vtkUGFacetReader::CreateDefaultLocator()
362 {
363   if ( this->Locator == NULL )
364     {
365     this->Locator = vtkMergePoints::New();
366     }
367 }
368 
PrintSelf(ostream & os,vtkIndent indent)369 void vtkUGFacetReader::PrintSelf(ostream& os, vtkIndent indent)
370 {
371   this->Superclass::PrintSelf(os,indent);
372 
373   os << indent << "File Name: "
374      << (this->FileName ? this->FileName : "(none)") << "\n";
375 
376   os << indent << "Part Number: " << this->PartNumber << "\n";
377 
378   os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n");
379   if ( this->Locator )
380     {
381     os << indent << "Locator: " << this->Locator << "\n";
382     }
383   else
384     {
385     os << indent << "Locator: (none)\n";
386     }
387 }
388