Trying to have the tubeFilter use CellData for coloring instead of point data

I am trying to use the tube filter but instead of using point data to color the tubes, use cell data instead. However, when I have it use cell data, the color just won’t show up. I am just using this example and building from it

Inside add representation, I tried to see what the cell data is coming out of the tube filter
and it displayed [0.2,0.2,0.2,0.2]. So somehow only the first value from my cell data got passed through so I feel like I definitely invoked something wrong.

Here is my code

  function addRepresentation(name, filter, props = {}) {
    const mapper = vtkMapper.newInstance();
    if (filter.isA('vtkPolyData')) {
      mapper.setInputData(filter);
    } else {
      mapper.setInputConnection(filter.getOutputPort());
     console.log(filter.getOutputData().getCellData().getArrays()[0].getData())
      mapper.setColorModeToMapScalars();
      mapper.setScalarVisibility(true)
    }

  
    const actor =vtkActor.newInstance();
    actor.setMapper(mapper);
    actor.getProperty().set(props);
    renderer.addActor(actor);

    return actor
  }
  vtkMath.randomSeed(15222);
  const numSegments = 4;
  
  function initializePolyData() {
    const polyData = vtkPolyData.newInstance();
    const points = vtkPoints.newInstance();
    points.setNumberOfPoints(numSegments + 1);
    var pointData = new Float32Array(3 * (numSegments + 1));
    var verts = new Uint32Array(2 * (numSegments + 1));
    var lines = new Uint32Array(numSegments + 2);
    var scalarsData = new Float32Array(numSegments + 1);
    for (let i = 0; i <= numSegments + 1; ++i) {
      verts[i] = 1;
      verts[i + 1] = i;
    }
    scalarsData= [0.2,0.4,0.6,0.8];
    const scalars = vtkDataArray.newInstance({
      name: 'Scalars',
      values: scalarsData,
    });
    lines = [2,0,1,2,2,3,2,4,5,2,6,7];
    pointData = [0,0,1,0,0,2,1,0,1,1,0,2,2,0,1,2,0,2,3,0,1,3,0,2]
    points.setData(pointData);
    console.log(pointData);
    console.log(lines);
    console.log(scalarsData);
    polyData.setPoints(points);
    polyData.getLines().setData(lines);
    polyData.getCellData().setScalars(scalars);
    return polyData;
  }
  
  // ----------------------------------------------------------------------------
  
  const polyData = initializePolyData();
  const tubeFilter = vtkTubeFilter.newInstance();
  
  tubeFilter.setCapping(false);
  tubeFilter.setNumberOfSides(50);
  tubeFilter.setRadius(0.1);
  
  tubeFilter.setInputData(polyData);
  console.log(tubeFilter);
  tubeFilter.setInputArrayToProcess(0, 'Scalars', 'CellData', 'Scalars');
  
  const polyActor = addRepresentation('polyData', polyData, {});
  const tubeActor = addRepresentation('tubeFilter', tubeFilter, {});
  renderer.resetCamera();
  renderWindow.render();

You may need to make sure "Scalars" are the active scalars array on the tube filter’s output poly data. Then you likely need mapper.setScalarModeToUseCellData() I think… not too sure.

Hope this helps

I will give it shot, it seems to me that when I pass in point data, the filter recalculate the colors for each point but when I pass in cell data, there is no recalculation done. I am trying to use the XMLpolydata writer and write the output into a file and see if I can spot something.

Here’s my understanding of the underlying problem: it appears that when vtkTubeFilter tries to copy over the cell data, it can’t copy everything over because the tube’s cell data is still capped at 4 elements when it should be more. (For each line segment, that line’s cell data should be copied to each of the tube faces encircling that segment.) This might be a bug, but I’m not yet sure where in the copy pipeline.

Update: there is a vtk.js PR for fixing what I think is a bug in vtkTubeFilter. In addition, you probably can remove the line tubeFilter.setInputArrayToProcess(...), since that’s used for varying tube radius.

The updates to vtkTubeFilter have been merged into vtk.js.

1 Like