1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkXMLPolyDataWriter.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 "vtkXMLPolyDataWriter.h"
16 
17 #include "vtkCellArray.h"
18 #include "vtkCellData.h"
19 #include "vtkErrorCode.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationIntegerKey.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkPointData.h"
24 #include "vtkPolyData.h"
25 #include "vtkStreamingDemandDrivenPipeline.h"
26 #define vtkXMLOffsetsManager_DoNotInclude
27 #include "vtkXMLOffsetsManager.h"
28 #undef  vtkXMLOffsetsManager_DoNotInclude
29 
30 vtkStandardNewMacro(vtkXMLPolyDataWriter);
31 
32 //----------------------------------------------------------------------------
vtkXMLPolyDataWriter()33 vtkXMLPolyDataWriter::vtkXMLPolyDataWriter()
34 {
35   this->VertsOM = new OffsetsManagerArray;
36   this->LinesOM = new OffsetsManagerArray;
37   this->StripsOM = new OffsetsManagerArray;
38   this->PolysOM = new OffsetsManagerArray;
39 }
40 
41 //----------------------------------------------------------------------------
~vtkXMLPolyDataWriter()42 vtkXMLPolyDataWriter::~vtkXMLPolyDataWriter()
43 {
44   delete this->VertsOM;
45   delete this->LinesOM;
46   delete this->StripsOM;
47   delete this->PolysOM;
48 }
49 
50 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)51 void vtkXMLPolyDataWriter::PrintSelf(ostream& os, vtkIndent indent)
52 {
53   this->Superclass::PrintSelf(os, indent);
54 }
55 
56 //----------------------------------------------------------------------------
GetInput()57 vtkPolyData* vtkXMLPolyDataWriter::GetInput()
58 {
59   return static_cast<vtkPolyData*>(this->Superclass::GetInput());
60 }
61 
62 //----------------------------------------------------------------------------
GetDataSetName()63 const char* vtkXMLPolyDataWriter::GetDataSetName()
64 {
65   return "PolyData";
66 }
67 
68 //----------------------------------------------------------------------------
GetDefaultFileExtension()69 const char* vtkXMLPolyDataWriter::GetDefaultFileExtension()
70 {
71   return "vtp";
72 }
73 
74 //----------------------------------------------------------------------------
AllocatePositionArrays()75 void vtkXMLPolyDataWriter::AllocatePositionArrays()
76 {
77   this->Superclass::AllocatePositionArrays();
78 
79   this->NumberOfVertsPositions = new unsigned long[this->NumberOfPieces];
80   this->NumberOfLinesPositions = new unsigned long[this->NumberOfPieces];
81   this->NumberOfStripsPositions = new unsigned long[this->NumberOfPieces];
82   this->NumberOfPolysPositions = new unsigned long[this->NumberOfPieces];
83 
84   this->VertsOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps);
85   this->LinesOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps);
86   this->StripsOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps);
87   this->PolysOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps);
88 }
89 
90 //----------------------------------------------------------------------------
DeletePositionArrays()91 void vtkXMLPolyDataWriter::DeletePositionArrays()
92 {
93   this->Superclass::DeletePositionArrays();
94 
95   delete[] this->NumberOfVertsPositions;
96   delete[] this->NumberOfLinesPositions;
97   delete[] this->NumberOfStripsPositions;
98   delete[] this->NumberOfPolysPositions;
99 }
100 
101 //----------------------------------------------------------------------------
WriteInlinePieceAttributes()102 void vtkXMLPolyDataWriter::WriteInlinePieceAttributes()
103 {
104   this->Superclass::WriteInlinePieceAttributes();
105   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
106     {
107     return;
108     }
109 
110   vtkPolyData* input = this->GetInput();
111   this->WriteScalarAttribute("NumberOfVerts",
112                              input->GetVerts()->GetNumberOfCells());
113   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
114     {
115     return;
116     }
117   this->WriteScalarAttribute("NumberOfLines",
118                              input->GetLines()->GetNumberOfCells());
119   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
120     {
121     return;
122     }
123   this->WriteScalarAttribute("NumberOfStrips",
124                              input->GetStrips()->GetNumberOfCells());
125   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
126     {
127     return;
128     }
129   this->WriteScalarAttribute("NumberOfPolys",
130                              input->GetPolys()->GetNumberOfCells());
131 }
132 
133 //----------------------------------------------------------------------------
WriteInlinePiece(vtkIndent indent)134 void vtkXMLPolyDataWriter::WriteInlinePiece(vtkIndent indent)
135 {
136   // Split progress range by the approximate fraction of data written
137   // by each step in this method.
138   float progressRange[2] = { 0.f, 0.f };
139   this->GetProgressRange(progressRange);
140   float fractions[6];
141   this->CalculateSuperclassFraction(fractions);
142 
143   // Set the range of progress for superclass.
144   this->SetProgressRange(progressRange, 0, fractions);
145 
146   // Let the superclass write its data.
147   this->Superclass::WriteInlinePiece(indent);
148   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
149     {
150     return;
151     }
152 
153   vtkPolyData* input = this->GetInput();
154 
155   // Set the range of progress for Verts.
156   this->SetProgressRange(progressRange, 1, fractions);
157 
158   // Write the Verts.
159   this->WriteCellsInline("Verts", input->GetVerts(), 0, indent);
160   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
161     {
162     return;
163     }
164 
165   // Set the range of progress for Lines.
166   this->SetProgressRange(progressRange, 2, fractions);
167 
168   // Write the Lines.
169   this->WriteCellsInline("Lines", input->GetLines(), 0, indent);
170   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
171     {
172     return;
173     }
174 
175   // Set the range of progress for Strips.
176   this->SetProgressRange(progressRange, 3, fractions);
177 
178   // Write the Strips.
179   this->WriteCellsInline("Strips", input->GetStrips(), 0, indent);
180   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
181     {
182     return;
183     }
184 
185   // Set the range of progress for Polys.
186   this->SetProgressRange(progressRange, 4, fractions);
187 
188   // Write the Polys.
189   this->WriteCellsInline("Polys", input->GetPolys(), 0, indent);
190 }
191 
192 //----------------------------------------------------------------------------
WriteAppendedPieceAttributes(int index)193 void vtkXMLPolyDataWriter::WriteAppendedPieceAttributes(int index)
194 {
195   this->Superclass::WriteAppendedPieceAttributes(index);
196   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
197     {
198     return;
199     }
200   this->NumberOfVertsPositions[index] =
201     this->ReserveAttributeSpace("NumberOfVerts");
202   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
203     {
204     return;
205     }
206   this->NumberOfLinesPositions[index] =
207     this->ReserveAttributeSpace("NumberOfLines");
208   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
209     {
210     return;
211     }
212   this->NumberOfStripsPositions[index] =
213     this->ReserveAttributeSpace("NumberOfStrips");
214   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
215     {
216     return;
217     }
218   this->NumberOfPolysPositions[index] =
219     this->ReserveAttributeSpace("NumberOfPolys");
220 }
221 
222 //----------------------------------------------------------------------------
WriteAppendedPiece(int index,vtkIndent indent)223 void vtkXMLPolyDataWriter::WriteAppendedPiece(int index, vtkIndent indent)
224 {
225   this->Superclass::WriteAppendedPiece(index, indent);
226   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
227     {
228     return;
229     }
230 
231   this->WriteCellsAppended("Verts", 0, indent,
232     &this->VertsOM->GetPiece(index));
233   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
234     {
235     return;
236     }
237 
238   this->WriteCellsAppended("Lines", 0, indent ,
239     &this->LinesOM->GetPiece(index));
240   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
241     {
242     return;
243     }
244 
245   this->WriteCellsAppended("Strips", 0, indent,
246     &this->StripsOM->GetPiece(index));
247   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
248     {
249     return;
250     }
251 
252   this->WriteCellsAppended("Polys", 0, indent,
253     &this->PolysOM->GetPiece(index));
254 }
255 
256 //----------------------------------------------------------------------------
WriteAppendedPieceData(int index)257 void vtkXMLPolyDataWriter::WriteAppendedPieceData(int index)
258 {
259   ostream& os = *(this->Stream);
260   vtkPolyData* input = this->GetInput();
261 
262   unsigned long returnPosition = os.tellp();
263   os.seekp(this->NumberOfVertsPositions[index]);
264   this->WriteScalarAttribute("NumberOfVerts",
265                              input->GetVerts()->GetNumberOfCells());
266   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
267     {
268     return;
269     }
270 
271   os.seekp(this->NumberOfLinesPositions[index]);
272   this->WriteScalarAttribute("NumberOfLines",
273                              input->GetLines()->GetNumberOfCells());
274   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
275     {
276     return;
277     }
278 
279   os.seekp(this->NumberOfStripsPositions[index]);
280   this->WriteScalarAttribute("NumberOfStrips",
281                              input->GetStrips()->GetNumberOfCells());
282   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
283     {
284     return;
285     }
286 
287   os.seekp(this->NumberOfPolysPositions[index]);
288   this->WriteScalarAttribute("NumberOfPolys",
289                              input->GetPolys()->GetNumberOfCells());
290   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
291     {
292     return;
293     }
294   os.seekp(returnPosition);
295 
296   // Split progress range by the approximate fraction of data written
297   // by each step in this method.
298   float progressRange[2] = { 0.f, 0.f };
299   this->GetProgressRange(progressRange);
300   float fractions[6];
301   this->CalculateSuperclassFraction(fractions);
302 
303   // Set the range of progress for superclass.
304   this->SetProgressRange(progressRange, 0, fractions);
305 
306   // Let the superclass write its data.
307   this->Superclass::WriteAppendedPieceData(index);
308   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
309     {
310     return;
311     }
312 
313   // Set the range of progress for Verts.
314   this->SetProgressRange(progressRange, 1, fractions);
315 
316   // Write the Verts.
317   this->WriteCellsAppendedData(input->GetVerts(), 0,
318                                this->CurrentTimeIndex,
319                                &this->VertsOM->GetPiece(index));
320   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
321     {
322     return;
323     }
324 
325   // Set the range of progress for Lines.
326   this->SetProgressRange(progressRange, 2, fractions);
327 
328   // Write the Lines.
329   this->WriteCellsAppendedData(input->GetLines(), 0,
330                                this->CurrentTimeIndex,
331                                &this->LinesOM->GetPiece(index));
332   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
333     {
334     return;
335     }
336 
337   // Set the range of progress for Strips.
338   this->SetProgressRange(progressRange, 3, fractions);
339 
340   // Write the Strips.
341   this->WriteCellsAppendedData(input->GetStrips(), 0,
342                                this->CurrentTimeIndex,
343                                &this->StripsOM->GetPiece(index));
344   if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
345     {
346     return;
347     }
348 
349   // Set the range of progress for Polys.
350   this->SetProgressRange(progressRange, 4, fractions);
351 
352   // Write the Polys.
353   this->WriteCellsAppendedData(input->GetPolys(), 0,
354                                this->CurrentTimeIndex,
355                                &this->PolysOM->GetPiece(index));
356 }
357 
358 //----------------------------------------------------------------------------
GetNumberOfInputCells()359 vtkIdType vtkXMLPolyDataWriter::GetNumberOfInputCells()
360 {
361   vtkPolyData* input = this->GetInput();
362   return (input->GetVerts()->GetNumberOfCells()+
363           input->GetLines()->GetNumberOfCells()+
364           input->GetStrips()->GetNumberOfCells()+
365           input->GetPolys()->GetNumberOfCells());
366 }
367 
368 //----------------------------------------------------------------------------
CalculateSuperclassFraction(float * fractions)369 void vtkXMLPolyDataWriter::CalculateSuperclassFraction(float* fractions)
370 {
371   vtkPolyData* input = this->GetInput();
372 
373   // The superclass will write point/cell data and point specifications.
374   int pdArrays = input->GetPointData()->GetNumberOfArrays();
375   int cdArrays = input->GetCellData()->GetNumberOfArrays();
376   vtkIdType pdSize = pdArrays*this->GetNumberOfInputPoints();
377   vtkIdType cdSize = cdArrays*this->GetNumberOfInputCells();
378   vtkIdType pointsSize = this->GetNumberOfInputPoints();
379 
380   // This class will write cell specifications.
381   vtkIdType connectSizeV = (input->GetVerts()->GetData()->GetNumberOfTuples() -
382                             input->GetVerts()->GetNumberOfCells());
383   vtkIdType connectSizeL = (input->GetLines()->GetData()->GetNumberOfTuples() -
384                             input->GetLines()->GetNumberOfCells());
385   vtkIdType connectSizeS = (input->GetStrips()->GetData()->GetNumberOfTuples() -
386                             input->GetStrips()->GetNumberOfCells());
387   vtkIdType connectSizeP = (input->GetPolys()->GetData()->GetNumberOfTuples() -
388                             input->GetPolys()->GetNumberOfCells());
389   vtkIdType offsetSizeV = input->GetVerts()->GetNumberOfCells();
390   vtkIdType offsetSizeL = input->GetLines()->GetNumberOfCells();
391   vtkIdType offsetSizeS = input->GetStrips()->GetNumberOfCells();
392   vtkIdType offsetSizeP = input->GetPolys()->GetNumberOfCells();
393   fractions[0] = 0;
394   fractions[1] = fractions[0] + pdSize+cdSize+pointsSize;
395   fractions[2] = fractions[1] + connectSizeV+offsetSizeV;
396   fractions[3] = fractions[2] + connectSizeL+offsetSizeL;
397   fractions[4] = fractions[3] + connectSizeS+offsetSizeS;
398   fractions[5] = fractions[4] + connectSizeP+offsetSizeP;
399   if (fractions[5] == 0)
400     {
401     fractions[5] = 1;
402     }
403   for (int i = 0; i < 5; ++i)
404     {
405     fractions[i+1] = fractions[i+1] / fractions[5];
406     }
407 }
408 
409 //----------------------------------------------------------------------------
FillInputPortInformation(int,vtkInformation * info)410 int vtkXMLPolyDataWriter::FillInputPortInformation(int, vtkInformation* info)
411 {
412   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
413   return 1;
414 }
415