1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkXMLHyperOctreeReader.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 
16 //TODO:
17 // Add support for timesteps
18 // Add streaming support.
19 
20 #include "vtkXMLHyperOctreeReader.h"
21 
22 #include "vtkDataArray.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkHyperOctree.h"
25 #include "vtkHyperOctreeCursor.h"
26 #include "vtkXMLDataElement.h"
27 #include "vtkXMLDataParser.h"
28 #include "vtkInformation.h"
29 #include "vtkStreamingDemandDrivenPipeline.h"
30 #include "vtkIntArray.h"
31 #include "vtkFieldData.h"
32 
33 vtkStandardNewMacro(vtkXMLHyperOctreeReader);
34 
35 //----------------------------------------------------------------------------
vtkXMLHyperOctreeReader()36 vtkXMLHyperOctreeReader::vtkXMLHyperOctreeReader()
37 {
38 }
39 
40 //----------------------------------------------------------------------------
~vtkXMLHyperOctreeReader()41 vtkXMLHyperOctreeReader::~vtkXMLHyperOctreeReader()
42 {
43 }
44 
45 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)46 void vtkXMLHyperOctreeReader::PrintSelf(ostream& os, vtkIndent indent)
47 {
48   this->Superclass::PrintSelf(os, indent);
49 }
50 
51 //----------------------------------------------------------------------------
GetOutput()52 vtkHyperOctree* vtkXMLHyperOctreeReader::GetOutput()
53 {
54   return this->GetOutput(0);
55 }
56 
57 //----------------------------------------------------------------------------
GetOutput(int idx)58 vtkHyperOctree* vtkXMLHyperOctreeReader::GetOutput(int idx)
59 {
60   return vtkHyperOctree::SafeDownCast(this->GetOutputDataObject(idx));
61 }
62 
63 //----------------------------------------------------------------------------
GetDataSetName()64 const char* vtkXMLHyperOctreeReader::GetDataSetName()
65 {
66   return "HyperOctree";
67 }
68 
69 //----------------------------------------------------------------------------
SetupEmptyOutput()70 void vtkXMLHyperOctreeReader::SetupEmptyOutput()
71 {
72   this->GetCurrentOutput()->Initialize();
73 }
74 
75 //----------------------------------------------------------------------------
FillOutputPortInformation(int,vtkInformation * info)76 int vtkXMLHyperOctreeReader::FillOutputPortInformation(int, vtkInformation *info)
77 {
78   info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkHyperOctree");
79   return 1;
80 }
81 
82 //----------------------------------------------------------------------------
GetNumberOfPoints()83 vtkIdType vtkXMLHyperOctreeReader::GetNumberOfPoints()
84 {
85   vtkIdType numPts = 0;
86   vtkDataSet* output = vtkDataSet::SafeDownCast(this->GetCurrentOutput());
87   if (output)
88     {
89     numPts = output->GetNumberOfPoints();
90     }
91   return numPts;
92 }
93 
94 //----------------------------------------------------------------------------
GetNumberOfCells()95 vtkIdType vtkXMLHyperOctreeReader::GetNumberOfCells()
96 {
97   vtkIdType numCells = 0;
98   vtkDataSet* output = vtkDataSet::SafeDownCast(this->GetCurrentOutput());
99   if (output)
100     {
101     numCells = output->GetNumberOfCells();
102     }
103   return numCells;
104 }
105 
106 //----------------------------------------------------------------------------
ReadArrayForPoints(vtkXMLDataElement * da,vtkAbstractArray * outArray)107 int vtkXMLHyperOctreeReader::ReadArrayForPoints(vtkXMLDataElement* da,
108                                                 vtkAbstractArray* outArray)
109 {
110   vtkIdType components = outArray->GetNumberOfComponents();
111   vtkIdType numberOfTuples = this->GetNumberOfPoints();
112   outArray->SetNumberOfTuples(numberOfTuples);
113   return this->ReadArrayValues(da, 0, outArray, 0, numberOfTuples*components);
114 }
115 
116 //----------------------------------------------------------------------------
ReadArrayForCells(vtkXMLDataElement * da,vtkAbstractArray * outArray)117 int vtkXMLHyperOctreeReader::ReadArrayForCells(vtkXMLDataElement* da,
118                                                vtkAbstractArray* outArray)
119 {
120   vtkIdType components = outArray->GetNumberOfComponents();
121   vtkIdType numberOfTuples = this->GetNumberOfCells();
122   outArray->SetNumberOfTuples(numberOfTuples);
123   return this->ReadArrayValues(da, 0, outArray, 0, numberOfTuples*components);
124 
125 }
126 
127 //----------------------------------------------------------------------------
ReadXMLData()128 void vtkXMLHyperOctreeReader::ReadXMLData()
129 {
130 
131   //1) vtkXMLReader grandparent class checks if this timestep needs to SetupOutputData, and if so initializes the output.
132   //2) vtkXMLDataReader parent class reads fielddata
133   this->Superclass::ReadXMLData();
134 
135   //3) For Other XML readers, vtkXMLUnstructuredDataReader or vtkXMLStructuredDataReader parent classes use pipeline info to determines what pieces to read and then ReadPieceData is called to read only part of the data. Since HyperOctree is not streamed yet, I'll just read the whole file here instead.
136 
137   vtkXMLDataElement *ePrimary =
138     this->XMLParser->GetRootElement()->GetNestedElement(0);
139 
140   int dimension;
141   double size[3];
142   double origin[3];
143 
144   if (!ePrimary->GetScalarAttribute("Dimension", dimension))
145     {
146     dimension = 3;
147     }
148 
149   if (ePrimary->GetVectorAttribute("Size", 3, size) != 3)
150     {
151     size[0] = 1;
152     size[1] = 1;
153     size[2] = 1;
154     }
155 
156   if (ePrimary->GetVectorAttribute("Origin", 3, origin) != 3)
157     {
158     origin[0] = 0;
159     origin[1] = 0;
160     origin[2] = 0;
161     }
162 
163   vtkHyperOctree *output = vtkHyperOctree::SafeDownCast(
164       this->GetCurrentOutput());
165   output->SetDimension(dimension);
166   output->SetSize(size);
167   output->SetOrigin(origin);
168 
169   // Find the topology element, which defines the structure of the HyperOctree
170   // Rebuild the HyperOctree from that.
171   // This needs to happen before ReadPieceData so that numPoints and numCells
172   // will be defined.
173   int numNested = ePrimary->GetNumberOfNestedElements();
174   for (int i = 0; i < numNested; ++i)
175     {
176     vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
177     if (strcmp(eNested->GetName(), "Topology") == 0)
178       {
179       this->ReadTopology(eNested);
180       break;
181       }
182     }
183 
184   //Read the pointdata and celldata attribute data.
185   //We only have one piece so this will suffice.
186   this->ReadPieceData();
187 }
188 
189 //----------------------------------------------------------------------------
ReadTopology(vtkXMLDataElement * elem)190 void vtkXMLHyperOctreeReader::ReadTopology(vtkXMLDataElement *elem)
191 {
192 
193   float progressRange[2] = { 0.f, 0.f };
194   this->GetProgressRange(progressRange);
195   //Part spent reading and reconstructing assumed to be roughly equal.
196   float fractions[3] = { 0.f, 0.5f, 1.f };
197   this->SetProgressRange(progressRange, 0, fractions);
198 
199   //Find the topology array and read it into a vtkIntArray
200   int numNested = elem->GetNumberOfNestedElements();
201   if (numNested != 1)
202     {
203     return;
204     }
205 
206   vtkXMLDataElement* tElem = elem->GetNestedElement(0);
207 
208   // Since topology is a vtkIntArray.
209   vtkAbstractArray* a = this->CreateArray(tElem);
210   vtkDataArray *tda = vtkDataArray::SafeDownCast(a);
211   if (!tda)
212     {
213     if (a)
214       {
215       a->Delete();
216       }
217     return;
218     }
219 
220   int numTuples;
221   if (!tElem->GetScalarAttribute("NumberOfTuples", numTuples))
222     {
223     tda->Delete();
224     return;
225     }
226 
227   tda->SetNumberOfTuples(numTuples);
228   if (!this->ReadArrayValues(tElem, 0, tda, 0, numTuples* tda->GetNumberOfComponents())
229 
230    /* this->ReadData(tElem, tda->GetVoidPointer(0), tda->GetDataType(),
231                       0, numTuples*tda->GetNumberOfComponents())*/)
232     {
233     tda->Delete();
234     return;
235     }
236 
237   vtkIntArray *ta = vtkIntArray::SafeDownCast(tda);
238   if (!ta)
239     {
240     tda->Delete();
241     return;
242     }
243 
244   this->SetProgressRange(progressRange, 1, fractions);
245 
246   //Restore the topology from the vtkIntArray. Do it recursively, cell by cell.
247   vtkHyperOctreeCursor *cursor=vtkHyperOctree::SafeDownCast(
248     this->GetCurrentOutput())->NewCellCursor();
249   cursor->ToRoot();
250   //Where in the array we need to read from next.
251   this->ArrayIndex = 0;
252   if (!this->BuildNextCell(ta, cursor, cursor->GetNumberOfChildren()))
253     {
254     vtkErrorMacro( << "Problem reading topology. ");
255     ta->Delete();
256     return ;
257     }
258 
259   //Cleanup
260   cursor->Delete();
261   ta->Delete();
262 }
263 
264 //----------------------------------------------------------------------------
BuildNextCell(vtkIntArray * ta,vtkHyperOctreeCursor * cursor,int nchildren)265 int vtkXMLHyperOctreeReader::BuildNextCell(
266   vtkIntArray *ta, vtkHyperOctreeCursor *cursor, int nchildren)
267 {
268 
269   int nodeType = ta->GetValue(this->ArrayIndex);
270 
271   if (nodeType == 1)
272     {
273     //leaf, stop now
274     }
275 /*
276   else if (nodeType == 2)
277     {
278     //terminal node
279     //subdivide but stop there
280     vtkHyperOctree::SafeDownCast(this->GetCurrentOutput())->SubdivideLeaf(cursor);
281     }
282 */
283   else
284     {
285     //internal node
286     //subdivide
287     vtkHyperOctree::SafeDownCast(this->GetCurrentOutput())->SubdivideLeaf(cursor);
288     //then keep going down
289     int i = 0;
290     while (i < nchildren)
291       {
292       cursor->ToChild(i);
293 
294       this->ArrayIndex++;
295       if (!this->BuildNextCell(ta, cursor, nchildren))
296         {
297         //IO failure somewhere below
298         return 0;
299         }
300 
301       cursor->ToParent();
302       ++i;
303       }
304     }
305   return 1;
306 }
307