text: /*=========================================================================
  
  Copyright (c) Kitware Inc.
  All rights reserved.
  
  =========================================================================*/
  // .SECTION Description
  // This program illustrates the use of various filters acting upon hyper
  // tree grid data sets. It generates output files in VTK format.
  //
  // .SECTION Usage
  //   --branch-factor opt  Branching factor of hyper tree grid
  //   --dimension opt      Dimension of hyper tree grid
  //   --grid-size-X opt    Size of hyper tree grid in X direction
  //   --grid-size-Y opt    Size of hyper tree grid in Y direction
  //   --grid-size-Z opt    Size of hyper tree grid in Z direction
  //   --descriptor         String of characters specifying tree structure
  //   --max-level opt      Maximum depth of hyper tree grid
  //   --contours           Number of iso-contours to be calculated
  //   --skip-Axis-Cut      Skip axis cut filter
  //   --skip-Contour       Skip contour filter
  //   --skip-Cut           Skip cut filter
  //   --skip-Geometry      Skip geometry filter
  //   --skip-Shrink        Skip shrink filter
  //
  // .SECTION Thanks
  // This example was written by Philippe Pebay and Charles Law, Kitware 2012
  // This work was supported in part by Commissariat a l'Energie Atomique (CEA/DIF)
  
  #include "vtkHyperTreeGrid.h"
  #include "vtkHyperTreeGridAxisCut.h"
  #include "vtkHyperTreeGridSource.h"
  #include "vtkHyperTreeGridGeometry.h"
  
  #include "vtkContourFilter.h"
  #include "vtkCutter.h"
  #include "vtkDataSetWriter.h"
  #include "vtkMath.h"
  #include "vtkNew.h"
  #include "vtkPlane.h"
  #include "vtkPointData.h"
  #include "vtkPolyDataWriter.h"
  #include "vtkShrinkFilter.h"
  #include "vtkStdString.h"
  #include "vtkTimerLog.h"
  #include "vtkUnstructuredGrid.h"
  #include "vtkUnstructuredGridWriter.h"
  
  #include "vtksys/CommandLineArguments.hxx"
  
  #include <sstream>
  
  void SetInputParameters( int& dim,
                           int& branch,
                           int& nX,
                           int& nY,
                           int& nZ,
                           int max,
                           vtkStdString& str )
  {
    // Ensure that parsed dimensionality makes sense
    if ( dim > 3 )
      {
      dim = 3;
      }
    else if ( dim < 1 )
      {
      dim = 1;
      }
  
    // Ensure that parsed branch factor makes sense
    if ( branch > 3 )
      {
      branch = 3;
      }
    else if ( branch < 2 )
      {
      branch = 2;
      }
  
    // Ensure that parsed grid sizes make sense
    if ( nX < 1 )
      {
      nX = 1;
      }
    if ( nY < 1 )
      {
      nY = 1;
      }
    if ( nZ < 1 )
      {
      nZ = 1;
      }
  
    // Ensure that parsed grid sizes are consistent with dimensionality
    if ( dim < 3 )
      {
      nZ = 1;
      if ( dim < 2 )
        {
        nY = 1;
        }
      }
  
    // Ensure that maximum level makes sense
    if ( max < 1 )
      {
      max = 1;
      }
  
    // Generate a descriptor if none was provided
    if ( str = "" )
      {
      // Calculate refined block size
      int blockSize = branch;
      for ( int i = 1; i < dim; ++ i )
        {
        blockSize *= branch;
        }
  
      // Initialize character stream
      std::ostringstream stream;
  
      // Seed random number generator
      vtkMath::RandomSeed( static_cast<int>( vtkTimerLog::GetUniversalTime() ) );
  
      // Initialize per-level cardinality
      int cardLevel = nX * nY * nZ;
  
      // Iterate over refinement levels
      for ( int l = 0; l < max - 1; ++ l )
        {
        // Initialize counters for this level
        int nRefined = 0;
        int nLeaves = 0;
  
        // Insert separator if not first level
        if ( l )
          {
          stream << '|';
          }
  
        // Iterate over entries in this level
        for ( int i = 0; i < cardLevel; ++ i )
          {
          // Generate next character based on pseudo-random clause
          double u = vtkMath::Random();
          if ( u < .3 )
            {
            // Refined cell
            stream << 'R';
            ++ nRefined;
            } // if ( u < .1 )
          else
            {
            // Leaf cell
            stream << '.';
            ++ nLeaves;
            } // else
          } // i
        
        // Update cardinality for next level 
        cardLevel = nRefined * blockSize;
        } // l
  
      // Last level contains only leaf cells
      if ( max > 1 )
        {
        // Insert separator if not first level
        stream << '|';
        }
      // Iterate over entries in this level
      for ( int i = 0; i < cardLevel; ++ i )
        {
        stream << '.';
        }
  
      // Finally dump stream into descriptor
      str = stream.str();
      
      } // if ( str = "" )
  }
  
    int main( int argc, char* argv[] )
  {
    // Set default argument values and options
    vtkStdString descriptor = "";
    int dim = 3;
    int branch = 3;
    int max = 3;
    int nX = 2;
    int nY = 3;
    int nZ = 2;
    double sX = 1.5;
    double sY = 1.;
    double sZ = .7;
    int nContours = 1;
    bool skipAxisCut = false;
    bool skipContour = false;
    bool skipCut = false;
    bool skipGeometry = false;
    bool skipShrink = false;
    bool printDescriptor = false;
  
    // Initialize command line argument parser
    vtksys::CommandLineArguments clArgs;
    clArgs.Initialize( argc, argv );
    clArgs.StoreUnusedArguments( false );
  
    // Parse command line parameters and options
    clArgs.AddArgument( "--dimension",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &dim, "Dimension of hyper tree grid" );
  
    clArgs.AddArgument( "--branch-factor",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &branch, "Branching factor of hyper tree grid" );
  
    clArgs.AddArgument( "--max-level",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &max, "Maximum depth of hyper tree grid" );
  
    clArgs.AddArgument("--descriptor",
                       vtksys::CommandLineArguments::SPACE_ARGUMENT,
                       &descriptor, "String describing the hyper tree grid");
  
    clArgs.AddArgument( "--grid-size-X",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &nX, "Size of hyper tree grid in X direction" );
  
    clArgs.AddArgument( "--grid-size-Y",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &nY, "Size of hyper tree grid in Y direction" );
  
    clArgs.AddArgument( "--grid-size-Z",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &nZ, "Size of hyper tree grid in Z direction" );
  
    clArgs.AddArgument( "--grid-scale-X",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &sX, "Scale of hyper tree grid in X direction" );
  
    clArgs.AddArgument( "--grid-scale-Y",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &sY, "Scale of hyper tree grid in Y direction" );
  
    clArgs.AddArgument( "--grid-scale-Z",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &sZ, "Scale of hyper tree grid in Z direction" );
  
    clArgs.AddArgument( "--contours",
                        vtksys::CommandLineArguments::SPACE_ARGUMENT,
                        &nContours, "Number of iso-contours to be calculated" );
  
    clArgs.AddArgument( "--skip-Axis-Cut",
                        vtksys::CommandLineArguments::NO_ARGUMENT,
                        &skipAxisCut, "Skip axis cut filter" );
  
    clArgs.AddArgument( "--skip-Contour",
                        vtksys::CommandLineArguments::NO_ARGUMENT,
                        &skipContour, "Skip contour filter" );
  
    clArgs.AddArgument( "--skip-Cut",
                        vtksys::CommandLineArguments::NO_ARGUMENT,
                        &skipCut, "Skip cut filter" );
  
    clArgs.AddArgument( "--skip-Geometry",
                        vtksys::CommandLineArguments::NO_ARGUMENT,
                        &skipGeometry, "Skip geometry filter" );
  
    clArgs.AddArgument( "--skip-Shrink",
                        vtksys::CommandLineArguments::NO_ARGUMENT,
                        &skipShrink, "Skip shrink filter" );
  
    clArgs.AddArgument( "--print-Descriptor",
                        vtksys::CommandLineArguments::NO_ARGUMENT,
                        &printDescriptor, "Print descriptor string" );
  
    // If incorrect arguments were provided, provide some help and terminate in error.
    if ( ! clArgs.Parse() )
      {
      cerr << "Usage: "
           << clArgs.GetHelp()
           << "\n";
      return 1;
      }
  
    // Verify and set input parameters
    SetInputParameters( dim, branch, nX, nY, nZ, max, descriptor );
    if ( printDescriptor )
      {
      cerr << "# Hyper tree grid descriptor: "
           << endl
           << descriptor
           << endl;
      }
  
    // Create hyper tree grid source
    vtkNew<vtkHyperTreeGridSource> source;
    source->DualOn();
    source->SetGridSize( nX, nY, nZ );
    source->SetGridScale( sX, sY, sZ );
    source->SetDimension( dim );
    source->SetAxisBranchFactor( branch );
    source->SetMaximumLevel( max );
    source->SetDescriptor( descriptor.c_str() );
    source->Update();
    vtkHyperTreeGrid* htGrid = source->GetOutput();
    cerr << "  Number of hyper tree dual grid cells: "
         << htGrid->GetNumberOfCells()
         << endl;
  
    if ( ! skipGeometry )
      {
      cerr << "# Geometry" << endl;
      vtkNew<vtkHyperTreeGridGeometry> geometry;
      geometry->SetInputConnection( source->GetOutputPort() );
      vtkNew<vtkPolyDataWriter> writer4;
      writer4->SetFileName( "./hyperTreeGridGeometry.vtk" );
      writer4->SetInputConnection( geometry->GetOutputPort() );
      writer4->Write();
      cerr << "  Number of surface cells: "
           << geometry->GetOutput()->GetNumberOfCells()
           << endl;
      }
  
    if ( ! skipContour )
      {
      cerr << "# Contour" << endl;
      vtkNew<vtkContourFilter> contour;
      contour->SetInputData( htGrid );
      double* range = htGrid->GetPointData()->GetScalars()->GetRange();
      cerr << "  Calculating "
           << nContours
           << " iso-contours across ["
           << range[0]
           << ", "
           << range[1]
           << "] range:"
           << endl;
      contour->SetNumberOfContours( nContours );
      double resolution = ( range[1] - range[0] ) / ( nContours + 1. );
      double isovalue = resolution;
      for ( int i = 0; i < nContours; ++ i, isovalue += resolution )
        {
        cerr << "    Contour "
             << i
             << " at iso-value: "
             << isovalue
             << endl;
        contour->SetValue( i, isovalue );
        }
      vtkNew<vtkPolyDataWriter> writer0;
      writer0->SetFileName( "./hyperTreeGridContour.vtk" );
      writer0->SetInputConnection( contour->GetOutputPort() );
      writer0->Write();
      cerr << "  Number of cells in iso-contours: "
           << contour->GetOutput()->GetNumberOfCells()
           << endl;
      }
  
    if ( ! skipShrink )
      {
      cerr << "# Shrink" << endl;
      vtkNew<vtkShrinkFilter> shrink;
      shrink->SetInputData( htGrid );
      shrink->SetShrinkFactor( .5 );
      vtkNew<vtkUnstructuredGridWriter> writer1;
      writer1->SetFileName( "./hyperTreeGridShrink.vtk" );
      writer1->SetInputConnection( shrink->GetOutputPort() );
      writer1->Write();
      cerr << "  Number of shrunk cells: "
           << shrink->GetOutput()->GetNumberOfCells()
           << endl;
      }
  
    if ( ! skipAxisCut )
      {
      // Axis-aligned cut works only in 3D for now
      if ( dim == 3 )
        {
        cerr << "# HyperTreeGridAxisCut" << endl;
        vtkNew<vtkHyperTreeGridAxisCut> axisCut;
        axisCut->SetInputConnection( source->GetOutputPort() );
        axisCut->SetPlaneNormalAxis( 2 );
        axisCut->SetPlanePosition( .499 * nZ * sZ );
        vtkNew<vtkPolyDataWriter> writer2;
        writer2->SetFileName( "./hyperTreeGridAxisCut.vtk" );
        writer2->SetInputConnection( axisCut->GetOutputPort() );
        writer2->Write();
        cerr << "  Number of cells in axis cut: "
             << axisCut->GetOutput()->GetNumberOfCells()
             << endl;
        }
      }
  
    if ( ! skipCut )
      {
      cerr << "# Cut" << endl;
      vtkNew<vtkCutter> cut;
      vtkNew<vtkPlane> plane;
      plane->SetOrigin( .5, .5, .15 );
      plane->SetNormal( 0, 0, 1 );
      cut->SetInputData( htGrid );
      cut->SetCutFunction( plane.GetPointer() );
      vtkNew<vtkPolyDataWriter> writer3;
      writer3->SetFileName( "./hyperTreeGridCut.vtk" );
      writer3->SetInputConnection( cut->GetOutputPort() );
      writer3->Write();
      cerr << "  Number of cells in generic cut: "
           << cut->GetOutput()->GetNumberOfCells()
           << endl;
      }
  
    return 0;
  }
  