You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
492 lines
16 KiB
492 lines
16 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: ExerciseUnstructuredGridRayCastMapper.cxx,v $
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
|
|
#include "ExerciseUnstructuredGridRayCastMapper.h"
|
|
|
|
#include "vtkActor.h"
|
|
#include "vtkArrayCalculator.h"
|
|
#include "vtkAssignAttribute.h"
|
|
#include "vtkCamera.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkColorTransferFunction.h"
|
|
#include "vtkCubeSource.h"
|
|
#include "vtkDataSet.h"
|
|
#include "vtkDataSetTriangleFilter.h"
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkImageMandelbrotSource.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPiecewiseFunction.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPointDataToCellData.h"
|
|
#include "vtkPolyDataMapper.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRenderWindowInteractor.h"
|
|
#include "vtkUnstructuredGridVolumeRayCastFunction.h"
|
|
#include "vtkUnstructuredGridVolumeRayCastMapper.h"
|
|
#include "vtkUnstructuredGridVolumeRayIntegrator.h"
|
|
#include "vtkVolume.h"
|
|
#include "vtkVolumeProperty.h"
|
|
|
|
#include "vtkRegressionTestImage.h"
|
|
|
|
//=============================================================================
|
|
|
|
// A simple filter that will convert an array from independent scalars
|
|
// to dependent scalars.
|
|
class vtkClassifyVolume : public vtkDataSetAlgorithm
|
|
{
|
|
public:
|
|
vtkTypeRevisionMacro(vtkClassifyVolume, vtkDataSetAlgorithm);
|
|
static vtkClassifyVolume *New();
|
|
|
|
vtkGetObjectMacro(TransferFunction, vtkVolumeProperty);
|
|
vtkSetObjectMacro(TransferFunction, vtkVolumeProperty);
|
|
|
|
protected:
|
|
vtkClassifyVolume();
|
|
~vtkClassifyVolume();
|
|
|
|
virtual int RequestData(vtkInformation *, vtkInformationVector **,
|
|
vtkInformationVector *);
|
|
|
|
virtual void Classify(vtkDataSetAttributes *in, vtkDataSetAttributes *out);
|
|
|
|
vtkVolumeProperty *TransferFunction;
|
|
|
|
private:
|
|
vtkClassifyVolume(const vtkClassifyVolume&); // Not implemented
|
|
void operator=(const vtkClassifyVolume&); // Not implemented
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
vtkCxxRevisionMacro(vtkClassifyVolume, "$Revision: 1.4 $");
|
|
vtkStandardNewMacro(vtkClassifyVolume);
|
|
|
|
vtkClassifyVolume::vtkClassifyVolume()
|
|
{
|
|
this->TransferFunction = NULL;
|
|
}
|
|
|
|
vtkClassifyVolume::~vtkClassifyVolume()
|
|
{
|
|
this->SetTransferFunction(NULL);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int vtkClassifyVolume::RequestData(vtkInformation *,
|
|
vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
|
|
vtkDataSet *input = vtkDataSet::SafeDownCast(
|
|
inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
vtkDataSet *output = vtkDataSet::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
output->CopyStructure(input);
|
|
this->Classify(input->GetPointData(), output->GetPointData());
|
|
this->Classify(input->GetCellData(), output->GetCellData());
|
|
|
|
return 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void vtkClassifyVolume::Classify(vtkDataSetAttributes *inAttrib,
|
|
vtkDataSetAttributes *outAttrib)
|
|
{
|
|
vtkDataArray *scalars = inAttrib->GetScalars();
|
|
if (!scalars) return;
|
|
|
|
if (scalars->GetNumberOfComponents() != 1)
|
|
{
|
|
vtkErrorMacro(<< "Only 1-tuple scalars are supported now.");
|
|
return;
|
|
}
|
|
vtkIdType numScalars = scalars->GetNumberOfTuples();
|
|
|
|
vtkDoubleArray *colors = vtkDoubleArray::New();
|
|
colors->SetName(scalars->GetName());
|
|
|
|
if (this->TransferFunction->GetColorChannels() == 3)
|
|
{
|
|
colors->SetNumberOfComponents(4);
|
|
colors->SetNumberOfTuples(numScalars);
|
|
|
|
vtkColorTransferFunction *rgb
|
|
= this->TransferFunction->GetRGBTransferFunction();
|
|
vtkPiecewiseFunction *alpha = this->TransferFunction->GetScalarOpacity();
|
|
|
|
for (vtkIdType i = 0; i < numScalars; i++)
|
|
{
|
|
double c[4];
|
|
double x = scalars->GetComponent(i, 0);
|
|
rgb->GetColor(x, c);
|
|
c[3] = alpha->GetValue(x);
|
|
colors->SetTuple(i, c);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro(<< "Gray values are not supported now.");
|
|
}
|
|
|
|
outAttrib->SetScalars(colors);
|
|
colors->Delete();
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
static vtkRenderer *NewTestViewport(RayCastFunctionCreator NewFunction,
|
|
RayIntegratorCreator NewIntegrator,
|
|
vtkVolumeProperty *volumeProperty,
|
|
int UseCellData, int UseDependentComponents,
|
|
int UseMultipleTransferFunctions)
|
|
{
|
|
// Create the render window.
|
|
vtkRenderer *ren = vtkRenderer::New();
|
|
|
|
// Create a small mesh. The coarser and more opaque the mesh, the easier it
|
|
// is to see rendering errors.
|
|
vtkImageMandelbrotSource *input = vtkImageMandelbrotSource::New();
|
|
input->SetWholeExtent(0, 2, 0, 2, 0, 2);
|
|
input->SetSizeCX(2, 2, 2, 2);
|
|
input->SetMaximumNumberOfIterations(10);
|
|
vtkAlgorithmOutput *outputPort = input->GetOutputPort(0);
|
|
|
|
// Make sure we have only tetrahedra.
|
|
vtkDataSetTriangleFilter *trifilter = vtkDataSetTriangleFilter::New();
|
|
trifilter->SetInputConnection(0, outputPort);
|
|
outputPort = trifilter->GetOutputPort(0);
|
|
|
|
// Make multiple scalars if necessary.
|
|
vtkArrayCalculator *calc = NULL;
|
|
vtkAssignAttribute *assign = NULL;
|
|
if (UseMultipleTransferFunctions)
|
|
{
|
|
calc = vtkArrayCalculator::New();
|
|
calc->AddScalarArrayName("Iterations");
|
|
calc->SetResultArrayName("Result");
|
|
calc->SetFunction("Iterations*iHat + (10-Iterations)*jHat");
|
|
calc->SetInputConnection(0, outputPort);
|
|
outputPort = calc->GetOutputPort(0);
|
|
|
|
assign = vtkAssignAttribute::New();
|
|
assign->Assign(vtkDataSetAttributes::VECTORS, vtkDataSetAttributes::SCALARS,
|
|
vtkAssignAttribute::POINT_DATA);
|
|
assign->SetInputConnection(0, outputPort);
|
|
outputPort = assign->GetOutputPort(0);
|
|
}
|
|
|
|
// Convert to cell centered data if requested.
|
|
vtkPointDataToCellData *celldata = NULL;
|
|
if (UseCellData)
|
|
{
|
|
celldata = vtkPointDataToCellData::New();
|
|
celldata->SetInputConnection(0, outputPort);
|
|
celldata->PassPointDataOff();
|
|
outputPort = celldata->GetOutputPort(0);
|
|
}
|
|
|
|
// Classify the data if testing dependent components.
|
|
vtkClassifyVolume *classify = NULL;
|
|
if (UseDependentComponents)
|
|
{
|
|
classify = vtkClassifyVolume::New();
|
|
classify->SetTransferFunction(volumeProperty);
|
|
classify->SetInputConnection(0, outputPort);
|
|
outputPort = classify->GetOutputPort(0);
|
|
}
|
|
|
|
// Set up the mapper.
|
|
vtkUnstructuredGridVolumeRayCastMapper *mapper
|
|
= vtkUnstructuredGridVolumeRayCastMapper::New();
|
|
mapper->SetInputConnection(0, outputPort);
|
|
if (NewFunction)
|
|
{
|
|
vtkUnstructuredGridVolumeRayCastFunction *function = NewFunction();
|
|
mapper->SetRayCastFunction(function);
|
|
function->Delete();
|
|
}
|
|
if (NewIntegrator)
|
|
{
|
|
vtkUnstructuredGridVolumeRayIntegrator *integrator = NewIntegrator();
|
|
mapper->SetRayIntegrator(integrator);
|
|
integrator->Delete();
|
|
}
|
|
|
|
// The volume holds the mapper and property and can be used to position/orient
|
|
// the volume.
|
|
vtkVolume *volume = vtkVolume::New();
|
|
volume->SetMapper(mapper);
|
|
if (!UseDependentComponents)
|
|
{
|
|
volume->SetProperty(volumeProperty);
|
|
}
|
|
else
|
|
{
|
|
// Set up a volume property that does not have the transfer function.
|
|
vtkVolumeProperty *vp = vtkVolumeProperty::New();
|
|
vp->SetShade(volumeProperty->GetShade());
|
|
vp->SetInterpolationType(volumeProperty->GetInterpolationType());
|
|
vp->SetScalarOpacityUnitDistance(
|
|
volumeProperty->GetScalarOpacityUnitDistance());
|
|
vp->IndependentComponentsOff();
|
|
volume->SetProperty(vp);
|
|
vp->Delete();
|
|
}
|
|
|
|
// Add the volume to the renderer.
|
|
ren->AddVolume(volume);
|
|
|
|
ren->ResetCamera();
|
|
ren->GetActiveCamera()->Azimuth(20.0);
|
|
ren->GetActiveCamera()->Elevation(15.0);
|
|
ren->GetActiveCamera()->Zoom(1.5);
|
|
|
|
// Delete objects. Will not actually be destroyed due to reference counting.
|
|
input->Delete();
|
|
trifilter->Delete();
|
|
if (celldata) celldata->Delete();
|
|
if (calc) calc->Delete();
|
|
if (assign) assign->Delete();
|
|
if (classify) classify->Delete();
|
|
mapper->Delete();
|
|
volume->Delete();
|
|
|
|
return ren;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static vtkRenderer *NewPlaceholderViewport()
|
|
{
|
|
vtkRenderer *ren = vtkRenderer::New();
|
|
|
|
vtkCubeSource *cube = vtkCubeSource::New();
|
|
|
|
vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
|
|
mapper->SetInputConnection(0, cube->GetOutputPort(0));
|
|
cube->Delete();
|
|
|
|
vtkActor *actor = vtkActor::New();
|
|
actor->SetMapper(mapper);
|
|
mapper->Delete();
|
|
|
|
ren->AddActor(actor);
|
|
ren->ResetCamera();
|
|
actor->Delete();
|
|
|
|
return ren;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static vtkVolumeProperty *NewRGBVolumeProperty()
|
|
{
|
|
// Create transfer mapping scalar value to opacity.
|
|
vtkPiecewiseFunction *opacityTransferFunction = vtkPiecewiseFunction::New();
|
|
opacityTransferFunction->AddPoint( 0.0, 0.0);
|
|
opacityTransferFunction->AddPoint(10.0, 1.0);
|
|
|
|
// Create transfer mapping scalar value to color.
|
|
vtkColorTransferFunction *colorTransferFunction
|
|
= vtkColorTransferFunction::New();
|
|
colorTransferFunction->SetColorSpaceToHSV();
|
|
colorTransferFunction->HSVWrapOn();
|
|
colorTransferFunction->AddHSVPoint( 0.0, 4.0/6.0, 1.0, 1.0);
|
|
colorTransferFunction->AddHSVPoint( 4.0, 2.0/6.0, 1.0, 1.0);
|
|
colorTransferFunction->AddHSVPoint( 6.0, 1.0/6.0, 1.0, 1.0);
|
|
colorTransferFunction->AddHSVPoint(10.0, 5.0/6.0, 1.0, 1.0);
|
|
|
|
vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();
|
|
volumeProperty->SetColor(colorTransferFunction);
|
|
volumeProperty->SetScalarOpacity(opacityTransferFunction);
|
|
volumeProperty->ShadeOff();
|
|
volumeProperty->SetInterpolationTypeToLinear();
|
|
volumeProperty->SetScalarOpacityUnitDistance(0.75);
|
|
|
|
// Delete objects. Will not actually be destroyed due to reference counting.
|
|
opacityTransferFunction->Delete();
|
|
colorTransferFunction->Delete();
|
|
|
|
return volumeProperty;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static vtkVolumeProperty *NewGrayVolumeProperty()
|
|
{
|
|
// Create transfer mapping scalar value to opacity.
|
|
vtkPiecewiseFunction *opacityTransferFunction = vtkPiecewiseFunction::New();
|
|
opacityTransferFunction->AddPoint( 0.0, 0.0);
|
|
opacityTransferFunction->AddPoint(10.0, 1.0);
|
|
|
|
// Create transfer mapping scalar value to color.
|
|
vtkPiecewiseFunction *grayTransferFunction = vtkPiecewiseFunction::New();
|
|
grayTransferFunction->AddPoint( 0.0, 0.0);
|
|
grayTransferFunction->AddPoint(10.0, 1.0);
|
|
|
|
vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();
|
|
volumeProperty->SetColor(grayTransferFunction);
|
|
volumeProperty->SetScalarOpacity(opacityTransferFunction);
|
|
volumeProperty->ShadeOff();
|
|
volumeProperty->SetInterpolationTypeToLinear();
|
|
volumeProperty->SetScalarOpacityUnitDistance(0.75);
|
|
|
|
// Delete objects. Will not actually be destroyed due to reference counting.
|
|
opacityTransferFunction->Delete();
|
|
grayTransferFunction->Delete();
|
|
|
|
return volumeProperty;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static vtkVolumeProperty *NewMultiTFVolumeProperty()
|
|
{
|
|
vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();
|
|
volumeProperty->ShadeOff();
|
|
volumeProperty->SetInterpolationTypeToLinear();
|
|
volumeProperty->SetScalarOpacityUnitDistance(0.75);
|
|
|
|
vtkColorTransferFunction *rgb;
|
|
vtkPiecewiseFunction *a;
|
|
|
|
// Create first tf.
|
|
rgb = vtkColorTransferFunction::New();
|
|
rgb->AddRGBPoint(0.0, 1.0, 0.0, 0.0);
|
|
volumeProperty->SetColor(0, rgb);
|
|
rgb->Delete();
|
|
|
|
a = vtkPiecewiseFunction::New();
|
|
a->AddPoint(2.9, 0.0);
|
|
a->AddPoint(3.0, 1.0);
|
|
volumeProperty->SetScalarOpacity(0, a);
|
|
a->Delete();
|
|
|
|
// Create second tf.
|
|
rgb = vtkColorTransferFunction::New();
|
|
rgb->AddRGBPoint(0.0, 0.0, 1.0, 1.0);
|
|
volumeProperty->SetColor(1, rgb);
|
|
rgb->Delete();
|
|
|
|
a = vtkPiecewiseFunction::New();
|
|
a->AddPoint(4.9, 0.0);
|
|
a->AddPoint(5.0, 0.5);
|
|
volumeProperty->SetScalarOpacity(1, a);
|
|
a->Delete();
|
|
|
|
// Create third tf.
|
|
rgb = vtkColorTransferFunction::New();
|
|
rgb->AddRGBPoint(0.0, 0.0, 0.0, 0.0);
|
|
volumeProperty->SetColor(2, rgb);
|
|
rgb->Delete();
|
|
|
|
a = vtkPiecewiseFunction::New();
|
|
a->AddPoint(0.0, 0.0);
|
|
volumeProperty->SetScalarOpacity(2, a);
|
|
a->Delete();
|
|
|
|
return volumeProperty;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int ExerciseUnstructuredGridRayCastMapper(int argc, char *argv[],
|
|
RayCastFunctionCreator NewFunction,
|
|
RayIntegratorCreator NewIntegrator,
|
|
int UseCellData,
|
|
int TestDependentComponents)
|
|
{
|
|
// Create the standard render window and interactor.
|
|
vtkRenderWindow *renWin = vtkRenderWindow::New();
|
|
renWin->SetSize(300, 300);
|
|
|
|
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
|
|
iren->SetRenderWindow(renWin);
|
|
iren->SetDesiredUpdateRate(3.0);
|
|
|
|
// The property describes how the data will look. Establish various
|
|
// rendering modes with the property and its transfer functions.
|
|
vtkVolumeProperty *volumeProperty;
|
|
vtkRenderer *viewport;
|
|
|
|
// RGB transfer function.
|
|
volumeProperty = NewRGBVolumeProperty();
|
|
viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty,
|
|
UseCellData, 0, 0);
|
|
if (!viewport) return -1;
|
|
viewport->SetViewport(0.0, 0.0, 0.5, 0.5);
|
|
renWin->AddRenderer(viewport);
|
|
volumeProperty->Delete();
|
|
viewport->Delete();
|
|
|
|
// Gray transfer function.
|
|
volumeProperty = NewGrayVolumeProperty();
|
|
viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty,
|
|
UseCellData, 0, 0);
|
|
if (!viewport) return -1;
|
|
viewport->SetViewport(0.5, 0.0, 1.0, 0.5);
|
|
renWin->AddRenderer(viewport);
|
|
volumeProperty->Delete();
|
|
viewport->Delete();
|
|
|
|
if (TestDependentComponents)
|
|
{
|
|
// RGBA dependent components.
|
|
volumeProperty = NewRGBVolumeProperty();
|
|
viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty,
|
|
UseCellData, 1, 0);
|
|
volumeProperty->Delete();
|
|
}
|
|
else
|
|
{
|
|
viewport = NewPlaceholderViewport();
|
|
}
|
|
if (!viewport) return -1;
|
|
viewport->SetViewport(0.0, 0.5, 0.5, 1.0);
|
|
renWin->AddRenderer(viewport);
|
|
viewport->Delete();
|
|
|
|
// Multiple transfer functions
|
|
volumeProperty = NewMultiTFVolumeProperty();
|
|
viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty,
|
|
UseCellData, 0, 1);
|
|
if (!viewport) return -1;
|
|
viewport->SetViewport(0.5, 0.5, 1.0, 1.0);
|
|
renWin->AddRenderer(viewport);
|
|
volumeProperty->Delete();
|
|
viewport->Delete();
|
|
|
|
int retVal = vtkRegressionTestImageThreshold(renWin, 70);
|
|
if (retVal == vtkRegressionTester::DO_INTERACTOR)
|
|
{
|
|
iren->Start();
|
|
}
|
|
|
|
// Delete objects.
|
|
renWin->Delete();
|
|
iren->Delete();
|
|
|
|
return !retVal;
|
|
}
|
|
|