1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkDataObjectTreeIterator.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 "vtkDataObjectTreeIterator.h"
16 
17 #include "vtkDataObjectTree.h"
18 #include "vtkDataObjectTreeInternals.h"
19 #include "vtkObjectFactory.h"
20 
21 
22 class vtkDataObjectTreeIterator::vtkInternals
23 {
24 public:
25   // This implements a simple, no frills, depth-first iterator that iterates
26   // over the composite dataset.
27   class vtkIterator
28     {
29     vtkDataObject* DataObject;
30     vtkDataObjectTree* CompositeDataSet;
31 
32     vtkDataObjectTreeInternals::Iterator Iter;
33     vtkDataObjectTreeInternals::ReverseIterator ReverseIter;
34     vtkIterator* ChildIterator;
35 
36     vtkInternals* Parent;
37     bool Reverse;
38     bool PassSelf;
39     unsigned int ChildIndex;
40 
InitChildIterator()41     void InitChildIterator()
42       {
43       if (!this->ChildIterator)
44         {
45         this->ChildIterator = new vtkIterator(this->Parent);
46         }
47       this->ChildIterator->Initialize(this->Reverse, 0);
48 
49       if (this->Reverse &&
50         this->ReverseIter != this->GetInternals(this->CompositeDataSet)->Children.rend())
51         {
52         this->ChildIterator->Initialize(this->Reverse,
53           this->ReverseIter->DataObject);
54         }
55       else if (!this->Reverse &&
56         this->Iter != this->GetInternals(this->CompositeDataSet)->Children.end())
57         {
58         this->ChildIterator->Initialize(this->Reverse,
59           this->Iter->DataObject);
60         }
61       }
62 
GetInternals(vtkDataObjectTree * cd)63     vtkDataObjectTreeInternals* GetInternals(vtkDataObjectTree* cd)
64       {
65       return this->Parent->GetInternals(cd);
66       }
67   public:
vtkIterator(vtkInternals * parent)68     vtkIterator(vtkInternals* parent)
69       {
70       this->ChildIterator = 0;
71       this->Parent = parent;
72       }
73 
~vtkIterator()74     ~vtkIterator()
75       {
76       delete this->ChildIterator;
77       this->ChildIterator = 0;
78       }
79 
80 
81 
Initialize(bool reverse,vtkDataObject * dataObj)82     void Initialize(bool reverse, vtkDataObject* dataObj)
83       {
84       vtkDataObjectTree* compositeData = vtkDataObjectTree::SafeDownCast(dataObj);
85       this->Reverse = reverse;
86       this->DataObject = dataObj;
87       this->CompositeDataSet = compositeData;
88       this->ChildIndex = 0;
89       this->PassSelf = true;
90 
91       delete this->ChildIterator;
92       this->ChildIterator = NULL;
93 
94       if (compositeData)
95         {
96         this->Iter = this->GetInternals(compositeData)->Children.begin();
97         this->ReverseIter = this->GetInternals(compositeData)->Children.rbegin();
98         this->InitChildIterator();
99         }
100       }
101 
InSubTree()102     bool InSubTree()
103       {
104       if (this->PassSelf || this->IsDoneWithTraversal())
105         {
106         return false;
107         }
108 
109       if (!this->ChildIterator)
110         {
111         return false;
112         }
113 
114       if (this->ChildIterator->PassSelf)
115         {
116         return false;
117         }
118 
119       return true;
120       }
121 
122 
IsDoneWithTraversal()123     bool IsDoneWithTraversal()
124       {
125       if (!this->DataObject)
126         {
127         return true;
128         }
129 
130       if (this->PassSelf)
131         {
132         return false;
133         }
134 
135       if (!this->CompositeDataSet)
136         {
137         return true;
138         }
139 
140       if (this->Reverse &&
141         this->ReverseIter == this->GetInternals(this->CompositeDataSet)->Children.rend())
142         {
143         return true;
144         }
145 
146       if (!this->Reverse &&
147         this->Iter == this->GetInternals(this->CompositeDataSet)->Children.end())
148         {
149         return true;
150         }
151       return false;
152       }
153 
154     // Should not be called is this->IsDoneWithTraversal() returns true.
GetCurrentDataObject()155     vtkDataObject* GetCurrentDataObject()
156       {
157       if (this->PassSelf)
158         {
159         return this->DataObject;
160         }
161       return this->ChildIterator?
162         this->ChildIterator->GetCurrentDataObject() : 0;
163       }
164 
GetCurrentMetaData()165     vtkInformation* GetCurrentMetaData()
166       {
167       if (this->PassSelf || !this->ChildIterator)
168         {
169         return NULL;
170         }
171 
172       if (this->ChildIterator->PassSelf)
173         {
174         if (this->Reverse)
175           {
176           if (!this->ReverseIter->MetaData.GetPointer())
177             {
178             this->ReverseIter->MetaData.TakeReference(vtkInformation::New());
179             }
180           return this->ReverseIter->MetaData;
181           }
182         else
183           {
184           if (!this->Iter->MetaData.GetPointer())
185             {
186             this->Iter->MetaData.TakeReference(vtkInformation::New());
187             }
188           return this->Iter->MetaData;
189           }
190         }
191       return this->ChildIterator->GetCurrentMetaData();
192       }
193 
HasCurrentMetaData()194     int HasCurrentMetaData()
195       {
196       if (this->PassSelf || !this->ChildIterator)
197         {
198         return 0;
199         }
200 
201       if (this->ChildIterator->PassSelf)
202         {
203         return this->Reverse?
204           (this->ReverseIter->MetaData.GetPointer() != 0):
205           (this->Iter->MetaData.GetPointer() != 0);
206         }
207 
208       return this->ChildIterator->HasCurrentMetaData();
209       }
210 
211     // Go to the next element.
Next()212     void Next()
213       {
214       if (this->PassSelf)
215         {
216         this->PassSelf = false;
217         }
218       else if (this->ChildIterator)
219         {
220         this->ChildIterator->Next();
221         if (this->ChildIterator->IsDoneWithTraversal())
222           {
223           this->ChildIndex++;
224           if (this->Reverse)
225             {
226             this->ReverseIter++;
227             }
228           else
229             {
230             this->Iter++;
231             }
232           this->InitChildIterator();
233           }
234         }
235       }
236 
237     // Returns the full-tree index for the current location.
GetCurrentIndex()238     vtkDataObjectTreeIndex GetCurrentIndex()
239       {
240       vtkDataObjectTreeIndex index;
241       if (this->PassSelf || this->IsDoneWithTraversal() || !this->ChildIterator)
242         {
243         return index;
244         }
245       index.push_back(this->ChildIndex);
246       vtkDataObjectTreeIndex childIndex = this->ChildIterator->GetCurrentIndex();
247       index.insert(index.end(), childIndex.begin(), childIndex.end());
248       return index;
249       }
250 
251     };
252 
253   // Description:
254   // Helper method used by vtkInternals to get access to the internals of
255   // vtkDataObjectTree.
GetInternals(vtkDataObjectTree * cd)256   vtkDataObjectTreeInternals* GetInternals(vtkDataObjectTree* cd)
257     {
258     return this->CompositeDataIterator->GetInternals(cd);
259     }
260 
vtkInternals()261   vtkInternals()
262     {
263     this->Iterator = new vtkIterator(this);
264     }
~vtkInternals()265   ~vtkInternals()
266     {
267     delete this->Iterator;
268     this->Iterator = 0;
269     }
270 
271   vtkIterator *Iterator;
272   vtkDataObjectTreeIterator* CompositeDataIterator;
273 };
274 
275 vtkStandardNewMacro(vtkDataObjectTreeIterator);
276 //----------------------------------------------------------------------------
vtkDataObjectTreeIterator()277 vtkDataObjectTreeIterator::vtkDataObjectTreeIterator()
278 {
279   this->VisitOnlyLeaves = 1;
280   this->TraverseSubTree = 1;
281   this->CurrentFlatIndex = 0;
282   this->Internals = new vtkInternals();
283   this->Internals->CompositeDataIterator = this;
284 }
285 
286 //----------------------------------------------------------------------------
~vtkDataObjectTreeIterator()287 vtkDataObjectTreeIterator::~vtkDataObjectTreeIterator()
288 {
289   delete this->Internals;
290 }
291 
292 //----------------------------------------------------------------------------
IsDoneWithTraversal()293 int vtkDataObjectTreeIterator::IsDoneWithTraversal()
294 {
295   return this->Internals->Iterator->IsDoneWithTraversal();
296 }
297 
298 //----------------------------------------------------------------------------
GoToFirstItem()299 void vtkDataObjectTreeIterator::GoToFirstItem()
300 {
301   this->CurrentFlatIndex = 0;
302   this->Internals->Iterator->Initialize(this->Reverse !=0, this->DataSet);
303   this->NextInternal();
304 
305   while (!this->Internals->Iterator->IsDoneWithTraversal())
306     {
307     vtkDataObject* dObj = this->Internals->Iterator->GetCurrentDataObject();
308     if ((!dObj && this->SkipEmptyNodes) ||
309       (this->VisitOnlyLeaves && vtkDataObjectTree::SafeDownCast(dObj)))
310       {
311       this->NextInternal();
312       }
313     else
314       {
315       break;
316       }
317     }
318 }
319 
320 //----------------------------------------------------------------------------
GoToNextItem()321 void vtkDataObjectTreeIterator::GoToNextItem()
322 {
323   if (!this->Internals->Iterator->IsDoneWithTraversal())
324     {
325     this->NextInternal();
326 
327     while (!this->Internals->Iterator->IsDoneWithTraversal())
328       {
329       vtkDataObject* dObj = this->Internals->Iterator->GetCurrentDataObject();
330       if ((!dObj && this->SkipEmptyNodes) ||
331         (this->VisitOnlyLeaves && vtkDataObjectTree::SafeDownCast(dObj)))
332         {
333         this->NextInternal();
334         }
335       else
336         {
337         break;
338         }
339       }
340     }
341 }
342 
343 //----------------------------------------------------------------------------
NextInternal()344 void vtkDataObjectTreeIterator::NextInternal()
345 {
346   do
347     {
348     this->CurrentFlatIndex++;
349     this->Internals->Iterator->Next();
350     }
351   while (!this->TraverseSubTree && this->Internals->Iterator->InSubTree());
352 }
353 
354 //----------------------------------------------------------------------------
GetCurrentDataObject()355 vtkDataObject* vtkDataObjectTreeIterator::GetCurrentDataObject()
356 {
357   if (!this->IsDoneWithTraversal())
358     {
359     return this->Internals->Iterator->GetCurrentDataObject();
360     }
361 
362   return 0;
363 }
364 
365 //----------------------------------------------------------------------------
GetCurrentMetaData()366 vtkInformation* vtkDataObjectTreeIterator::GetCurrentMetaData()
367 {
368   if (!this->IsDoneWithTraversal())
369     {
370     return this->Internals->Iterator->GetCurrentMetaData();
371     }
372 
373   return 0;
374 }
375 
376 //----------------------------------------------------------------------------
HasCurrentMetaData()377 int vtkDataObjectTreeIterator::HasCurrentMetaData()
378 {
379   if (!this->IsDoneWithTraversal())
380     {
381     return this->Internals->Iterator->HasCurrentMetaData();
382     }
383 
384   return 0;
385 }
386 
387 //----------------------------------------------------------------------------
GetCurrentIndex()388 vtkDataObjectTreeIndex vtkDataObjectTreeIterator::GetCurrentIndex()
389 {
390   return this->Internals->Iterator->GetCurrentIndex();
391 }
392 
393 //----------------------------------------------------------------------------
GetCurrentFlatIndex()394 unsigned int vtkDataObjectTreeIterator::GetCurrentFlatIndex()
395 {
396   if (this->Reverse)
397     {
398     vtkErrorMacro(
399       "FlatIndex cannot be obtained when iterating in reverse order.");
400     return 0;
401     }
402   return this->CurrentFlatIndex;
403 }
404 
405 //----------------------------------------------------------------------------
GetInternals(vtkDataObjectTree * cd)406 vtkDataObjectTreeInternals* vtkDataObjectTreeIterator::GetInternals(
407   vtkDataObjectTree* cd)
408 {
409   if (cd)
410     {
411     return cd->Internals;
412     }
413 
414   return 0;
415 }
416 
417 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)418 void vtkDataObjectTreeIterator::PrintSelf(ostream& os, vtkIndent indent)
419 {
420   this->Superclass::PrintSelf(os, indent);
421   os << indent << "VisitOnlyLeaves: "
422     << (this->VisitOnlyLeaves? "On" : "Off") << endl;
423   os << indent << "Reverse: "
424     << (this->Reverse? "On" : "Off") << endl;
425   os << indent << "TraverseSubTree: "
426     << (this->TraverseSubTree? "On" : "Off") << endl;
427   os << indent << "SkipEmptyNodes: "
428     << (this->SkipEmptyNodes? "On" : "Off") << endl;
429   os << indent << "CurrentFlatIndex: " << this->CurrentFlatIndex << endl;
430 }
431