Commit a07731a2 authored by Cory Quammen's avatar Cory Quammen

Handle coloring by field data

Some level of support was previously available for coloring by field
data, but this was restricted to drawing triangle strips. This patch
adds another mode to coloring by field data that enables coloring the
entire data set by a particular tuple in the field data. The field
data tuple gets mapped through the color map, and that color is used
to color the entire data set. The default behavior for triangle strips
is retained by setting this tuple index to -1, the default value.

The motivation for this change is to make it possible to color blocks
in a multi-block dataset according to a value in that block's field
data array, e.g., an initial condition, block ID, etc. Vector values
(arrays with more than one component) are fully supported.

Several other improvements were also made:

- Added test for existing capability of coloring by field data.

- Added test for coloring by tuple of field data.

- Modified vtkMapper::GetScalarModeAsString() to return
  string for field data scalar mode.

- Fixed vtkDataSetSurfaceFilter::UnstructuredGridExecute(...) and
  vtkUnstructuredGridGeometryFilter::RequestData(...)
  to pass field data through to output

Change-Id: I0d97e84ec77e7ea01ca1b1350acce73cb6c4c15b
parent d8de2be7
......@@ -1388,11 +1388,16 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
vtkIdType inPtId, outPtId;
vtkPointData *inputPD = input->GetPointData();
vtkCellData *inputCD = input->GetCellData();
vtkFieldData *inputFD = input->GetFieldData();
vtkCellData *cd = input->GetCellData();
vtkPointData *outputPD = output->GetPointData();
vtkCellData *outputCD = output->GetCellData();
vtkFieldData *outputFD = output->GetFieldData();
vtkFastGeomQuad *q;
// Shallow copy field data not associated with points or cells
outputFD->ShallowCopy(inputFD);
// These are for the default case/
vtkIdList *pts;
vtkPoints *coords;
......
......@@ -815,6 +815,7 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
}
vtkPointData *pd=input->GetPointData();
vtkCellData *cd=input->GetCellData();
vtkFieldData *fd=input->GetFieldData();
vtkIdType numPts=input->GetNumberOfPoints();
vtkPoints *inPts=input->GetPoints();
vtkSmartPointer<vtkCellIterator> cellIter =
......@@ -823,6 +824,7 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
// Output
vtkPointData *outputPD=output->GetPointData();
vtkCellData *outputCD=output->GetCellData();
vtkFieldData *outputFD=output->GetFieldData();
// vtkUnsignedCharArray *types=vtkUnsignedCharArray::New();
// types->Allocate(numCells);
// vtkIdTypeArray *locs=vtkIdTypeArray::New();
......@@ -936,6 +938,9 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
originalCellIds->Allocate(numCells, numCells/2);
}
// Shallow copy field data not associated with points or cells
outputFD->ShallowCopy(fd);
vtkIdType *pointMap=0;
if(this->Merging)
......
......@@ -60,6 +60,8 @@ vtkMapper::vtkMapper()
this->ArrayComponent = 0;
this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
this->FieldDataTupleId = -1;
this->InterpolateScalarsBeforeMapping = 0;
this->ColorCoordinates = 0;
this->ColorTextureMap = 0;
......@@ -488,6 +490,10 @@ const char *vtkMapper::GetScalarModeAsString(void)
{
return "UseCellFieldData";
}
else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA )
{
return "UseFieldData";
}
else
{
return "Default";
......
......@@ -228,11 +228,19 @@ public:
// (ScalarModeToUseCellFieldData). If scalars are coming from a field
// data array, you must call SelectColorArray before you call
// GetColors.
// When ScalarMode is set to use Field Data (ScalarModeToFieldData), you
// must call SelectColorArray to choose the field data array to be used to
// color cells. In this mode, if the poly data has triangle strips,
// the field data is treated as the celldata for each mini-cell formed by
// a triangle in the strip rather than the entire strip.
// When ScalarMode is set to use Field Data (ScalarModeToFieldData),
// you must call SelectColorArray to choose the field data array to
// be used to color cells. In this mode, the default behavior is to
// treat the field data tuples as being associated with cells. If
// the poly data contains triangle strips, the array is expected to
// contain the cell data for each mini-cell formed by any triangle
// strips in the poly data as opposed to treating them as a single
// tuple that applies to the entire strip. This mode can also be
// used to color the entire poly data by a single color obtained by
// mapping the tuple at a given index in the field data array
// through the color map. Use SetFieldDataTupleId() to specify
// the tuple index.
vtkSetMacro(ScalarMode, int);
vtkGetMacro(ScalarMode, int);
void SetScalarModeToDefault()
......@@ -255,6 +263,17 @@ public:
void SelectColorArray(int arrayNum);
void SelectColorArray(const char* arrayName);
// Description:
// When ScalarMode is set to UseFieldData, set the index of the
// tuple by which to color the entire data set. By default, the
// index is -1, which means to treat the field data array selected
// with SelectColorArray as having a scalar value for each cell.
// Indices of 0 or higher mean to use the tuple at the given index
// for coloring the entire data set.
vtkSetMacro(FieldDataTupleId, vtkIdType);
vtkGetMacro(FieldDataTupleId, vtkIdType);
// Description:
// Legacy:
// These methods used to be used to specify the array component.
......@@ -421,6 +440,10 @@ protected:
int ArrayComponent;
int ArrayAccessMode;
// If coloring by field data, which tuple to use to color the entire
// data set. If -1, treat array values as cell data.
vtkIdType FieldDataTupleId;
int Static;
int ForceCompileOnly;
......
......@@ -16,6 +16,12 @@ vtk_add_test_cxx(${vtk-module}CxxTests render_window_tests
TestValuePainter.cxx,NO_VALID
TestValuePasses.cxx
)
vtk_add_test_cxx(${vtk-module}CxxTests render_window_tests
TestScalarsToColorsPainterFieldDataCells,TestScalarsToColorsPainterFieldData.cxx -1
)
vtk_add_test_cxx(${vtk-module}CxxTests render_window_tests
TestScalarsToColorsPainterFieldDataTuple,TestScalarsToColorsPainterFieldData.cxx 50
)
vtk_add_test_cxx(${vtk-module}CxxTests render_window_tests
TestBlurAndSobelPasses.cxx
#TestGaussianBlurPass.cxx # Missing symbol checking for Mesa bug
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestScalarsToColorsPainterFieldData.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// This tests coloring by a field data
#include "vtkActor.h"
#include "vtkColorTransferFunction.h"
#include "vtkDataArray.h"
#include "vtkFieldData.h"
#include "vtkFloatArray.h"
#include "vtkNew.h"
#include "vtkPainterPolyDataMapper.h"
#include "vtkPointData.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkStripper.h"
#include "vtkTestUtilities.h"
int TestScalarsToColorsPainterFieldData(int argc, char* argv[])
{
vtkIdType tupleId = -1;
if (argc > 1)
{
tupleId = atoi(argv[1]);
}
// Set up sphere source
vtkNew<vtkSphereSource> sphere;
sphere->SetPhiResolution(8);
sphere->SetThetaResolution(8);
sphere->Update();
// Add a field data array
vtkPolyData* pd = sphere->GetOutput();
vtkFieldData* fd = pd->GetFieldData();
vtkNew<vtkFloatArray> newArray;
newArray->SetName("floatArray");
newArray->SetNumberOfComponents(1);
newArray->SetNumberOfTuples(pd->GetNumberOfCells());
for (vtkIdType i = 0; i < pd->GetNumberOfCells(); ++i)
{
float value = static_cast<float>(i);
newArray->SetTuple(i, &value);
}
fd->AddArray(newArray.GetPointer());
// Set up lookup table
vtkNew<vtkColorTransferFunction> lookupTable;
lookupTable->AddRGBPoint(0.0, 1.0, 1.0, 1.0);
lookupTable->AddRGBPoint(static_cast<float>(pd->GetNumberOfCells()), 1.0, 0.0, 0.0);
vtkNew<vtkPainterPolyDataMapper> mapper;
mapper->SetInputData(pd);
mapper->SetLookupTable(lookupTable.GetPointer());
mapper->SelectColorArray("floatArray");
mapper->SetScalarModeToUseFieldData();
mapper->SetFieldDataTupleId(tupleId);
mapper->ScalarVisibilityOn();
vtkNew<vtkActor> actor;
actor->SetMapper(mapper.GetPointer());
// Render image
vtkNew<vtkRenderer> renderer;
renderer->AddActor(actor.GetPointer());
vtkNew<vtkRenderWindow> renWin;
renWin->SetMultiSamples(0);
renWin->SetAlphaBitPlanes(1);
renWin->AddRenderer(renderer.GetPointer());
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin.GetPointer());
// Compare image
int retVal = vtkRegressionTestImage(renWin.GetPointer());
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
return !retVal;
}
......@@ -254,6 +254,7 @@ void vtkPainterPolyDataMapper::UpdatePainterInformation()
info->Set(vtkScalarsToColorsPainter::ARRAY_ID(), this->ArrayId);
info->Set(vtkScalarsToColorsPainter::ARRAY_NAME(), this->ArrayName);
info->Set(vtkScalarsToColorsPainter::ARRAY_COMPONENT(), this->ArrayComponent);
info->Set(vtkScalarsToColorsPainter::FIELD_DATA_TUPLE_ID(), this->FieldDataTupleId);
info->Set(vtkScalarsToColorsPainter::SCALAR_MATERIAL_MODE(),
this->GetScalarMaterialMode());
......
......@@ -17,6 +17,7 @@
#include "vtkActor.h"
#include "vtkCellData.h"
#include "vtkCellTypes.h"
#include "vtkCompositeDataIterator.h"
#include "vtkCompositeDataSet.h"
#include "vtkDoubleArray.h"
......@@ -80,6 +81,7 @@ vtkInformationKeyMacro(vtkScalarsToColorsPainter, ARRAY_ACCESS_MODE, Integer);
vtkInformationKeyMacro(vtkScalarsToColorsPainter, ARRAY_ID, Integer);
vtkInformationKeyMacro(vtkScalarsToColorsPainter, ARRAY_NAME, String);
vtkInformationKeyMacro(vtkScalarsToColorsPainter, ARRAY_COMPONENT, Integer);
vtkInformationKeyMacro(vtkScalarsToColorsPainter, FIELD_DATA_TUPLE_ID, Integer);
vtkInformationKeyMacro(vtkScalarsToColorsPainter, SCALAR_MATERIAL_MODE, Integer);
//-----------------------------------------------------------------------------
......@@ -89,6 +91,7 @@ vtkScalarsToColorsPainter::vtkScalarsToColorsPainter()
this->ArrayId = -1;
this->ArrayComponent = 0;
this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
this->FieldDataTupleId = -1;
this->ColorMode = VTK_COLOR_MODE_DEFAULT;
this->InterpolateScalarsBeforeMapping = 0;
......@@ -186,6 +189,11 @@ void vtkScalarsToColorsPainter::ProcessInformation(vtkInformation* info)
this->SetArrayComponent(info->Get(ARRAY_COMPONENT()));
}
if (info->Has(FIELD_DATA_TUPLE_ID()))
{
this->SetFieldDataTupleId(info->Get(FIELD_DATA_TUPLE_ID()));
}
if (info->Has(SCALAR_MATERIAL_MODE()))
{
this->SetScalarMaterialMode(info->Get(SCALAR_MATERIAL_MODE()));
......@@ -647,15 +655,58 @@ void vtkScalarsToColorsPainter::MapScalars(vtkDataSet* output,
}
else
{
// Typically, when a name is assigned of the scalars array in PointData or CellData
// it implies 3 component colors. This implication does not hold for FieldData.
// For colors in field data, we use the component count of the color array
// to decide if the colors are opaque colors.
// These colors are nothing but cell colors,
// except when rendering TStrips, in which case they represent
// the triange colors.
colors->SetName("Color");
opfd->AddArray(colors);
if (this->FieldDataTupleId <= -1)
{
// Treat field data as cell-associated data
// Typically, when a name is assigned of the scalars array in PointData or CellData
// it implies 3 component colors. This implication does not hold for FieldData.
// For colors in field data, we use the component count of the color array
// to decide if the colors are opaque colors.
// These colors are nothing but cell colors,
// except when rendering TStrips, in which case they represent
// the triange colors.
colors->SetName("Color");
opfd->AddArray(colors);
}
else
{
vtkUnsignedCharArray* scalarColors =
lut->MapScalars(scalars, this->ColorMode, arraycomponent);
if (this->FieldDataTupleId < scalarColors->GetNumberOfTuples())
{
// Use only the requested tuple's color
unsigned char color[4];
scalarColors->GetTupleValue(this->FieldDataTupleId, color);
vtkUnsignedCharArray* newColors = vtkUnsignedCharArray::New();
newColors->SetNumberOfComponents(4);
newColors->SetNumberOfTuples(input->GetNumberOfCells());
newColors->SetName("Color");
for (vtkIdType i = 0; i < input->GetNumberOfCells(); ++i)
{
newColors->SetTupleValue(i, color);
}
opfd->AddArray(newColors);
if (multiply_with_alpha)
{
vtkMultiplyColorsWithAlpha(newColors);
}
newColors->Delete();
}
else
{
vtkErrorMacro(<< "FieldDataTupleId " << this->FieldDataTupleId << " is greater than "
<< "the number of tuples in the scalarColors array ("
<< scalarColors->GetNumberOfTuples() << ")");
}
if (scalarColors)
{
scalarColors->Delete();
}
}
}
colors->Delete();
}
......
......@@ -95,8 +95,9 @@ public:
// Controls what data array is used to generate colors.
static vtkInformationIntegerKey* ARRAY_ACCESS_MODE();
static vtkInformationIntegerKey* ARRAY_ID();
static vtkInformationStringKey* ARRAY_NAME();
static vtkInformationStringKey* ARRAY_NAME();
static vtkInformationIntegerKey* ARRAY_COMPONENT();
static vtkInformationIntegerKey* FIELD_DATA_TUPLE_ID();
// Description:
// Set the light-model color mode.
......@@ -190,6 +191,7 @@ protected:
vtkSetMacro(ArrayComponent, int);
vtkSetMacro(ArrayId, int);
vtkSetStringMacro(ArrayName);
vtkSetMacro(FieldDataTupleId, vtkIdType);
vtkDataObject* OutputData;
......@@ -197,6 +199,7 @@ protected:
int ArrayComponent;
int ArrayId;
char* ArrayName;
vtkIdType FieldDataTupleId;
vtkScalarsToColors *LookupTable;
// Lookup table provided via the scalars. This gets preference over the one
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment