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