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