1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    TestCellIterators.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 #include "vtkCellIterator.h"
17 
18 #include "vtkCellArray.h"
19 #include "vtkFloatArray.h"
20 #include "vtkGenericCell.h"
21 #include "vtkNew.h"
22 #include "vtkPoints.h"
23 #include "vtkSmartPointer.h"
24 #include "vtkTestUtilities.h"
25 #include "vtkTimerLog.h"
26 #include "vtkUnsignedCharArray.h"
27 #include "vtkUnstructuredGrid.h"
28 #include "vtkUnstructuredGridReader.h"
29 
30 #include <sstream>
31 #include <string>
32 
33 // Enable/disable code that helps/hinders profiling.
34 #undef PROFILE
35 //#define PROFILE
36 
37 // Enable benchmarks.
38 #undef BENCHMARK
39 //#define BENCHMARK
40 
41 #ifdef BENCHMARK
42 #  ifdef PROFILE
43 #    define NUM_BENCHMARKS 10
44 #  else // PROFILE
45 #    define NUM_BENCHMARKS 100
46 #  endif // PROFILE
47 #endif // BENCHMARK
48 
49 //------------------------------------------------------------------------------
50 // Compare the cell type, point ids, and points in 'grid' with those returned
51 // in 'iter'.
testCellIterator(vtkCellIterator * iter,vtkUnstructuredGrid * grid)52 bool testCellIterator(vtkCellIterator *iter, vtkUnstructuredGrid *grid)
53 {
54   vtkIdType cellId = 0;
55   vtkNew<vtkGenericCell> cell;
56   iter->InitTraversal();
57   while (!iter->IsDoneWithTraversal())
58     {
59     grid->GetCell(cellId, cell.GetPointer());
60 
61     if (iter->GetCellType() != cell->GetCellType())
62       {
63       cerr << "Type mismatch for cell " << cellId << endl;
64       return false;
65       }
66 
67     vtkIdType numPoints = iter->GetNumberOfPoints();
68     if (numPoints != cell->GetNumberOfPoints())
69       {
70       cerr << "Number of points mismatch for cell " << cellId << endl;
71       return false;
72       }
73 
74     for (vtkIdType pointInd = 0; pointInd < numPoints; ++pointInd)
75       {
76       if (iter->GetPointIds()->GetId(pointInd)
77           != cell->PointIds->GetId(pointInd))
78         {
79         cerr << "Point id mismatch in cell " << cellId << endl;
80         return false;
81         }
82 
83       double iterPoint[3];
84       double cellPoint[3];
85       iter->GetPoints()->GetPoint(pointInd, iterPoint);
86       cell->Points->GetPoint(pointInd, cellPoint);
87       if (iterPoint[0] != cellPoint[0] ||
88           iterPoint[1] != cellPoint[1] ||
89           iterPoint[2] != cellPoint[2] )
90         {
91         cerr << "Point mismatch in cell " << cellId << endl;
92         return false;
93         }
94       }
95 
96     iter->GoToNextCell();
97     ++cellId;
98     }
99 
100   // ensure that we checked all of the cells
101   if (cellId != grid->GetNumberOfCells())
102     {
103     cerr << "Iterator did not cover all cells in the dataset!" << endl;
104     return false;
105     }
106 
107 //  cout << "Verified " << cellId << " cells with a " << iter->GetClassName()
108 //       << "." << endl;
109   return true;
110 }
111 
112 #define TEST_ITERATOR(iter_, className_) \
113   if (std::string(#className_) != std::string(iter->GetClassName())) \
114     { \
115     cerr << "Unexpected iterator type (expected " #className_ ", got " \
116          << iter_->GetClassName() << ")" << endl; \
117     return false; \
118     } \
119   \
120   if (!testCellIterator(iter_, grid)) \
121     { \
122     cerr << #className_ << " test failed." << endl; \
123     return false; \
124     } \
125   \
126   if (!testCellIterator(iter_, grid)) \
127     { \
128     cerr << #className_ << " test failed after rewind." << endl; \
129     return false; \
130     } \
131 
132 
runValidation(vtkUnstructuredGrid * grid)133 bool runValidation(vtkUnstructuredGrid *grid)
134 {
135   // vtkDataSetCellIterator:
136   vtkCellIterator *iter = grid->vtkDataSet::NewCellIterator();
137   TEST_ITERATOR(iter, vtkDataSetCellIterator);
138   iter->Delete();
139 
140   // vtkPointSetCellIterator:
141   iter = grid->vtkPointSet::NewCellIterator();
142   TEST_ITERATOR(iter, vtkPointSetCellIterator);
143   iter->Delete();
144 
145   // vtkUnstructuredGridCellIterator:
146   iter = grid->vtkUnstructuredGrid::NewCellIterator();
147   TEST_ITERATOR(iter, vtkUnstructuredGridCellIterator);
148   iter->Delete();
149 
150   return true;
151 }
152 
153 // Do-nothing function that ensures arguments passed in will not be compiled
154 // out. Aggressive optimization will otherwise remove portions of the following
155 // loops, throwing off the benchmark results:
156 namespace {
157 std::stringstream _sink;
158 template <class Type>
useData(const Type & data)159 void useData(const Type& data)
160 {
161   _sink << data;
162 }
163 } // end anon namespace
164 
165 // Benchmarking code follows:
166 #ifdef BENCHMARK
167 // There are three signatures for each benchmark function:
168 // - double ()(vtkUnstructuredGrid *)
169 //   Iterate through cells in an unstructured grid, using raw memory when
170 //   possible.
171 // - double ()(vtkUnstructuredGrid *, int)
172 //   Iterator through cells in an unstructured grid, using API only
173 // - double ()(vtkCellIterator *)
174 //   Iterator through all cells available through the iterator.
benchmarkTypeIteration(vtkUnstructuredGrid * grid)175 double benchmarkTypeIteration(vtkUnstructuredGrid *grid)
176 {
177   vtkIdType numCells = grid->GetNumberOfCells();
178   vtkUnsignedCharArray *types = grid->GetCellTypesArray();
179   unsigned char *ptr = types->GetPointer(0);
180   unsigned char range[2] = {VTK_UNSIGNED_CHAR_MAX, VTK_UNSIGNED_CHAR_MIN};
181 
182   vtkNew<vtkTimerLog> timer;
183   timer->StartTimer();
184   for (int i = 0; i < numCells; ++i)
185     {
186     range[0] = std::min(range[0], ptr[i]);
187     range[1] = std::max(range[1], ptr[i]);
188     }
189   timer->StopTimer();
190 
191   useData(range[0]);
192   useData(range[1]);
193 
194   return timer->GetElapsedTime();
195 }
196 
benchmarkTypeIteration(vtkUnstructuredGrid * grid,int)197 double benchmarkTypeIteration(vtkUnstructuredGrid *grid, int)
198 {
199   vtkIdType numCells = grid->GetNumberOfCells();
200   unsigned char tmp;
201   unsigned char range[2] = {VTK_UNSIGNED_CHAR_MAX, VTK_UNSIGNED_CHAR_MIN};
202 
203   vtkNew<vtkTimerLog> timer;
204   timer->StartTimer();
205   for (int i = 0; i < numCells; ++i)
206     {
207     tmp = static_cast<unsigned char>(grid->GetCellType(i));
208     range[0] = std::min(range[0], tmp);
209     range[1] = std::max(range[1], tmp);
210     }
211   timer->StopTimer();
212 
213   useData(range[0]);
214   useData(range[1]);
215 
216   return timer->GetElapsedTime();
217 }
218 
benchmarkTypeIteration(vtkCellIterator * iter)219 double benchmarkTypeIteration(vtkCellIterator *iter)
220 {
221   int range[2] = {VTK_UNSIGNED_CHAR_MAX, VTK_UNSIGNED_CHAR_MIN};
222   int tmp;
223 
224   vtkNew<vtkTimerLog> timer;
225   timer->StartTimer();
226   for (iter->InitTraversal(); iter->IsDoneWithTraversal(); iter->GoToNextCell())
227     {
228     tmp = iter->GetCellType();
229     range[0] = std::min(range[0], tmp);
230     range[1] = std::max(range[1], tmp);
231     }
232   timer->StopTimer();
233 
234   useData(range[0]);
235   useData(range[1]);
236 
237   return timer->GetElapsedTime();
238 }
239 
benchmarkPointIdIteration(vtkUnstructuredGrid * grid)240 double benchmarkPointIdIteration(vtkUnstructuredGrid *grid)
241 {
242   vtkCellArray *cellArray = grid->GetCells();
243   vtkIdType numCells = cellArray->GetNumberOfCells();
244   vtkIdType *cellPtr = cellArray->GetPointer();
245   vtkIdType range[2] = {VTK_ID_MAX, VTK_ID_MIN};
246   vtkIdType cellSize;
247 
248   vtkNew<vtkTimerLog> timer;
249   timer->StartTimer();
250   for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
251     {
252     cellSize = *(cellPtr++);
253     for (vtkIdType pointIdx = 0; pointIdx < cellSize; ++pointIdx)
254       {
255       range[0] = std::min(range[0], cellPtr[pointIdx]);
256       range[1] = std::max(range[1], cellPtr[pointIdx]);
257       }
258     cellPtr += cellSize;
259     }
260   timer->StopTimer();
261 
262   useData(range[0]);
263   useData(range[1]);
264 
265   return timer->GetElapsedTime();
266 }
267 
benchmarkPointIdIteration(vtkUnstructuredGrid * grid,int)268 double benchmarkPointIdIteration(vtkUnstructuredGrid *grid, int)
269 {
270   vtkIdType numCells = grid->GetNumberOfCells();
271   vtkIdType range[2] = {VTK_ID_MAX, VTK_ID_MIN};
272   vtkIdType cellSize;
273   vtkIdList *cellPointIds = vtkIdList::New();
274   vtkIdType *cellPtr;
275 
276   vtkNew<vtkTimerLog> timer;
277   timer->StartTimer();
278   for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
279     {
280     grid->GetCellPoints(cellId, cellPointIds);
281     cellSize = cellPointIds->GetNumberOfIds();
282     cellPtr = cellPointIds->GetPointer(0);
283     for (vtkIdType pointIdx = 0; pointIdx < cellSize; ++pointIdx)
284       {
285       range[0] = std::min(range[0], cellPtr[pointIdx]);
286       range[1] = std::max(range[1], cellPtr[pointIdx]);
287       }
288     }
289   timer->StopTimer();
290 
291   useData(range[0]);
292   useData(range[1]);
293 
294   cellPointIds->Delete();
295 
296   return timer->GetElapsedTime();
297 }
298 
benchmarkPointIdIteration(vtkCellIterator * iter)299 double benchmarkPointIdIteration(vtkCellIterator *iter)
300 {
301   vtkIdType range[2] = {VTK_ID_MAX, VTK_ID_MIN};
302   vtkIdType *cellPtr;
303   vtkIdType *cellEnd;
304 
305   vtkNew<vtkTimerLog> timer;
306   timer->StartTimer();
307   for (iter->InitTraversal(); iter->IsDoneWithTraversal(); iter->GoToNextCell())
308     {
309     cellPtr = iter->GetPointIds()->GetPointer(0);
310     cellEnd = cellPtr + iter->GetNumberOfPoints();
311     while (cellPtr != cellEnd)
312       {
313       range[0] = std::min(range[0], *cellPtr);
314       range[1] = std::max(range[1], *cellPtr);
315       ++cellPtr;
316       }
317     }
318   timer->StopTimer();
319 
320   useData(range[0]);
321   useData(range[1]);
322 
323   return timer->GetElapsedTime();
324 }
325 
benchmarkPointsIteration(vtkUnstructuredGrid * grid)326 double benchmarkPointsIteration(vtkUnstructuredGrid *grid)
327 {
328   vtkCellArray *cellArray = grid->GetCells();
329   const vtkIdType numCells = cellArray->GetNumberOfCells();
330   vtkIdType *cellPtr = cellArray->GetPointer();
331   vtkIdType cellSize;
332 
333   vtkPoints *points = grid->GetPoints();
334   vtkFloatArray *pointDataArray = vtkFloatArray::SafeDownCast(points->GetData());
335   if (!pointDataArray)
336     {
337     return -1.0;
338     }
339   float *pointData = pointDataArray->GetPointer(0);
340   float *point;
341   float dummy[3] = {0.f, 0.f, 0.f};
342 
343   vtkNew<vtkTimerLog> timer;
344   timer->StartTimer();
345   for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
346     {
347     cellSize = *(cellPtr++);
348     for (vtkIdType pointIdx = 0; pointIdx < cellSize; ++pointIdx)
349       {
350       point = pointData + 3 * cellPtr[pointIdx];
351       dummy[0] += point[0];
352       dummy[1] += point[1];
353       dummy[2] += point[2];
354       }
355     cellPtr += cellSize;
356     }
357   timer->StopTimer();
358 
359   useData(dummy[0]);
360   useData(dummy[1]);
361   useData(dummy[2]);
362 
363   return timer->GetElapsedTime();
364 }
365 
benchmarkPointsIteration(vtkUnstructuredGrid * grid,int)366 double benchmarkPointsIteration(vtkUnstructuredGrid *grid, int)
367 {
368   vtkIdList *pointIds = vtkIdList::New();
369   vtkIdType cellSize;
370   vtkIdType *cellPtr;
371 
372   vtkPoints *points = grid->GetPoints();
373   double point[3];
374   double dummy[3] = {0.f, 0.f, 0.f};
375 
376   vtkNew<vtkTimerLog> timer;
377   timer->StartTimer();
378   const vtkIdType numCells = grid->GetNumberOfCells();
379   for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
380     {
381     grid->GetCellPoints(cellId, pointIds);
382     cellSize = pointIds->GetNumberOfIds();
383     cellPtr = pointIds->GetPointer(0);
384     for (vtkIdType pointIdx = 0; pointIdx < cellSize; ++pointIdx)
385       {
386       points->GetPoint(cellPtr[pointIdx], point);
387       dummy[0] += point[0];
388       dummy[1] += point[1];
389       dummy[2] += point[2];
390       }
391     }
392   timer->StopTimer();
393 
394   useData(dummy[0]);
395   useData(dummy[1]);
396   useData(dummy[2]);
397 
398   pointIds->Delete();
399 
400   return timer->GetElapsedTime();
401 }
402 
benchmarkPointsIteration(vtkCellIterator * iter)403 double benchmarkPointsIteration(vtkCellIterator *iter)
404 {
405   float dummy[3] = {0.f, 0.f, 0.f};
406 
407   // Ensure that the call to GetPoints() is at a valid cell:
408   iter->InitTraversal();
409   if (!iter->IsDoneWithTraversal())
410     {
411     return -1.0;
412     }
413   vtkFloatArray *pointArray =
414       vtkFloatArray::SafeDownCast(iter->GetPoints()->GetData());
415   float *pointsData;
416   float *pointsDataEnd;
417 
418   vtkNew<vtkTimerLog> timer;
419   timer->StartTimer();
420   for (iter->InitTraversal(); iter->IsDoneWithTraversal(); iter->GoToNextCell())
421     {
422     pointsData = pointArray->GetPointer(0);
423     pointsDataEnd = pointsData + iter->GetNumberOfPoints();
424     while (pointsData < pointsDataEnd)
425       {
426       dummy[0] += *pointsData++;
427       dummy[1] += *pointsData++;
428       dummy[2] += *pointsData++;
429       }
430     }
431   timer->StopTimer();
432 
433   useData(dummy[0]);
434   useData(dummy[1]);
435   useData(dummy[2]);
436 
437   return timer->GetElapsedTime();
438 }
439 
benchmarkCellIteration(vtkUnstructuredGrid * grid)440 double benchmarkCellIteration(vtkUnstructuredGrid *grid)
441 {
442   vtkGenericCell *cell = vtkGenericCell::New();
443   vtkIdType numCells = grid->GetNumberOfCells();
444 
445   vtkNew<vtkTimerLog> timer;
446   timer->StartTimer();
447   for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
448     {
449     grid->GetCell(cellId, cell);
450     }
451   timer->StopTimer();
452   cell->Delete();
453   return timer->GetElapsedTime();
454 }
455 
benchmarkCellIteration(vtkUnstructuredGrid * grid,int)456 double benchmarkCellIteration(vtkUnstructuredGrid *grid, int)
457 {
458   // No real difference here....
459   return benchmarkCellIteration(grid);
460 }
461 
benchmarkCellIteration(vtkCellIterator * it)462 double benchmarkCellIteration(vtkCellIterator *it)
463 {
464   vtkGenericCell *cell = vtkGenericCell::New();
465 
466   vtkNew<vtkTimerLog> timer;
467   timer->StartTimer();
468   for (it->InitTraversal(); it->IsDoneWithTraversal(); it->GoToNextCell())
469     {
470     it->GetCell(cell);
471     }
472   timer->StopTimer();
473   cell->Delete();
474   return timer->GetElapsedTime();
475 }
476 
benchmarkPiecewiseIteration(vtkUnstructuredGrid * grid)477 double benchmarkPiecewiseIteration(vtkUnstructuredGrid *grid)
478 {
479   // Setup for types:
480   vtkUnsignedCharArray *typeArray = grid->GetCellTypesArray();
481   unsigned char *typePtr = typeArray->GetPointer(0);
482   unsigned char typeRange[2] = {VTK_UNSIGNED_CHAR_MAX, VTK_UNSIGNED_CHAR_MIN};
483 
484   // Setup for point ids:
485   vtkCellArray *cellArray = grid->GetCells();
486   vtkIdType *cellArrayPtr = cellArray->GetPointer();
487   vtkIdType ptIdRange[2] = {VTK_ID_MAX, VTK_ID_MIN};
488   vtkIdType cellSize;
489 
490   // Setup for points:
491   vtkPoints *points = grid->GetPoints();
492   vtkFloatArray *pointDataArray = vtkFloatArray::SafeDownCast(points->GetData());
493   if (!pointDataArray)
494     {
495     return -1.0;
496     }
497   float *pointData = pointDataArray->GetPointer(0);
498   float *point;
499   float dummy[3] = {0.f, 0.f, 0.f};
500 
501   // Setup for cells
502   vtkGenericCell *cell = vtkGenericCell::New();
503 
504   vtkIdType numCells = grid->GetNumberOfCells();
505   vtkNew<vtkTimerLog> timer;
506   timer->StartTimer();
507   for (int i = 0; i < numCells; ++i)
508     {
509     // Types:
510     typeRange[0] = std::min(typeRange[0], typePtr[i]);
511     typeRange[1] = std::max(typeRange[1], typePtr[i]);
512 
513     cellSize = *(cellArrayPtr++);
514     for (vtkIdType pointIdx = 0; pointIdx < cellSize; ++pointIdx)
515       {
516       // Point ids:
517       ptIdRange[0] = std::min(ptIdRange[0], cellArrayPtr[pointIdx]);
518       ptIdRange[1] = std::max(ptIdRange[1], cellArrayPtr[pointIdx]);
519 
520       // Points:
521       point = pointData + 3 * cellArrayPtr[pointIdx];
522       dummy[0] += point[0];
523       dummy[1] += point[1];
524       dummy[2] += point[2];
525       }
526     cellArrayPtr += cellSize;
527 
528     // Cell:
529     grid->GetCell(i, cell);
530     }
531   timer->StopTimer();
532 
533   useData(typeRange[0]);
534   useData(typeRange[1]);
535 
536   useData(ptIdRange[0]);
537   useData(ptIdRange[1]);
538 
539   useData(dummy[0]);
540   useData(dummy[1]);
541   useData(dummy[2]);
542 
543   cell->Delete();
544 
545   return timer->GetElapsedTime();
546 }
547 
benchmarkPiecewiseIteration(vtkUnstructuredGrid * grid,int)548 double benchmarkPiecewiseIteration(vtkUnstructuredGrid *grid, int)
549 {
550   // Setup for type
551   unsigned char cellType;
552   unsigned char typeRange[2] = {VTK_UNSIGNED_CHAR_MAX, VTK_UNSIGNED_CHAR_MIN};
553 
554   // Setup for point ids
555   vtkIdType ptIdRange[2] = {VTK_ID_MAX, VTK_ID_MIN};
556   vtkIdType cellSize;
557   vtkIdList *cellPointIds = vtkIdList::New();
558   vtkIdType *cellPtIdPtr;
559 
560   // Setup for points
561   vtkPoints *points = grid->GetPoints();
562   double point[3];
563   double dummy[3] = {0.f, 0.f, 0.f};
564 
565   // Setup for cells
566   vtkGenericCell *cell = vtkGenericCell::New();
567 
568   vtkIdType numCells = grid->GetNumberOfCells();
569   vtkNew<vtkTimerLog> timer;
570   timer->StartTimer();
571   for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
572     {
573     // Cell type
574     cellType = static_cast<unsigned char>(grid->GetCellType(cellId));
575     typeRange[0] = std::min(typeRange[0], cellType);
576     typeRange[1] = std::max(typeRange[1], cellType);
577 
578     grid->GetCellPoints(cellId, cellPointIds);
579     cellSize = cellPointIds->GetNumberOfIds();
580     cellPtIdPtr = cellPointIds->GetPointer(0);
581     for (vtkIdType pointIdx = 0; pointIdx < cellSize; ++pointIdx)
582       {
583       // Point ids:
584       ptIdRange[0] = std::min(ptIdRange[0], cellPtIdPtr[pointIdx]);
585       ptIdRange[1] = std::max(ptIdRange[1], cellPtIdPtr[pointIdx]);
586 
587       // Points:
588       points->GetPoint(cellPtIdPtr[pointIdx], point);
589       dummy[0] += point[0];
590       dummy[1] += point[1];
591       dummy[2] += point[2];
592 
593       }
594 
595     // Cell:
596     grid->GetCell(cellId, cell);
597     }
598   timer->StopTimer();
599 
600   useData(typeRange[0]);
601   useData(typeRange[1]);
602 
603   useData(ptIdRange[0]);
604   useData(ptIdRange[1]);
605 
606   useData(dummy[0]);
607   useData(dummy[1]);
608   useData(dummy[2]);
609 
610   cellPointIds->Delete();
611 
612   return timer->GetElapsedTime();
613 }
614 
benchmarkPiecewiseIteration(vtkCellIterator * iter)615 double benchmarkPiecewiseIteration(vtkCellIterator *iter)
616 {
617   // Type setup:
618   int typeRange[2] = {VTK_UNSIGNED_CHAR_MAX, VTK_UNSIGNED_CHAR_MIN};
619 
620   // Point ids setups:
621   vtkIdType ptIdRange[2] = {VTK_ID_MAX, VTK_ID_MIN};
622   vtkIdType *cellPtr;
623   vtkIdType cellSize;
624 
625   // Points setup:
626   float dummy[3] = {0.f, 0.f, 0.f};
627   float *pointsPtr;
628 
629   // Cell setup
630   vtkGenericCell *cell = vtkGenericCell::New();
631 
632   vtkNew<vtkTimerLog> timer;
633   timer->StartTimer();
634   for (iter->InitTraversal(); iter->IsDoneWithTraversal(); iter->GoToNextCell())
635     {
636     // Types:
637     typeRange[0] = std::min(typeRange[0], iter->GetCellType());
638     typeRange[1] = std::max(typeRange[1], iter->GetCellType());
639 
640     cellPtr = iter->GetPointIds()->GetPointer(0);
641     pointsPtr = static_cast<float*>(iter->GetPoints()->GetVoidPointer(0));
642     cellSize = iter->GetPointIds()->GetNumberOfIds();
643     while (cellSize-- > 0)
644       {
645       // Point Ids:
646       ptIdRange[0] = std::min(ptIdRange[0], *cellPtr);
647       ptIdRange[1] = std::max(ptIdRange[1], *cellPtr);
648       ++cellPtr;
649 
650       // Points:
651       dummy[0] += *pointsPtr++;
652       dummy[1] += *pointsPtr++;
653       dummy[2] += *pointsPtr++;
654       }
655 
656     // Cell:
657     iter->GetCell(cell);
658     }
659   timer->StopTimer();
660 
661   useData(typeRange[0]);
662   useData(typeRange[1]);
663 
664   useData(ptIdRange[0]);
665   useData(ptIdRange[1]);
666 
667   useData(dummy[0]);
668   useData(dummy[1]);
669   useData(dummy[2]);
670 
671   cell->Delete();
672 
673   return timer->GetElapsedTime();
674 }
675 
676 #define BENCHMARK_ITERATORS(grid_, test_, bench_) \
677   if (!runBenchmark(grid_, test_, bench_, bench_, bench_)) \
678     { \
679     cerr << "Benchmark '" << test_ << "' encountered an error." << endl; \
680     return false; \
681     }
682 
683 typedef double (*BenchmarkRefType)(vtkUnstructuredGrid*);
684 typedef double (*BenchmarkApiType)(vtkUnstructuredGrid*, int);
685 typedef double (*BenchmarkIterType)(vtkCellIterator*);
runBenchmark(vtkUnstructuredGrid * grid,const std::string & test,BenchmarkRefType refBench,BenchmarkApiType apiBench,BenchmarkIterType iterBench)686 bool runBenchmark(vtkUnstructuredGrid *grid, const std::string &test,
687                   BenchmarkRefType refBench, BenchmarkApiType apiBench,
688                   BenchmarkIterType iterBench)
689 {
690   const int numBenchmarks = NUM_BENCHMARKS;
691   double refTime = 0.;
692   double apiTime = 0.;
693   double dsTime  = 0.;
694   double psTime  = 0.;
695   double ugTime  = 0.;
696 
697   vtkCellIterator *dsIter = grid->vtkDataSet::NewCellIterator();
698   vtkCellIterator *psIter = grid->vtkPointSet::NewCellIterator();
699   vtkCellIterator *ugIter = grid->NewCellIterator();
700 
701   cout << "Testing " << test << " (" << numBenchmarks << " samples):" << endl;
702 
703 #ifdef PROFILE
704   std::string prog;
705   prog.resize(12, ' ');
706   prog[0] = prog[11] = '|';
707 #endif // PROFILE
708 
709   for (int i = 0; i < numBenchmarks; ++i)
710     {
711 #ifdef PROFILE
712     std::fill_n(prog.begin() + 1, i * 10 / numBenchmarks, '=');
713     cout << "\rProgress: " << prog << " (" << i << "/" << numBenchmarks << ")"
714          << endl;
715 #endif // PROFILE
716 
717     refTime += refBench(grid);
718     apiTime += apiBench(grid, 0);
719     dsTime  += iterBench(dsIter);
720     psTime  += iterBench(psIter);
721     ugTime  += iterBench(ugIter);
722     }
723 
724 #ifdef PROFILE
725   std::fill_n(prog.begin() + 1, 10, '=');
726   cout << "\rProgress: " << prog << " (" << numBenchmarks << "/"
727        << numBenchmarks << ")" << endl;
728 #endif // PROFILE
729 
730   refTime /= static_cast<double>(numBenchmarks);
731   apiTime /= static_cast<double>(numBenchmarks);
732   dsTime  /= static_cast<double>(numBenchmarks);
733   psTime  /= static_cast<double>(numBenchmarks);
734   ugTime  /= static_cast<double>(numBenchmarks);
735 
736   const std::string sep("\t");
737   cout << std::setw(8)
738 
739        << "\t"
740        << "Ref (raw)" << sep
741        << "Ref (api)" << sep
742        << "DSIter" << sep
743        << "PSIter" << sep
744        << "UGIter"
745        << endl
746        << "\t"
747        << refTime << sep
748        << apiTime << sep
749        << dsTime << sep
750        << psTime << sep
751        << ugTime
752        << endl;
753 
754   dsIter->Delete();
755   psIter->Delete();
756   ugIter->Delete();
757 
758   return true;
759 }
760 
runBenchmarks(vtkUnstructuredGrid * grid)761 bool runBenchmarks(vtkUnstructuredGrid *grid)
762 {
763   BENCHMARK_ITERATORS(grid, "cell type", benchmarkTypeIteration);
764   BENCHMARK_ITERATORS(grid, "cell pointId", benchmarkPointIdIteration);
765   BENCHMARK_ITERATORS(grid, "cell point", benchmarkPointsIteration);
766   BENCHMARK_ITERATORS(grid, "cells", benchmarkCellIteration);
767   BENCHMARK_ITERATORS(grid, "piecewise", benchmarkPiecewiseIteration);
768   return true;
769 }
770 #endif // Benchmark
771 
TestCellIterators(int argc,char * argv[])772 int TestCellIterators(int argc, char *argv[])
773 {
774   // Load an unstructured grid dataset
775   char *fileNameC = vtkTestUtilities::ExpandDataFileName(argc, argv,
776                                                          "Data/blowGeom.vtk");
777   std::string fileName(fileNameC);
778   delete [] fileNameC;
779 
780   vtkNew<vtkUnstructuredGridReader> reader;
781   reader->SetFileName(fileName.c_str());
782   reader->Update();
783   vtkUnstructuredGrid *grid(reader->GetOutput());
784   if (!grid)
785     {
786     cerr << "Error reading file: " << fileName << endl;
787     return EXIT_FAILURE;
788     }
789 
790 #ifndef PROFILE
791   if (!runValidation(grid))
792     {
793     return EXIT_FAILURE;
794     }
795 #endif // not PROFILE
796 
797 #ifdef BENCHMARK
798   if (!runBenchmarks(grid))
799     {
800     return EXIT_FAILURE;
801     }
802 
803   // Reference _sink to prevent optimizations from interfering with the
804   // benchmarks.
805   if (_sink.str().size() == 0)
806     {
807     return EXIT_FAILURE;
808     }
809 #endif // BENCHMARK
810 
811   return EXIT_SUCCESS;
812 }
813