# SpikeFran

VTKExamples/Cxx/VisualizationAlgorithms/SpikeFran

### Description

This examples uses glyphs to indicate surface normals on model of human face. Glyph positions are randomly selected.

Info

See Figure 6-30 in Chapter 6 the VTK Textbook.

Other Languages

See (Python)

### Code

SpikeFran.cxx

    #include <vtkActor.h>
    #include <vtkCamera.h>
    #include <vtkConeSource.h>
    #include <vtkGlyph3D.h>
    #include <vtkMaskPoints.h>
    #include <vtkNamedColors.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkPolyDataNormals.h>
    #include <vtkPolyDataReader.h>
    #include <vtkProperty.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkRenderer.h>
    #include <vtkTransform.h>
    #include <vtkTransformPolyDataFilter.h>

    // This example demonstrates the use of glyphing. We also use a mask filter
    // to select a subset of points to glyph.

    // Read a data file. This originally was a Cyberware laser digitizer scan
    // of Fran J.'s face. Surface normals are generated based on local geometry
    // (i.e., the polygon normals surrounding each point are averaged). We flip
    // the normals because we want them to point out from Fran's face.
    //
    int main (int argc, char *argv[])
    {
      if (argc < 2)
      {
        std::cout << "Usage: " << argv[0] << " fran_cut.vtk" << std::endl;
        return EXIT_FAILURE;
      }

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

      vtkSmartPointer<vtkPolyDataReader> fran =
        vtkSmartPointer<vtkPolyDataReader>::New();
      fran->SetFileName(argv[1]);

      vtkSmartPointer<vtkPolyDataNormals> normals =
        vtkSmartPointer<vtkPolyDataNormals>::New();
      normals->SetInputConnection(fran->GetOutputPort());
      normals->FlipNormalsOn();

      vtkSmartPointer<vtkPolyDataMapper> franMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
      franMapper->SetInputConnection(normals->GetOutputPort());

      vtkSmartPointer<vtkActor> franActor =
        vtkSmartPointer<vtkActor>::New();
      franActor->SetMapper(franMapper);
      franActor->GetProperty()->SetColor(colors->GetColor3d("Flesh").GetData());

    // We subsample the dataset because we want to glyph just a subset of
    // the points. Otherwise the display is cluttered and cannot be easily
    // read. The RandomModeOn and SetOnRatio combine to random select one out
    // of every 10 points in the dataset.
    //
      vtkSmartPointer<vtkMaskPoints> ptMask =
        vtkSmartPointer<vtkMaskPoints>::New();
      ptMask->SetInputConnection(normals->GetOutputPort());
      ptMask->SetOnRatio(10);
      ptMask->RandomModeOn();

    // In this case we are using a cone as a glyph. We transform the cone so
    // its base is at 0,0,0. This is the point where glyph rotation occurs.
      vtkSmartPointer<vtkConeSource> cone =
        vtkSmartPointer<vtkConeSource>::New();
      cone->SetResolution(6);

      vtkSmartPointer<vtkTransform> transform =
        vtkSmartPointer<vtkTransform>::New();
      transform->Translate(0.5, 0.0, 0.0);

      vtkSmartPointer<vtkTransformPolyDataFilter> transformF =
        vtkSmartPointer<vtkTransformPolyDataFilter>::New();
      transformF->SetInputConnection(cone->GetOutputPort());
      transformF->SetTransform(transform);

    // vtkGlyph3D takes two inputs: the input point set (SetInputConnection)
    // which can be any vtkDataSet; and the glyph (SetSourceConnection) which
    // must be a vtkPolyData.  We are interested in orienting the glyphs by the
    // surface normals that we previously generated.
      vtkSmartPointer<vtkGlyph3D> glyph =
        vtkSmartPointer<vtkGlyph3D>::New();
      glyph->SetInputConnection(ptMask->GetOutputPort());
      glyph->SetSourceConnection(transformF->GetOutputPort());
      glyph->SetVectorModeToUseNormal();
      glyph->SetScaleModeToScaleByVector();
      glyph->SetScaleFactor(0.004);

      vtkSmartPointer<vtkPolyDataMapper> spikeMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
      spikeMapper->SetInputConnection(glyph->GetOutputPort());

      vtkSmartPointer<vtkActor> spikeActor =
        vtkSmartPointer<vtkActor>::New();
      spikeActor->SetMapper(spikeMapper);
      spikeActor->GetProperty()->SetColor(colors->GetColor3d("Emerald_Green").GetData());

    // Create the RenderWindow, Renderer and both Actors
    //
      vtkSmartPointer<vtkRenderer> ren1 =
        vtkSmartPointer<vtkRenderer>::New();
      vtkSmartPointer<vtkRenderWindow> renWin =
        vtkSmartPointer<vtkRenderWindow>::New();
      renWin->AddRenderer(ren1);

      vtkSmartPointer<vtkRenderWindowInteractor> iren =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
      iren->SetRenderWindow(renWin);

    // Add the actors to the renderer, set the background and size
    //
      ren1->AddActor(franActor);
      ren1->AddActor(spikeActor);

      renWin->SetSize(640, 480);
      ren1->SetBackground(colors->GetColor3d("SlateGray").GetData());

    // render the image
    //
      renWin->Render();

      ren1->GetActiveCamera()->Zoom(1.4);
      ren1->GetActiveCamera()->Azimuth(110);
      renWin->Render();
      iren->Start();

      return EXIT_SUCCESS;
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

    project(SpikeFran)

    find_package(VTK COMPONENTS
      vtkCommonColor
      vtkCommonTransforms
      vtkFiltersCore
      vtkFiltersGeneral
      vtkFiltersSources
      vtkIOLegacy
      vtkInteractionStyle
      vtkRenderingCore
      vtkRenderingFreeType
      vtkRenderingOpenGL2 QUIET)
    if (NOT VTK_FOUND)
      message("Skipping SpikeFran: ${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(SpikeFran MACOSX_BUNDLE SpikeFran.cxx )
      target_link_libraries(SpikeFran PRIVATE ${VTK_LIBRARIES})
    else ()
      # include all components
      add_executable(SpikeFran MACOSX_BUNDLE SpikeFran.cxx )
      target_link_libraries(SpikeFran PRIVATE ${VTK_LIBRARIES})
      # vtk_module_autoinit is needed
      vtk_module_autoinit(
        TARGETS SpikeFran
        MODULES ${VTK_LIBRARIES}
        )
    endif ()

### Download and Build SpikeFran

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

    cd SpikeFran/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:

    ./SpikeFran

WINDOWS USERS

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