1 /*=========================================================================
2 
3 Copyright (c) Kitware Inc.
4 All rights reserved.
5 
6 =========================================================================*/
7 // .SECTION Description
8 // This program illustrates the use of various filters acting upon hyper
9 // tree grid data sets. It generates output files in VTK format.
10 //
11 // .SECTION Usage
12 //   --branch-factor opt  Branching factor of hyper tree grid
13 //   --dimension opt      Dimension of hyper tree grid
14 //   --grid-size-X opt    Size of hyper tree grid in X direction
15 //   --grid-size-Y opt    Size of hyper tree grid in Y direction
16 //   --grid-size-Z opt    Size of hyper tree grid in Z direction
17 //   --descriptor         String of characters specifying tree structure
18 //   --max-level opt      Maximum depth of hyper tree grid
19 //   --contours           Number of iso-contours to be calculated
20 //   --skip-Axis-Cut      Skip axis cut filter
21 //   --skip-Contour       Skip contour filter
22 //   --skip-Cut           Skip cut filter
23 //   --skip-Geometry      Skip geometry filter
24 //   --skip-Shrink        Skip shrink filter
25 //
26 // .SECTION Thanks
27 // This example was written by Philippe Pebay and Charles Law, Kitware 2012
28 // This work was supported in part by Commissariat a l'Energie Atomique (CEA/DIF)
29 
30 #include "vtkHyperTreeGrid.h"
31 #include "vtkHyperTreeGridAxisCut.h"
32 #include "vtkHyperTreeGridSource.h"
33 #include "vtkHyperTreeGridGeometry.h"
34 
35 #include "vtkContourFilter.h"
36 #include "vtkCutter.h"
37 #include "vtkDataSetWriter.h"
38 #include "vtkMath.h"
39 #include "vtkNew.h"
40 #include "vtkPlane.h"
41 #include "vtkPointData.h"
42 #include "vtkPolyDataWriter.h"
43 #include "vtkShrinkFilter.h"
44 #include "vtkStdString.h"
45 #include "vtkTimerLog.h"
46 #include "vtkUnstructuredGrid.h"
47 #include "vtkUnstructuredGridWriter.h"
48 
49 #include "vtksys/CommandLineArguments.hxx"
50 
51 #include <vtksys/ios/sstream>
52 
SetInputParameters(int & dim,int & branch,int & nX,int & nY,int & nZ,int max,vtkStdString & str)53 void SetInputParameters( int& dim,
54                          int& branch,
55                          int& nX,
56                          int& nY,
57                          int& nZ,
58                          int max,
59                          vtkStdString& str )
60 {
61   // Ensure that parsed dimensionality makes sense
62   if ( dim > 3 )
63     {
64     dim = 3;
65     }
66   else if ( dim < 1 )
67     {
68     dim = 1;
69     }
70 
71   // Ensure that parsed branch factor makes sense
72   if ( branch > 3 )
73     {
74     branch = 3;
75     }
76   else if ( branch < 2 )
77     {
78     branch = 2;
79     }
80 
81   // Ensure that parsed grid sizes make sense
82   if ( nX < 1 )
83     {
84     nX = 1;
85     }
86   if ( nY < 1 )
87     {
88     nY = 1;
89     }
90   if ( nZ < 1 )
91     {
92     nZ = 1;
93     }
94 
95   // Ensure that parsed grid sizes are consistent with dimensionality
96   if ( dim < 3 )
97     {
98     nZ = 1;
99     if ( dim < 2 )
100       {
101       nY = 1;
102       }
103     }
104 
105   // Ensure that maximum level makes sense
106   if ( max < 1 )
107     {
108     max = 1;
109     }
110 
111   // Generate a descriptor if none was provided
112   if ( str = "" )
113     {
114     // Calculate refined block size
115     int blockSize = branch;
116     for ( int i = 1; i < dim; ++ i )
117       {
118       blockSize *= branch;
119       }
120 
121     // Initialize character stream
122     vtksys_ios::ostringstream stream;
123 
124     // Seed random number generator
125     vtkMath::RandomSeed( static_cast<int>( vtkTimerLog::GetUniversalTime() ) );
126 
127     // Initialize per-level cardinality
128     int cardLevel = nX * nY * nZ;
129 
130     // Iterate over refinement levels
131     for ( int l = 0; l < max - 1; ++ l )
132       {
133       // Initialize counters for this level
134       int nRefined = 0;
135       int nLeaves = 0;
136 
137       // Insert separator if not first level
138       if ( l )
139         {
140         stream << '|';
141         }
142 
143       // Iterate over entries in this level
144       for ( int i = 0; i < cardLevel; ++ i )
145         {
146         // Generate next character based on pseudo-random clause
147         double u = vtkMath::Random();
148         if ( u < .3 )
149           {
150           // Refined cell
151           stream << 'R';
152           ++ nRefined;
153           } // if ( u < .1 )
154         else
155           {
156           // Leaf cell
157           stream << '.';
158           ++ nLeaves;
159           } // else
160         } // i
161 
162       // Update cardinality for next level
163       cardLevel = nRefined * blockSize;
164       } // l
165 
166     // Last level contains only leaf cells
167     if ( max > 1 )
168       {
169       // Insert separator if not first level
170       stream << '|';
171       }
172     // Iterate over entries in this level
173     for ( int i = 0; i < cardLevel; ++ i )
174       {
175       stream << '.';
176       }
177 
178     // Finally dump stream into descriptor
179     str = stream.str();
180 
181     } // if ( str = "" )
182 }
183 
main(int argc,char * argv[])184   int main( int argc, char* argv[] )
185 {
186   // Set default argument values and options
187   vtkStdString descriptor = "";
188   int dim = 3;
189   int branch = 3;
190   int max = 3;
191   int nX = 2;
192   int nY = 3;
193   int nZ = 2;
194   double sX = 1.5;
195   double sY = 1.;
196   double sZ = .7;
197   int nContours = 1;
198   bool skipAxisCut = false;
199   bool skipContour = false;
200   bool skipCut = false;
201   bool skipGeometry = false;
202   bool skipShrink = false;
203   bool printDescriptor = false;
204 
205   // Initialize command line argument parser
206   vtksys::CommandLineArguments clArgs;
207   clArgs.Initialize( argc, argv );
208   clArgs.StoreUnusedArguments( false );
209 
210   // Parse command line parameters and options
211   clArgs.AddArgument( "--dimension",
212                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
213                       &dim, "Dimension of hyper tree grid" );
214 
215   clArgs.AddArgument( "--branch-factor",
216                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
217                       &branch, "Branching factor of hyper tree grid" );
218 
219   clArgs.AddArgument( "--max-level",
220                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
221                       &max, "Maximum depth of hyper tree grid" );
222 
223   clArgs.AddArgument("--descriptor",
224                      vtksys::CommandLineArguments::SPACE_ARGUMENT,
225                      &descriptor, "String describing the hyper tree grid");
226 
227   clArgs.AddArgument( "--grid-size-X",
228                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
229                       &nX, "Size of hyper tree grid in X direction" );
230 
231   clArgs.AddArgument( "--grid-size-Y",
232                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
233                       &nY, "Size of hyper tree grid in Y direction" );
234 
235   clArgs.AddArgument( "--grid-size-Z",
236                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
237                       &nZ, "Size of hyper tree grid in Z direction" );
238 
239   clArgs.AddArgument( "--grid-scale-X",
240                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
241                       &sX, "Scale of hyper tree grid in X direction" );
242 
243   clArgs.AddArgument( "--grid-scale-Y",
244                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
245                       &sY, "Scale of hyper tree grid in Y direction" );
246 
247   clArgs.AddArgument( "--grid-scale-Z",
248                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
249                       &sZ, "Scale of hyper tree grid in Z direction" );
250 
251   clArgs.AddArgument( "--contours",
252                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
253                       &nContours, "Number of iso-contours to be calculated" );
254 
255   clArgs.AddArgument( "--skip-Axis-Cut",
256                       vtksys::CommandLineArguments::NO_ARGUMENT,
257                       &skipAxisCut, "Skip axis cut filter" );
258 
259   clArgs.AddArgument( "--skip-Contour",
260                       vtksys::CommandLineArguments::NO_ARGUMENT,
261                       &skipContour, "Skip contour filter" );
262 
263   clArgs.AddArgument( "--skip-Cut",
264                       vtksys::CommandLineArguments::NO_ARGUMENT,
265                       &skipCut, "Skip cut filter" );
266 
267   clArgs.AddArgument( "--skip-Geometry",
268                       vtksys::CommandLineArguments::NO_ARGUMENT,
269                       &skipGeometry, "Skip geometry filter" );
270 
271   clArgs.AddArgument( "--skip-Shrink",
272                       vtksys::CommandLineArguments::NO_ARGUMENT,
273                       &skipShrink, "Skip shrink filter" );
274 
275   clArgs.AddArgument( "--print-Descriptor",
276                       vtksys::CommandLineArguments::NO_ARGUMENT,
277                       &printDescriptor, "Print descriptor string" );
278 
279   // If incorrect arguments were provided, provide some help and terminate in error.
280   if ( ! clArgs.Parse() )
281     {
282     cerr << "Usage: "
283          << clArgs.GetHelp()
284          << "\n";
285     return 1;
286     }
287 
288   // Verify and set input parameters
289   SetInputParameters( dim, branch, nX, nY, nZ, max, descriptor );
290   if ( printDescriptor )
291     {
292     cerr << "# Hyper tree grid descriptor: "
293          << endl
294          << descriptor
295          << endl;
296     }
297 
298   // Create hyper tree grid source
299   vtkNew<vtkHyperTreeGridSource> source;
300   source->DualOn();
301   source->SetGridSize( nX, nY, nZ );
302   source->SetGridScale( sX, sY, sZ );
303   source->SetDimension( dim );
304   source->SetAxisBranchFactor( branch );
305   source->SetMaximumLevel( max );
306   source->SetDescriptor( descriptor.c_str() );
307   source->Update();
308   vtkHyperTreeGrid* htGrid = source->GetOutput();
309   cerr << "  Number of hyper tree dual grid cells: "
310        << htGrid->GetNumberOfCells()
311        << endl;
312 
313   if ( ! skipGeometry )
314     {
315     cerr << "# Geometry" << endl;
316     vtkNew<vtkHyperTreeGridGeometry> geometry;
317     geometry->SetInputConnection( source->GetOutputPort() );
318     vtkNew<vtkPolyDataWriter> writer4;
319     writer4->SetFileName( "./hyperTreeGridGeometry.vtk" );
320     writer4->SetInputConnection( geometry->GetOutputPort() );
321     writer4->Write();
322     cerr << "  Number of surface cells: "
323          << geometry->GetOutput()->GetNumberOfCells()
324          << endl;
325     }
326 
327   if ( ! skipContour )
328     {
329     cerr << "# Contour" << endl;
330     vtkNew<vtkContourFilter> contour;
331     contour->SetInputData( htGrid );
332     double* range = htGrid->GetPointData()->GetScalars()->GetRange();
333     cerr << "  Calculating "
334          << nContours
335          << " iso-contours across ["
336          << range[0]
337          << ", "
338          << range[1]
339          << "] range:"
340          << endl;
341     contour->SetNumberOfContours( nContours );
342     double resolution = ( range[1] - range[0] ) / ( nContours + 1. );
343     double isovalue = resolution;
344     for ( int i = 0; i < nContours; ++ i, isovalue += resolution )
345       {
346       cerr << "    Contour "
347            << i
348            << " at iso-value: "
349            << isovalue
350            << endl;
351       contour->SetValue( i, isovalue );
352       }
353     vtkNew<vtkPolyDataWriter> writer0;
354     writer0->SetFileName( "./hyperTreeGridContour.vtk" );
355     writer0->SetInputConnection( contour->GetOutputPort() );
356     writer0->Write();
357     cerr << "  Number of cells in iso-contours: "
358          << contour->GetOutput()->GetNumberOfCells()
359          << endl;
360     }
361 
362   if ( ! skipShrink )
363     {
364     cerr << "# Shrink" << endl;
365     vtkNew<vtkShrinkFilter> shrink;
366     shrink->SetInputData( htGrid );
367     shrink->SetShrinkFactor( .5 );
368     vtkNew<vtkUnstructuredGridWriter> writer1;
369     writer1->SetFileName( "./hyperTreeGridShrink.vtk" );
370     writer1->SetInputConnection( shrink->GetOutputPort() );
371     writer1->Write();
372     cerr << "  Number of shrunk cells: "
373          << shrink->GetOutput()->GetNumberOfCells()
374          << endl;
375     }
376 
377   if ( ! skipAxisCut )
378     {
379     // Axis-aligned cut works only in 3D for now
380     if ( dim == 3 )
381       {
382       cerr << "# HyperTreeGridAxisCut" << endl;
383       vtkNew<vtkHyperTreeGridAxisCut> axisCut;
384       axisCut->SetInputConnection( source->GetOutputPort() );
385       axisCut->SetPlaneNormalAxis( 2 );
386       axisCut->SetPlanePosition( .499 * nZ * sZ );
387       vtkNew<vtkPolyDataWriter> writer2;
388       writer2->SetFileName( "./hyperTreeGridAxisCut.vtk" );
389       writer2->SetInputConnection( axisCut->GetOutputPort() );
390       writer2->Write();
391       cerr << "  Number of cells in axis cut: "
392            << axisCut->GetOutput()->GetNumberOfCells()
393            << endl;
394       }
395     }
396 
397   if ( ! skipCut )
398     {
399     cerr << "# Cut" << endl;
400     vtkNew<vtkCutter> cut;
401     vtkNew<vtkPlane> plane;
402     plane->SetOrigin( .5, .5, .15 );
403     plane->SetNormal( 0, 0, 1 );
404     cut->SetInputData( htGrid );
405     cut->SetCutFunction( plane.GetPointer() );
406     vtkNew<vtkPolyDataWriter> writer3;
407     writer3->SetFileName( "./hyperTreeGridCut.vtk" );
408     writer3->SetInputConnection( cut->GetOutputPort() );
409     writer3->Write();
410     cerr << "  Number of cells in generic cut: "
411          << cut->GetOutput()->GetNumberOfCells()
412          << endl;
413     }
414 
415   return 0;
416 }
417