# Unstructured Gradient Filter and Marching Cubes

**URL:** https://discourse.vtk.org/t/unstructured-gradient-filter-and-marching-cubes/2853
**Category:** Support
**Created:** [March 18, 2020, 6:25pm UTC](https://discourse.vtk.org/t/unstructured-gradient-filter-and-marching-cubes/2853 "2020-03-18T18:25:52Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![ShaneKirkbride](https://discourse.vtk.org/user_avatar/discourse.vtk.org/shanekirkbride/32/1392_2.png) [@ShaneKirkbride](https://discourse.vtk.org/u/ShaneKirkbride)
#### Post date: [March 18, 2020, 6:25pm UTC](https://discourse.vtk.org/t/unstructured-gradient-filter-and-marching-cubes/2853/1 "2020-03-18T18:25:52Z")

</div>

I’m trying to show the gradient of a polyData surface similiar to the marching cubes example:  
[https://lorensen.github.io/VTKExamples/site/Cxx/Modelling/MarchingCubes/](https://lorensen.github.io/VTKExamples/site/Cxx/Modelling/MarchingCubes/)

I read in the documentation:  
[https://vtk.org/doc/nightly/html/classvtkGradientFilter.html](https://vtk.org/doc/nightly/html/classvtkGradientFilter.html)  
about the unstructured data grid option but I’m unlcear how to use it. Could I get a code snippet or pointer to an example

I saw this but it uses an image:  
[https://lorensen.github.io/VTKExamples/site/Cxx/PolyData/GradientFilter/](https://lorensen.github.io/VTKExamples/site/Cxx/PolyData/GradientFilter/)

Here is a sample of the code I tried:

```
#include <string>
#include <vtkSmartPointer.h>
#include <vtkMarchingCubes.h>
#include <vtkVoxelModeller.h>
#include <vtkSphereSource.h>
#include <vtkImageData.h>
#include <vtkDICOMImageReader.h>
#include <vtkJPEGReader.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkImageViewer2.h>

#include <vtkSmartPointer.h>

#include <vtkActor.h>
#include <vtkArrowSource.h>
#include <vtkAssignAttribute.h>
#include <vtkCamera.h>
#include <vtkExtractEdges.h>
#include <vtkGlyph3D.h>
#include <vtkGradientFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTubeFilter.h>
#include <vtkUnstructuredGridReader.h>

using namespace std;
int main(int argc, char *argv[])
{
  vtkSmartPointer<vtkImageData> volume =
    vtkSmartPointer<vtkImageData>::New();
  double isoValue;
  vtkSmartPointer<vtkSphereSource> sphereSource =
      vtkSmartPointer<vtkSphereSource>::New();
  sphereSource->SetPhiResolution(20);
  sphereSource->SetThetaResolution(20);
  sphereSource->Update();

  double bounds[6];
  sphereSource->GetOutput()->GetBounds(bounds);
  for (unsigned int i = 0; i < 6; i += 2)
  {
      double range = bounds[i + 1] - bounds[i];
      bounds[i] = bounds[i] - .1 * range;
      bounds[i + 1] = bounds[i + 1] + .1 * range;
  }
  vtkSmartPointer<vtkVoxelModeller> voxelModeller =
      vtkSmartPointer<vtkVoxelModeller>::New();
  voxelModeller->SetSampleDimensions(50, 50, 50);
  voxelModeller->SetModelBounds(bounds);
  voxelModeller->SetScalarTypeToFloat();
  voxelModeller->SetMaximumDistance(.1);

  voxelModeller->SetInputConnection(sphereSource->GetOutputPort());
  voxelModeller->Update();
  isoValue = 0.5;
  volume->DeepCopy(voxelModeller->GetOutput());
    
    //std::string inputFilename = argv[1];
    vtkSmartPointer<vtkMarchingCubes> surface =
        vtkSmartPointer<vtkMarchingCubes>::New();
    surface->SetInputData(volume);
    surface->ComputeNormalsOn();
    surface->SetValue(0, isoValue);

    // Create polydata from iso-surface
    vtkSmartPointer<vtkPolyData> marched = vtkSmartPointer<vtkPolyData>::New();
    surface->Update();
    marched->DeepCopy(surface->GetOutput());
    std::cout << "Number of points: " << marched->GetNumberOfPoints() << std::endl;
         
  vtkSmartPointer<vtkExtractEdges> edges = vtkSmartPointer<vtkExtractEdges>::New();
  edges->SetInputData(marched); // ->SetInputData(outputMesh); // ->SetInputConnection(reader->GetOutputPort());

  vtkSmartPointer<vtkTubeFilter> tubes = vtkSmartPointer<vtkTubeFilter>::New();
  tubes->SetInputConnection(edges->GetOutputPort());
  tubes->SetRadius(0.01);
  tubes->SetVaryRadiusToVaryRadiusOff();
  tubes->SetNumberOfSides(4);

  vtkSmartPointer<vtkPolyDataMapper> tubesMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  tubesMapper->SetInputConnection(tubes->GetOutputPort());
  tubesMapper->SetScalarRange(0.0, 25.0);

  vtkSmartPointer<vtkActor> tubesActor = vtkSmartPointer<vtkActor>::New();
  tubesActor->SetMapper(tubesMapper);

  vtkSmartPointer<vtkGradientFilter> gradients = vtkSmartPointer<vtkGradientFilter>::New();
  gradients->SetInputData(marched); // ->SetInputConnection(reader->GetOutputPort());
  gradients->Update();

  marched->Print(std::cout);
  vtkSmartPointer<vtkAssignAttribute> vectors = vtkSmartPointer<vtkAssignAttribute>::New();
  vectors->SetInputConnection(gradients->GetOutputPort());
  vectors->Assign("Gradients", vtkDataSetAttributes::VECTORS, vtkAssignAttribute::POINT_DATA);

  vtkSmartPointer<vtkArrowSource> arrow = vtkSmartPointer<vtkArrowSource>::New();

  vtkSmartPointer<vtkGlyph3D> glyphs = vtkSmartPointer<vtkGlyph3D>::New();
  glyphs->SetInputConnection(0, vectors->GetOutputPort());
  glyphs->SetInputConnection(1, arrow->GetOutputPort());
  glyphs->ScalingOn();
  glyphs->SetScaleModeToScaleByVector();
  glyphs->SetScaleFactor(0.25);
  glyphs->OrientOn();
  glyphs->ClampingOff();
  glyphs->SetVectorModeToUseVector();
  glyphs->SetIndexModeToOff();

  vtkSmartPointer<vtkPolyDataMapper> glyphMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  glyphMapper->SetInputConnection(glyphs->GetOutputPort());
  glyphMapper->ScalarVisibilityOff();

  vtkSmartPointer<vtkActor> glyphActor = vtkSmartPointer<vtkActor>::New();
  glyphActor->SetMapper(glyphMapper);

  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
  renderer->AddActor(tubesActor);
  renderer->AddActor(glyphActor);
  renderer->SetBackground(0.328125, 0.347656, 0.425781);

  vtkSmartPointer<vtkRenderWindow> renwin =
      vtkSmartPointer<vtkRenderWindow>::New();
  renwin->AddRenderer(renderer);
  renwin->SetSize(600, 600);

  renderer->ResetCamera();
  vtkCamera* camera = renderer->GetActiveCamera();
  camera->Elevation(-80.0);
  camera->OrthogonalizeViewUp();
  camera->Azimuth(135.0);

  vtkSmartPointer<vtkRenderWindowInteractor> iren =
      vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renwin);
  renwin->Render();
  iren->Initialize();
  iren->Start();

  return EXIT_SUCCESS;
}

```

Here is the result - I was hoping for something a little more colorful; and I think I’m probably doing something wrong.  
an example like this: [Gradient of Unstrucutred Grid in Python](https://discourse.vtk.org/t/gradient-of-unstrucutred-grid-in-python/2489)  
in C++ would probably be helpful enough.

 ![image](https://discourse.vtk.org/uploads/default/original/2X/0/006744b8c49e10b63354acf478db1c60b689f51f.png)

---

<div class="post-metadata">

### Author: ![ShaneKirkbride](https://discourse.vtk.org/user_avatar/discourse.vtk.org/shanekirkbride/32/1392_2.png) [@ShaneKirkbride](https://discourse.vtk.org/u/ShaneKirkbride)
#### Post date: [March 19, 2020, 12:47pm UTC](https://discourse.vtk.org/t/unstructured-gradient-filter-and-marching-cubes/2853/2 "2020-03-19T12:47:31Z")

</div>

I added some debug values to try to understand this more. I also changed the shape. It seems like all the gradient tuples are 0. I would think they would show some type of change. But I do understand why the shape is all red. I think there is something I’m missing in my pipeline but I’m not sure what. I’ll continue to search. Here is the result and

 ![image](https://discourse.vtk.org/uploads/default/original/2X/3/321a42106e828582e1dc552b8d069d6dfb51019d.png)  
Here is my code:

```
#include <string>
#include <vtkActor.h>
#include <vtkArrowSource.h>
#include <vtkAssignAttribute.h>
#include <vtkCamera.h>
#include <vtkConeSource.h>
#include <vtkDoubleArray.h>
#include <vtkSmartPointer.h>
#include <vtkMarchingCubes.h>
#include <vtkVoxelModeller.h>
#include <vtkImageData.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkJPEGReader.h>

#include <vtkPolyDataMapper.h>
#include <vtkSphereSource.h>
#include <vtkSmartPointer.h>
#include <vtkExtractEdges.h>
#include <vtkGlyph3D.h>
#include <vtkGradientFilter.h>
#include <vtkPoints.h>
#include <vtkPointData.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTubeFilter.h>
#include <vtkUnstructuredGridReader.h>

using namespace std;
int main(int argc, char *argv[])
{
    //Create a cone
    vtkSmartPointer<vtkConeSource> coneSource = vtkSmartPointer<vtkConeSource>::New();
    coneSource->Update();
  vtkSmartPointer<vtkImageData> volume = vtkSmartPointer<vtkImageData>::New();
  double isoValue;
  //vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
  //sphereSource->SetPhiResolution(200);
  //sphereSource->SetThetaResolution(200);
  //sphereSource->Update();

  double bounds[6];
  coneSource->GetOutput()->GetBounds(bounds);
  for (unsigned int i = 0; i < 6; i += 2)
  {
      double range = bounds[i + 1] - bounds[i];
      bounds[i] = bounds[i] - .1 * range;
      bounds[i + 1] = bounds[i + 1] + .1 * range;
  }
  vtkSmartPointer<vtkVoxelModeller> voxelModeller =
      vtkSmartPointer<vtkVoxelModeller>::New();
  voxelModeller->SetSampleDimensions(50, 50, 50);
  voxelModeller->SetModelBounds(bounds);
  voxelModeller->SetScalarTypeToFloat();
  voxelModeller->SetMaximumDistance(.1);

  voxelModeller->SetInputConnection(coneSource->GetOutputPort());
  voxelModeller->Update();
  isoValue = 0.5;
  volume->DeepCopy(voxelModeller->GetOutput());
    
    //std::string inputFilename = argv[1];
    vtkSmartPointer<vtkMarchingCubes> surface =
        vtkSmartPointer<vtkMarchingCubes>::New();
    surface->SetInputData(volume);
    surface->ComputeNormalsOn();
    surface->SetValue(0, isoValue);

    // Create polydata from iso-surface
    vtkSmartPointer<vtkPolyData> marched = vtkSmartPointer<vtkPolyData>::New();
    surface->Update();
    marched->DeepCopy(surface->GetOutput());
    std::cout << "Number of points: " << marched->GetNumberOfPoints() << std::endl;
 
  vtkSmartPointer<vtkGradientFilter> gradientFilter = vtkSmartPointer<vtkGradientFilter>::New();
  gradientFilter->SetInputData(marched); //->SetInputConnection(volume->GetOutputPort());
  gradientFilter->Update();
  
  auto gradientOutput = gradientFilter->GetOutput();
  gradientOutput->Print(std::cout);
  ////save gradient array
  vtkSmartPointer<vtkDoubleArray> gradients = vtkSmartPointer<vtkDoubleArray>::New();

  gradients->SetNumberOfTuples(gradientOutput->GetNumberOfPoints());
  gradients->SetName("gradients");
  gradients->Print(std::cout); 
  
  int numberOfTuples = gradientOutput->GetNumberOfPoints();
  auto gradient_array = gradientOutput->GetPointData()->GetArray("Gradients");
  for (vtkIdType ii = 0; ii < numberOfTuples; ii++) {
      double* gradientValue = gradient_array->GetTuple(ii);

      std::cout << gradientValue[0] << " " 
                << gradientValue[1] << " "
                << gradientValue[2] << std::endl;

  }
  
  vtkSmartPointer<vtkExtractEdges> edges = vtkSmartPointer<vtkExtractEdges>::New();
  edges->SetInputData(gradientOutput); // ->SetInputData(outputMesh); // ->SetInputConnection(reader->GetOutputPort());

  vtkSmartPointer<vtkTubeFilter> tubes = vtkSmartPointer<vtkTubeFilter>::New();
  tubes->SetInputConnection(edges->GetOutputPort());
  tubes->SetRadius(0.01);
  tubes->SetVaryRadiusToVaryRadiusOff();
  tubes->SetNumberOfSides(4);

  vtkSmartPointer<vtkPolyDataMapper> tubesMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  tubesMapper->SetInputConnection(tubes->GetOutputPort());
  tubesMapper->SetScalarRange(0.0, 25.0);

  vtkSmartPointer<vtkActor> tubesActor = vtkSmartPointer<vtkActor>::New();
  tubesActor->SetMapper(tubesMapper);
  
  vtkSmartPointer<vtkAssignAttribute> vectors = vtkSmartPointer<vtkAssignAttribute>::New();
  vectors->SetInputConnection(gradientFilter->GetOutputPort());
  vectors->Assign("Gradients", vtkDataSetAttributes::VECTORS, vtkAssignAttribute::POINT_DATA);

  vtkSmartPointer<vtkArrowSource> arrow = vtkSmartPointer<vtkArrowSource>::New();

  vtkSmartPointer<vtkGlyph3D> glyphs = vtkSmartPointer<vtkGlyph3D>::New();
  glyphs->SetInputConnection(0, vectors->GetOutputPort());
  glyphs->SetInputConnection(1, arrow->GetOutputPort());
  glyphs->ScalingOn();
  glyphs->SetScaleModeToScaleByVector();
  glyphs->SetScaleFactor(0.25);
  glyphs->OrientOn();
  glyphs->ClampingOff();
  glyphs->SetVectorModeToUseVector();
  glyphs->SetIndexModeToOff();

  vtkSmartPointer<vtkPolyDataMapper> glyphMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  glyphMapper->SetInputConnection(glyphs->GetOutputPort());
  glyphMapper->ScalarVisibilityOff();

  vtkSmartPointer<vtkActor> glyphActor = vtkSmartPointer<vtkActor>::New();
  glyphActor->SetMapper(glyphMapper);

  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
  renderer->AddActor(tubesActor);
  renderer->AddActor(glyphActor);
  renderer->SetBackground(0.328125, 0.347656, 0.425781);

  vtkSmartPointer<vtkRenderWindow> renwin =
      vtkSmartPointer<vtkRenderWindow>::New();
  renwin->AddRenderer(renderer);
  renwin->SetSize(600, 600);

  renderer->ResetCamera();
  vtkCamera* camera = renderer->GetActiveCamera();
  camera->Elevation(-80.0);
  camera->OrthogonalizeViewUp();
  camera->Azimuth(135.0);

  vtkSmartPointer<vtkRenderWindowInteractor> iren =
      vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renwin);
  renwin->Render();
  iren->Initialize();
  iren->Start();

  return EXIT_SUCCESS;
}
```

---

<div class="post-metadata">

### Author: ![ShaneKirkbride](https://discourse.vtk.org/user_avatar/discourse.vtk.org/shanekirkbride/32/1392_2.png) [@ShaneKirkbride](https://discourse.vtk.org/u/ShaneKirkbride)
#### Post date: [March 20, 2020, 5:00pm UTC](https://discourse.vtk.org/t/unstructured-gradient-filter-and-marching-cubes/2853/3 "2020-03-20T17:00:25Z")

</div>

Can someone please help me use the gradient filter on an isoSurface?
