Change color to cells in vtkjs using vtkLookupTable

Hi,

My goal is to highlight some cells of a polydata. The ids are included in a given list. I have successfully created the code for the regular c# VTK application. I would like to reproduce the same result in vtkjs. I made a lot of researches without luck.
Any suggestion to convert the following code in javascript with vtkjs?

// Windows Winform c# desktop application.

var filename = "model.stl";

var reader = new vtkSTLReader();
reader.SetFileName(filename);

var polydata = reader.GetOutput();

var scalars = vtkFloatArray.New();
var noc = polydata.GetNumberOfCells();
for (long i = 0; i < noc; i++)
{
    scalars.InsertNextTuple1(0);
}

// `cellToHighlight` is a list that contains the ids of cells that I need to highlight.
var cellToHighlight = new List<long>() { 123, 3454, 3532, 546456, 567567 }; 

foreach (var id in cellToHighlight) 
{
    scalars.InsertTuple1(id, 1);
}

polydata.GetCellData().SetScalars(scalars);

var lut = vtkLookupTable.New();
lut.SetNumberOfTableValues(2);
lut.SetTableRange(0, 1);
lut.SetTableValue(0, 1.0, 1.0, 1.0, 1.0);
lut.SetTableValue(1, 0.0, 1.0, 0.0, 1.0);
lut.Build();

var mapper = vtkPolyDataMapper.New();
mapper.SetInputDataObject(polydata);
mapper.SetScalarModeToUseCellData();
mapper.SetColorModeToMapScalars();
mapper.SetScalarRange(0, 1);
mapper.SetLookupTable(lut);
mapper.Update();

var actor = vtkActor.New();
actor.SetMapper(mapper);

renderer.AddActor(actor);
renderWindow.Render();

Thank you.

[...]
const noc = polydata.getNumberOfCells();
const newCellScalars = new UInt8Array(noc); // or any other typed array
newCellScalars.fill(0);
for (let i = 0; i < cellToHighlight.length; i++) {
   const cellIdx = cellToHighlight[i];
   newCellScalars[cellIdx] = 1;
}
const cellArray = vtkDataArray.newInstance({ name: "cellSelection", values: newCellScalars });
polydata.getCellData().addArray(cellArray);

[... later]
newCellScalars.fill(0);
newCellScalars[345] = 1
cellArray.setData(newCellScalars);

[...or]
newCellScalars.fill(0);
newCellScalars[345] = 1
cellArray.modified();

HTH

Hi Sebastien,

Thank you so much for the reply. Do you have any suggestions about the mapper settings and lookup-table part?

Thank you.

Something like

mapper.setScalarModeToUseCellData()

const lut = mapper.getLookupTable();
lut.setValueRange(0.2, 1.0);
lut.setHueRange(0.666, 0);

Thank you for your feedback. Unfortunately, I do not get the desired result. Here is my javascript code.

const reader = vtkSTLReader.newInstance();
reader.parseAsArrayBuffer(fileReader.result);

let polydata = reader.getOutputData();

// ---

let values = [];
const noc = polydata.getNumberOfCells();
for (let i = 0; i < noc; i++) {
    values[i] = 0;
}

toothResponse.data.triangles.forEach((cellId) => {
    values[cellId] = 1;
});

const VtkDataTypes = vtkDataArray.VtkDataTypes;
let scalars = vtkDataArray.newInstance({
    values: values,
    numberOfComponents: 1, // number of channels (grayscale)
    dataType: VtkDataTypes.FLOAT, // values encoding
    name: "scalars",
});
polydata.getCellData().setScalars(scalars);

// ---

const table = vtkDataArray.newInstance({
    numberOfComponents: 4,
    size: 2,
    dataType: "Uint8Array",
});
table.setTuple(0, [255, 255, 255, 255]);
table.setTuple(1, [0, 255, 0, 255]);

let lut = vtkLookupTable.newInstance();
lut.setNumberOfColors(2);
lut.setRange(0, 1);
lut.setTable(table);

// ---

const mapper = vtkMapper.newInstance();
mapper.setInputData(polydata);
mapper.setScalarVisibility(true);
mapper.setScalarModeToUseCellData();
mapper.setScalarRange(0, 1);
mapper.setLookupTable(lut);
mapper.update();

const actor = vtkActor.newInstance();
actor.setMapper(mapper);

renderer.addActor(actor);
renderer.resetCamera();
renderWindow.render();

I got a blank window.

I hope you can help me to find the cause of the problem. Because using C# is very strait forward.

Thank you

If you convert that to a stand alone example that I can easily run (like based on a cone source or something) then I’ll take a quick look locally. In general it looks OK to me.

Hi Ken,

Thank you so much for your help. Here is the example you requested. I have used the default single-page vtk template for creating the example. I got the same result as my original code: a blank window.

<!DOCTYPE html>
<html>
  <body>
    <script
      type="text/javascript"
      src="https://unpkg.com/@babel/polyfill@7.0.0/dist/polyfill.js"
    ></script>
    <script type="text/javascript" src="https://unpkg.com/vtk.js"></script>
    <script type="text/javascript">
      var fullScreenRenderer = vtk.Rendering.Misc.vtkFullScreenRenderWindow.newInstance();
      var renderWindow = fullScreenRenderer.getRenderWindow();
      var renderer = fullScreenRenderer.getRenderer();

      // ---

      var cone = vtk.Filters.Sources.vtkConeSource.newInstance();
      var polydata = cone.getOutputData();

      var values = [];
      var noc = polydata.getNumberOfCells();
      for (var i = 0; i < noc; i++) {
        values[i] = 0;
      }

      var cellToHighlight = [1, 2, 3];
      cellToHighlight.forEach((cellId) => {
        values[cellId] = 1;
      });

      const VtkDataTypes = vtk.Common.Core.vtkDataArray.VtkDataTypes;
      let scalars = vtk.Common.Core.vtkDataArray.newInstance({
        values: values,
        numberOfComponents: 1, // number of channels (grayscale)
        dataType: VtkDataTypes.FLOAT, // values encoding
        name: "scalars",
      });
      polydata.getCellData().setScalars(scalars);

      // ---

      const table = vtk.Common.Core.vtkDataArray.newInstance({
        numberOfComponents: 4,
        size: 2,
        dataType: "Uint8Array",
      });
      table.setTuple(0, [255, 255, 255, 255]);
      table.setTuple(1, [0, 255, 0, 255]);

      let lut = vtk.Common.Core.vtkLookupTable.newInstance();
      lut.setNumberOfColors(2);
      lut.setRange(0, 1);
      lut.setTable(table);

      // ---

      var mapper = vtk.Rendering.Core.vtkMapper.newInstance();
      mapper.setInputData(polydata);
      mapper.setScalarVisibility(true);
      mapper.setScalarModeToUseCellData();
      mapper.setScalarRange(0, 1);
      mapper.setLookupTable(lut);
      mapper.update();

      var actor = vtk.Rendering.Core.vtkActor.newInstance();
      actor.setMapper(mapper);

      renderer.addActor(actor);

      // ---

      renderer.resetCamera();
      renderWindow.render();
    </script>
  </body>
</html>

Thank you.

In table you need to set the size to 8 as there are 2 tuples each with 4 components for a total size of 8.

Thank you so much!

Have a great weekend.