# CompareRandomGeneratorsCxx

VTKExamples/Cxx/Plotting/CompareRandomGeneratorsCxx

## Description

This example demonstrates 6 random number generators offered by c++11. These are now part of the C++ standard. They offer a different API and more generators than presented the vtk generators vtkMinimalStandardRandomSequence, vtkBoxMuellerRandomSequence, vtkGaussianRandomSequence and vtkMersenneTwister.

The vtkRandomSequence generators are used internally by vtk classes, but application developers may prefer to use the C++ standard generators.

The c++ standard random number collections is described here.

### Code

CompareRandomGeneratorsCxx.cxx

    #include <vtkSmartPointer.h>
    #include <vtkBarChartActor.h>

    #include <vtkMath.h>
    #include <vtkActor.h>
    #include <vtkActor2D.h>
    #include <vtkFieldData.h>
    #include <vtkIntArray.h>
    #include <vtkLegendBoxActor.h>
    #include <vtkProperty2D.h>
    #include <vtkTextProperty.h>
    #include <vtkTextMapper.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkNamedColors.h>
    #include <vtkDataObject.h>

    #include <map>
    #include <random>
    #include <valarray>
    #include <array>
    #include <algorithm>

    namespace
    {
    vtkSmartPointer<vtkIntArray> CreateUniformDistribution(int, double, double);
    vtkSmartPointer<vtkIntArray> CreateNormalDistribution(int, double, double);
    vtkSmartPointer<vtkIntArray> CreateWeibullDistribution(int, double, double);
    vtkSmartPointer<vtkIntArray> CreateGammaDistribution(int, double, double);
    vtkSmartPointer<vtkIntArray> CreateCauchyDistribution(int, double, double);
    vtkSmartPointer<vtkIntArray> CreateExtremeValueDistribution(int, double, double);
    }
    int main( int, char *[] )
    {

      vtkSmartPointer<vtkNamedColors> colors =
        vtkSmartPointer<vtkNamedColors>::New();

      vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();

      int count = 100000;
      std::map<std::string, vtkSmartPointer<vtkIntArray> > frequencies;
      frequencies["Uniform Distribution"] = CreateUniformDistribution(count, -200.0, 200.0);
      frequencies["Normal Distribution"] = CreateNormalDistribution(count, 0.0, 6.0);
      frequencies["Weibull Distribution"] = CreateWeibullDistribution(count, 1.5, 1.0);
      frequencies["Gamma Distribution"] = CreateGammaDistribution(count, 2.0, 2.0);
      frequencies["Cauchy Distribution"] = CreateCauchyDistribution(count, -1.0, 2.0);
      frequencies["Extreme Value Distribution"] = CreateExtremeValueDistribution(count, .5, 1.0);

      std::vector<vtkSmartPointer<vtkRenderer> > renderers;

      for (auto fit = frequencies.begin(); fit != frequencies.end(); fit++)
      {
        vtkSmartPointer<vtkBarChartActor> chart=
          vtkSmartPointer<vtkBarChartActor>::New();

        vtkSmartPointer<vtkDataObject> dataObject =
          vtkSmartPointer<vtkDataObject>::New();
        dataObject->GetFieldData()->AddArray(fit->second);

        chart->SetInput( dataObject );
        chart->SetTitle( fit->first.c_str());
        chart->GetPositionCoordinate()->SetValue(0.05,0.05,0.0);
        chart->GetPosition2Coordinate()->SetValue(0.95,0.85,0.0);
        chart->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());
        chart->LegendVisibilityOff();
        chart->LabelVisibilityOff();
        chart->TitleVisibilityOff();
        for( int c = 0; c < count; ++c )
        {
          chart->SetBarColor( c, colors->GetColor3d("Tomato").GetData());
        }
        // Create a title
        vtkSmartPointer<vtkTextProperty> titleProperty =
          vtkSmartPointer<vtkTextProperty>::New();
        titleProperty->SetFontSize(16);
        titleProperty->SetJustificationToCentered();

        vtkSmartPointer<vtkTextMapper> titleMapper =
          vtkSmartPointer<vtkTextMapper>::New();
        titleMapper->SetInput(fit->first.c_str());
        titleMapper->SetTextProperty(titleProperty);

        vtkSmartPointer<vtkActor2D> titleActor =
          vtkSmartPointer<vtkActor2D>::New();
        titleActor->SetMapper(titleMapper);
        titleActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
        titleActor->GetPositionCoordinate()->SetValue(.5, .85, 0.0);
        titleActor->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());

        vtkSmartPointer<vtkRenderer> renderer =
          vtkSmartPointer<vtkRenderer>::New();
        renderer->AddActor(chart);
        renderer->AddActor(titleActor);
        renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());
        renderers.push_back(renderer);
        renderWindow->AddRenderer(renderer);
      }

      // Setup a grid of renderers
      int gridCols = 3;
      int gridRows = 2;

      // Define side length (in pixels) of each renderer square
      int rendererSize = 300;

      renderWindow->SetWindowName("Geometric Objects Demo");
      renderWindow->SetSize(rendererSize*gridCols, rendererSize*gridRows);

      // Set up a grid of viewports for each renderer
      int r = 0;
      for( double row = 0; row < gridRows; row++ )
      {
        for( double col = 0; col < gridCols; col++ )
        {
          double index = row*gridCols + col;

          // Set the renderer's viewport dimensions (xmin, ymin, xmax, ymax) within the render window.
          // Note that for the Y values, we need to subtract the row index from gridRows
          // because the viewport Y axis points upwards, but we want to draw the grid from top to down
          double viewport[4] = {
            static_cast<double>(col) / gridCols,
            static_cast<double>(gridRows - row - 1) / gridRows,
            static_cast<double>(col + 1) / gridCols,
            static_cast<double>(gridRows - row) / gridRows };
          renderers[r]->SetViewport(viewport);
          ++r;
        }
      }

      vtkSmartPointer<vtkRenderWindowInteractor> interactor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
      interactor->SetRenderWindow( renderWindow );

      renderWindow->Render();

      // Initialize the event loop and then start it
      interactor->Initialize();
      interactor->Start();

      return  EXIT_SUCCESS;
    }
    namespace
    {
    vtkSmartPointer<vtkIntArray> CreateUniformDistribution(int count, double a, double b)
    {
      std::mt19937 generator(8775070);
      double rmin, rmax;
      rmax = b;
      rmin = a;
      std::uniform_real_distribution<double> distribution(a, b);

      double range = (rmax - rmin);
      int numberOfBins = std::max(51, (int) std::ceil(range / 10));

      std::valarray<int> frequencies(0, numberOfBins);
      for (int i = 0; i < count; ++i)
      {
        double value = (distribution(generator) - rmin) / range;
        int bin = (int)(std::floor((numberOfBins) * value));
        if (bin > numberOfBins - 1)
        {
          bin = numberOfBins - 1;
        }
        ++frequencies[bin];
      }
      frequencies[numberOfBins - 1] = 0;

      vtkSmartPointer<vtkIntArray> frequenciesArray =
        vtkSmartPointer<vtkIntArray>::New();
      frequenciesArray->SetNumberOfComponents(1);
      frequenciesArray->SetNumberOfTuples(numberOfBins);

      for (int i = 0; i < numberOfBins; ++i)
      {
        frequenciesArray->SetTypedTuple(i, &frequencies[i]);
      }
      frequenciesArray->SetName("frequencies");

      return frequenciesArray;
    }

    vtkSmartPointer<vtkIntArray> CreateNormalDistribution(int count, double a, double b)
    {
      double rmin, rmax;
      std::mt19937 generator(8775070);
      std::normal_distribution<double> distribution(a, b);
      rmax =  6.0 * b;
      rmin = -6.0 * b;

      double range = (rmax - rmin);
      int numberOfBins = std::max(51, (int) std::ceil(range / 10));

      std::valarray<int> frequencies(0, numberOfBins);
      for (int i = 0; i < count; ++i)
      {
        double value = (distribution(generator) - rmin) / range;
        int bin = (int)(std::floor((numberOfBins) * value));
        if (bin > numberOfBins - 1)
        {
          bin = numberOfBins - 1;
        }
        else if (bin < 0)
        {
          bin = 0;
        }
       ++frequencies[bin];
      }
      frequencies[numberOfBins - 1] = 0;

      vtkSmartPointer<vtkIntArray> frequenciesArray =
        vtkSmartPointer<vtkIntArray>::New();
      frequenciesArray->SetNumberOfComponents(1);
      frequenciesArray->SetNumberOfTuples(numberOfBins);

      for (int i = 0; i < numberOfBins; ++i)
      {
        frequenciesArray->SetTypedTuple(i, &frequencies[i]);
      }
      frequenciesArray->SetName("frequencies");

      return frequenciesArray;
    }
    vtkSmartPointer<vtkIntArray> CreateWeibullDistribution(int count, double a, double b)
    {
      double rmin, rmax;
      std::mt19937 generator(8775070);
      std::weibull_distribution<double> distribution(a, b);
      rmax = 3.0;
      rmin = 0.0;

      double range = (rmax - rmin);
      int numberOfBins = std::max(51, (int) std::ceil(range / 10));

      std::valarray<int> frequencies(0, numberOfBins);
      for (int i = 0; i < count; ++i)
      {
        double value = (distribution(generator) - rmin) / range;
        int bin = (int)(std::floor((numberOfBins) * value));
        if (bin > numberOfBins - 1)
        {
          bin = numberOfBins - 1;
        }
        ++frequencies[bin];
      }
      frequencies[numberOfBins - 1] = 0;

      vtkSmartPointer<vtkIntArray> frequenciesArray =
        vtkSmartPointer<vtkIntArray>::New();
      frequenciesArray->SetNumberOfComponents(1);
      frequenciesArray->SetNumberOfTuples(numberOfBins);

      for (int i = 0; i < numberOfBins; ++i)
      {
        frequenciesArray->SetTypedTuple(i, &frequencies[i]);
      }
      frequenciesArray->SetName("frequencies");

      return frequenciesArray;
    }
    vtkSmartPointer<vtkIntArray> CreateGammaDistribution(int count, double a, double b)
    {
      double rmin, rmax;
      std::mt19937 generator(8775070);
      std::gamma_distribution<double> distribution(a, b);
      rmax = 20.0;
      rmin = 0.0;

      double range = (rmax - rmin);
      int numberOfBins = std::max(51, (int) std::ceil(range / 10));

      std::valarray<int> frequencies(0, numberOfBins);
      for (int i = 0; i < count; ++i)
      {
        double value = (distribution(generator) - rmin) / range;
        int bin = (int)(std::floor((numberOfBins) * value));
        if (bin > numberOfBins - 1)
        {
          bin = numberOfBins - 1;
        }
        ++frequencies[bin];
      }
      frequencies[numberOfBins - 1] = 0;

      vtkSmartPointer<vtkIntArray> frequenciesArray =
        vtkSmartPointer<vtkIntArray>::New();
      frequenciesArray->SetNumberOfComponents(1);
      frequenciesArray->SetNumberOfTuples(numberOfBins);

      for (int i = 0; i < numberOfBins; ++i)
      {
        frequenciesArray->SetTypedTuple(i, &frequencies[i]);
      }
      frequenciesArray->SetName("frequencies");

      return frequenciesArray;
    }

    vtkSmartPointer<vtkIntArray> CreateCauchyDistribution(int count, double a, double b)
    {
      double rmin, rmax;
      std::mt19937 generator(8775070);
      std::cauchy_distribution<double> distribution(a, b);

      rmin = -10;
      rmax = 15.0;

      double range = (rmax - rmin);
      int numberOfBins = std::max(51, (int) std::ceil(range / 10));

      std::valarray<int> frequencies(0, numberOfBins);
      for (int i = 0; i < count; ++i)
      {
        double value = (distribution(generator) - rmin) / range;
        int bin = (int)(std::floor((numberOfBins) * value));
        if (bin > numberOfBins - 1)
        {
          bin = numberOfBins - 1;
        }
        else if (bin < 0)
        {
          bin = 0;
        }
        ++frequencies[bin];
      }
      frequencies[0] = frequencies[1];
      frequencies[numberOfBins - 1] = frequencies[numberOfBins - 2];

      vtkSmartPointer<vtkIntArray> frequenciesArray =
        vtkSmartPointer<vtkIntArray>::New();
      frequenciesArray->SetNumberOfComponents(1);
      frequenciesArray->SetNumberOfTuples(numberOfBins);

      for (int i = 0; i < numberOfBins; ++i)
      {
        frequenciesArray->SetTypedTuple(i, &frequencies[i]);
      }
      frequenciesArray->SetName("frequencies");

      return frequenciesArray;
    }
    vtkSmartPointer<vtkIntArray> CreateExtremeValueDistribution(int count, double a, double b)
    {
      double rmin, rmax;
      std::mt19937 generator(8775070);

      std::extreme_value_distribution<double> distribution(a, b);
      rmax = 5.0;
      rmin = -2.0;

      double range = (rmax - rmin);
      int numberOfBins = std::max(51, (int) std::ceil(range / 10));

      std::valarray<int> frequencies(0, numberOfBins);
      for (int i = 0; i < count; ++i)
      {
        double value = (distribution(generator) - rmin) / range;
        int bin = (int)(std::floor((numberOfBins) * value));
        if (bin > numberOfBins - 1)
        {
          bin = numberOfBins - 1;
        }
        ++frequencies[bin];
      }
      frequencies[numberOfBins - 1] = 0;

      vtkSmartPointer<vtkIntArray> frequenciesArray =
        vtkSmartPointer<vtkIntArray>::New();
      frequenciesArray->SetNumberOfComponents(1);
      frequenciesArray->SetNumberOfTuples(numberOfBins);

      for (int i = 0; i < numberOfBins; ++i)
      {
        frequenciesArray->SetTypedTuple(i, &frequencies[i]);
      }
      frequenciesArray->SetName("frequencies");

      return frequenciesArray;
    }
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

    project(CompareRandomGeneratorsCxx)

    find_package(VTK COMPONENTS
      vtkCommonColor
      vtkCommonCore
      vtkCommonDataModel
      vtkInteractionStyle
      vtkRenderingAnnotation
      vtkRenderingContextOpenGL2
      vtkRenderingCore
      vtkRenderingFreeType
      vtkRenderingGL2PSOpenGL2
      vtkRenderingOpenGL2 QUIET)
    if (NOT VTK_FOUND)
      message("Skipping CompareRandomGeneratorsCxx: ${VTK_NOT_FOUND_MESSAGE}")
      return ()
    endif()
    message (STATUS "VTK_VERSION: ${VTK_VERSION}")
    if (VTK_VERSION VERSION_LESS "8.90.0")
      # old system
      include(${VTK_USE_FILE})
      add_executable(CompareRandomGeneratorsCxx MACOSX_BUNDLE CompareRandomGeneratorsCxx.cxx )
      target_link_libraries(CompareRandomGeneratorsCxx PRIVATE ${VTK_LIBRARIES})
    else ()
      # include all components
      add_executable(CompareRandomGeneratorsCxx MACOSX_BUNDLE CompareRandomGeneratorsCxx.cxx )
      target_link_libraries(CompareRandomGeneratorsCxx PRIVATE ${VTK_LIBRARIES})
      # vtk_module_autoinit is needed
      vtk_module_autoinit(
        TARGETS CompareRandomGeneratorsCxx
        MODULES ${VTK_LIBRARIES}
        )
    endif ()

### Download and Build CompareRandomGeneratorsCxx

Click here to download CompareRandomGeneratorsCxx and its CMakeLists.txt file. Once the tarball CompareRandomGeneratorsCxx.tar has been downloaded and extracted,

    cd CompareRandomGeneratorsCxx/build

If VTK is installed:

    cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

    cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

    make

and run it:

    ./CompareRandomGeneratorsCxx

WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.