Commit 3bd159a4 authored by Will Schroeder's avatar Will Schroeder

Flying edges plane cutter interpolates attributes

The flying edges plane cutter is now interpolating point
attribute data on request (enable InterpolateAttributes).

Some additional tweaks were made to avoid interpolating the scalar
data twice, since the scalar interpolation path overlaps the
general interpolate attributes path.
parent 74575a55
......@@ -142,13 +142,19 @@ void CreateArrayPair(ArrayList *list, T *inData, T *outData,
// A list of the arrays to interpolate, and a method to invoke interpolation on the list
struct ArrayList
{
// The list of arrays
// The list of arrays, and the arrays not to process
std::vector<BaseArrayPair*> Arrays;
std::vector<vtkDataArray*> ExcludedArrays;
// Add the arrays to interpolate here
void AddArrays(vtkIdType numOutPts, vtkDataSetAttributes *inPD,
vtkDataSetAttributes *outPD, double nullValue=0.0);
// Any array excluded here is not added by AddArrays(), hence not
// processed. Also check whether an array is excluded.
void ExcludeArray(vtkDataArray *da);
bool IsExcluded(vtkDataArray *da);
// Loop over the array pairs and copy data from one to another
void Copy(vtkIdType inId, vtkIdType outId)
{
......@@ -208,6 +214,13 @@ struct ArrayList
delete (*it);
}
}
// Return the number of arrays
vtkIdType GetNumberOfArrays()
{
return Arrays.size();
}
};
......
......@@ -28,6 +28,20 @@ void CreateArrayPair(ArrayList *list, T *inData, T *outData,
list->Arrays.push_back(pair);
}
// Indicate arrays not to process
void ArrayList::
ExcludeArray(vtkDataArray *da)
{
ExcludedArrays.push_back(da);
}
// Has the specified array been excluded?
bool ArrayList::
IsExcluded(vtkDataArray *da)
{
return (std::find(ExcludedArrays.begin(), ExcludedArrays.end(), da) != ExcludedArrays.end());
}
// Add the arrays to interpolate here
void ArrayList::
AddArrays(vtkIdType numOutPts, vtkDataSetAttributes *inPD, vtkDataSetAttributes *outPD,
......@@ -44,11 +58,11 @@ AddArrays(vtkIdType numOutPts, vtkDataSetAttributes *inPD, vtkDataSetAttributes
for (i=0; i < numArrays; ++i)
{
oArray = outPD->GetArray(i);
if ( oArray )
if ( oArray && ! this->IsExcluded(oArray) )
{
name = oArray->GetName();
iArray = inPD->GetArray(name);
if ( iArray )
if ( iArray && ! this->IsExcluded(iArray) )
{
iType = iArray->GetDataType();
oType = oArray->GetDataType();
......
......@@ -21,6 +21,7 @@ vtk_add_test_python(
TestFlyingEdges3DWithInterpolation.py
TestFlyingEdgesExtents.py
TestFlyingEdgesPlaneCutter.py
TestFlyingEdgesPlaneCutterInterpolation.py
TestGridSynchronizedTemplates3D.py
TestMarchingSquares.py
TestProbeFilterImageInput.py
......
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
res = 100
# Create the RenderWindow, Renderer and both Actors
#
ren1 = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.SetMultiSamples(0)
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# Create a synthetic source: sample a sphere across a volume
sphere = vtk.vtkSphere()
sphere.SetCenter( 0.0,0.0,0.0)
sphere.SetRadius(0.25)
sample = vtk.vtkSampleFunction()
sample.SetImplicitFunction(sphere)
sample.SetModelBounds(-0.5,0.5, -0.5,0.5, -0.5,0.5)
sample.SetSampleDimensions(res,res,res)
sample.ComputeNormalsOff()
sample.Update()
# Now create some new attributes to interpolate
cyl = vtk.vtkCylinder()
cyl.SetRadius(0.1)
cyl.SetAxis(1,1,1)
attr = vtk.vtkSampleImplicitFunctionFilter()
attr.SetInputConnection(sample.GetOutputPort())
attr.SetImplicitFunction(cyl)
attr.ComputeGradientsOn()
attr.Update()
# The cut plane
plane = vtk.vtkPlane()
plane.SetOrigin(-.2,-.2,-.2)
plane.SetNormal(1,1,1)
# Perform the cutting on named scalars
cut = vtk.vtkFlyingEdgesPlaneCutter()
cut.SetInputConnection(attr.GetOutputPort())
cut.SetInputArrayToProcess(0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS, "scalars")
cut.SetPlane(plane)
cut.ComputeNormalsOff()
cut.InterpolateAttributesOn()
# Time the execution of the filter
timer = vtk.vtkExecutionTimer()
timer.SetFilter(cut)
cut.Update()
CG = timer.GetElapsedWallClockTime()
print ("Cut and interpolate volume:", CG)
cutMapper = vtk.vtkPolyDataMapper()
cutMapper.SetInputConnection(cut.GetOutputPort())
cutMapper.SetScalarModeToUsePointFieldData()
cutMapper.SelectColorArray("Implicit scalars")
cutActor = vtk.vtkActor()
cutActor.SetMapper(cutMapper)
cutActor.GetProperty().SetColor(1,1,1)
cutActor.GetProperty().SetOpacity(1)
# Look at the vectors
ranPts = vtk.vtkMaskPoints()
ranPts.SetOnRatio(25)
ranPts.SetInputConnection(cut.GetOutputPort())
hhog = vtk.vtkHedgeHog()
hhog.SetInputConnection(ranPts.GetOutputPort())
hhog.SetVectorModeToUseVector()
hhog.SetScaleFactor(0.05)
hhogMapper = vtk.vtkPolyDataMapper()
hhogMapper.SetInputConnection(hhog.GetOutputPort())
hhogActor = vtk.vtkActor()
hhogActor.SetMapper(hhogMapper)
hhogActor.GetProperty().SetColor(1,1,1)
hhogActor.GetProperty().SetOpacity(1)
# Outline
outline = vtk.vtkOutlineFilter()
outline.SetInputConnection(sample.GetOutputPort())
outlineMapper = vtk.vtkPolyDataMapper()
outlineMapper.SetInputConnection(outline.GetOutputPort())
outlineActor = vtk.vtkActor()
outlineActor.SetMapper(outlineMapper)
outlineProp = outlineActor.GetProperty()
# Add the actors to the renderer, set the background and size
#
ren1.AddActor(outlineActor)
ren1.AddActor(cutActor)
ren1.AddActor(hhogActor)
ren1.SetBackground(0,0,0)
renWin.SetSize(400,400)
ren1.ResetCamera()
iren.Initialize()
renWin.Render()
# --- end of script --
......@@ -26,7 +26,6 @@
#include "vtkFloatArray.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkMarchingCubesTriangleCases.h"
#include "vtkArrayListTemplate.h"
#include "vtkSMPTools.h"
#include <cmath>
......@@ -36,7 +35,6 @@ vtkStandardNewMacro(vtkFlyingEdges3D);
//----------------------------------------------------------------------------
namespace {
#include "vtkArrayListTemplate.h" // For processing attribute data
}
// This templated class implements the heart of the algorithm.
// vtkFlyingEdges3D populates the information in this class and
......@@ -393,6 +391,7 @@ public:
// Interface between VTK and templated functions
static void Contour(vtkFlyingEdges3D *self, vtkImageData *input,
vtkDataArray *inScalars,
int extent[6], vtkIdType *incs, T *scalars,
vtkPolyData *output, vtkPoints *newPts, vtkCellArray *newTris,
vtkDataArray *newScalars,vtkFloatArray *newNormals,
......@@ -1097,9 +1096,9 @@ GenerateOutput(double value, T* rowPtr, vtkIdType row, vtkIdType slice)
// interfaces the vtkFlyingEdges3D class with the templated algorithm
// class. It also invokes the three passes of the Flying Edges algorithm.
template <class T> void vtkFlyingEdges3DAlgorithm<T>::
Contour(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
vtkIdType *incs, T *scalars, vtkPolyData *output, vtkPoints *newPts,
vtkCellArray *newTris, vtkDataArray *newScalars,
Contour(vtkFlyingEdges3D *self, vtkImageData *input, vtkDataArray *inScalars,
int extent[6], vtkIdType *incs, T *scalars, vtkPolyData *output,
vtkPoints *newPts, vtkCellArray *newTris, vtkDataArray *newScalars,
vtkFloatArray *newNormals, vtkFloatArray *newGradients)
{
double value, *values = self->GetValues();
......@@ -1234,8 +1233,11 @@ Contour(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
{
if ( vidx == 0 ) //first contour
{
// output->GetPointData()->CopyScalarsOff();
// Make sure we don't interpolate the input scalars twice; or generate scalars
// when ComputeScalars is off.
output->GetPointData()->InterpolateAllocate(input->GetPointData(),totalPts);
output->GetPointData()->RemoveArray(inScalars->GetName());
algo.Arrays.ExcludeArray(inScalars);
algo.Arrays.AddArrays(totalPts,input->GetPointData(),output->GetPointData());
}
else
......@@ -1264,6 +1266,8 @@ Contour(vtkFlyingEdges3D *self, vtkImageData *input, int extent[6],
delete [] algo.EdgeMetaData;
}
}//anonymous namespace
//----------------------------------------------------------------------------
// Here is the VTK class proper.
// Construct object with a single contour value of 0.0.
......@@ -1326,7 +1330,7 @@ int vtkFlyingEdges3D::RequestData(
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
vtkDebugMacro(<< "Executing 3D structured contour");
vtkDebugMacro(<< "Executing 3D flying edges");
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
......@@ -1412,7 +1416,7 @@ int vtkFlyingEdges3D::RequestData(
switch (inScalars->GetDataType())
{
vtkTemplateMacro(vtkFlyingEdges3DAlgorithm<VTK_TT>::
Contour(this, input, exExt, incs, (VTK_TT *)ptr,
Contour(this, input, inScalars, exExt, incs, (VTK_TT *)ptr,
output, newPts, newTris, newScalars, newNormals,
newGradients));
}
......
This diff is collapsed.
......@@ -78,6 +78,14 @@ public:
vtkGetMacro(ComputeNormals,int);
vtkBooleanMacro(ComputeNormals,int);
// Description:
// Indicate whether to interpolate other attribute data besides the input
// scalars (which are required). That is, as the isosurface is generated,
// interpolate all other point attribute data across intersected edges.
vtkSetMacro(InterpolateAttributes,int);
vtkGetMacro(InterpolateAttributes,int);
vtkBooleanMacro(InterpolateAttributes,int);
// Description:
// Set/get which component of the scalar array to contour on; defaults to 0.
vtkSetMacro(ArrayComponent, int);
......@@ -89,6 +97,7 @@ protected:
vtkPlane *Plane;
int ComputeNormals;
int InterpolateAttributes;
int ArrayComponent;
virtual int RequestData(vtkInformation *, vtkInformationVector **,
......
......@@ -113,6 +113,7 @@ public:
{
x[0] = this->Algo->Origin[0] + i*this->Algo->Spacing[0];
this->Algo->ImplicitFunction->FunctionGradient(x,n);
vtkMath::Normalize(n);
nPtr = this->Algo->Normals + 3*((i-extent[0])+jOffset+kOffset);
nPtr[0] = static_cast<TT>(-n[0]);
nPtr[1] = static_cast<TT>(-n[1]);
......
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