Commit b549faf1 authored by Will Schroeder's avatar Will Schroeder

Span space improvements and integration methods

Added vtkSpanSpace performance improvements and integration methods.
Integrated the class with vtkContour3DLinearGrid to accelerate
the contouring operation.
parent d8011ccc
This diff is collapsed.
......@@ -24,16 +24,16 @@
* This class has an API that supports both serial and parallel
* operation. The parallel API enables the using class to grab arrays
* (or batches) of cells that lie along a particular row in the span
* space. These arrays can then be processed separately in parallel.
* space. These arrays can then be processed separately or in parallel.
*
* Learn more about span space in these two publications: 1) "A Near
* Optimal Isosorface Extraction Algorithm Using the Spsn Space."
* Yarden Livnat et al. and 2) Isosurfacing in SPan Space with Utmost
* Optimal Isosorface Extraction Algorithm Using the Span Space."
* Yarden Livnat et al. and 2) Isosurfacing in Span Space with Utmost
* Efficiency." Han-Wei Shen et al.
*
* @sa
* vtkSimpleScalarTree
*/
* vtkScalarTree vtkSimpleScalarTree
*/
#ifndef vtkSpanSpace_h
#define vtkSpanSpace_h
......@@ -41,7 +41,7 @@
#include "vtkCommonExecutionModelModule.h" // For export macro
#include "vtkScalarTree.h"
class vtkInternalSpanSpace;
struct vtkInternalSpanSpace;
class VTKCOMMONEXECUTIONMODEL_EXPORT vtkSpanSpace : public vtkScalarTree
......@@ -81,7 +81,8 @@ public:
// The following methods satisfy the vtkScalarTree abstract API.
/**
* Initialize locator. Frees memory and resets object as appropriate.
* Initialize the span space. Frees memory and resets object as
* appropriate.
*/
void Initialize() override;
......@@ -92,10 +93,11 @@ public:
void BuildTree() override;
/**
* Begin to traverse the cells based on a scalar value. Returned cells
* will have scalar values that span the scalar value specified. Note this
* method must be called prior to parallel or serial traversal since it
* specifies the scalar value to be extracted.
* Begin to traverse the cells based on a scalar value. Returned cells will
* have scalar values that span the scalar value specified (within the
* resolution of the span space). Note this method must be called prior to
* parallel or serial traversal since it specifies the scalar value to be
* extracted.
*/
void InitTraversal(double scalarValue) override;
......@@ -103,7 +105,7 @@ public:
* Return the next cell that may contain scalar value specified to
* InitTraversal(). The value nullptr is returned if the list is
* exhausted. Make sure that InitTraversal() has been invoked first or
* you'll get erratic behavior. This is inherently a serial operation.
* you'll get undefined behavior. This is inherently a serial operation.
*/
vtkCell *GetNextCell(vtkIdType &cellId, vtkIdList* &ptIds,
vtkDataArray *cellScalars) override;
......@@ -115,22 +117,30 @@ public:
// taken from a portion of the span rectangle.
/**
* Get the number of cell batches available for processing. Note
* Get the number of cell batches available for parallel processing. Note
* that this methods should be called after InitTraversal(). This is
* because the number of batches available is typically a function
* of the isocontour value. Note that the cells found in
* [0...(NumberOfCellBatches-1)] will contain all the cells
* potentially containing the isocontour.
* because the number of batches available is typically a function of the
* isocontour value. Note that the cells found in
* [0...(NumberOfCellBatches-1)] will contain the cells potentially
* containing the isocontour.
*/
vtkIdType GetNumberOfCellBatches() override;
/**
* Return the array of cell ids in the specified batch. The method
* also returns the number of cell ids in the array. Make sure to
* call InitTraversal() beforehand.
* Return the array of cell ids in the specified batch. The method also
* returns the number of cell ids in the array. Make sure to call
* InitTraversal() and then GetNumberOfCellBatches() beforehand.
*/
const vtkIdType* GetCellBatch(vtkIdType batchNum,
vtkIdType& numCells) override;
vtkIdType& numCells) override;
//@{
/**
* Set/Get the size of the cell batches when processing in parallel.
*/
vtkSetClampMacro(BatchSize,vtkIdType,100,VTK_INT_MAX);
vtkGetMacro(BatchSize,vtkIdType);
//@}
protected:
vtkSpanSpace();
......
831b4cb02db9edc428e7f57080fb39513fc0c4c2ee912f9918e26a019ee26305d6af8c75eb1f4af98c984f577ec330c6b23946b47a4ea819f1edd9ecab2a9468
......@@ -19,6 +19,7 @@ vtk_add_test_python(
TestCalculatorDataTypes.py,NO_VALID
TestContour3DLinearGrid.py
TestContour3DLinearGrid2.py
TestContour3DLinearGridScalarTree.py
TestDecimatePolylineMaximumError.py
TestElevationFilter.py
TestFlyingEdges2D.py
......
#!/usr/bin/env python
import vtk
# Test vtkContour3DLinearGrid with vtkScalarTree.
# Control test size
#res = 300
res = 50
serialProcessing = 0
mergePoints = 1
interpolateAttr = 0
computeNormals = 0
#
# Quadric definition
quadric = vtk.vtkQuadric()
quadric.SetCoefficients([.5,1,.2,0,.1,0,0,.2,0,0])
sample = vtk.vtkSampleFunction()
sample.SetSampleDimensions(res,res,res)
sample.SetImplicitFunction(quadric)
sample.ComputeNormalsOn()
sample.Update()
#
# Extract voxel cells
extract = vtk.vtkExtractCells()
extract.SetInputConnection(sample.GetOutputPort())
extract.AddCellRange(0,sample.GetOutput().GetNumberOfCells())
extract.Update()
# Now contour the cells, using scalar tree or not
stree = vtk.vtkSpanSpace()
stree.SetDataSet(extract.GetOutput())
contour = vtk.vtkContour3DLinearGrid()
contour.SetInputConnection(extract.GetOutputPort())
contour.SetValue(0, 0.5)
contour.SetMergePoints(mergePoints)
contour.SetSequentialProcessing(serialProcessing)
contour.SetInterpolateAttributes(interpolateAttr);
contour.SetComputeNormals(computeNormals);
contour.UseScalarTreeOff()
contourST = vtk.vtkContour3DLinearGrid()
contourST.SetInputConnection(extract.GetOutputPort())
contourST.SetValue(0, 0.5)
contourST.SetMergePoints(mergePoints)
contourST.SetSequentialProcessing(serialProcessing)
contourST.SetInterpolateAttributes(interpolateAttr);
contourST.SetComputeNormals(computeNormals);
contourST.UseScalarTreeOn()
contourST.SetScalarTree(stree)
contMapper = vtk.vtkPolyDataMapper()
contMapper.SetInputConnection(contour.GetOutputPort())
contMapper.ScalarVisibilityOff()
contActor = vtk.vtkActor()
contActor.SetMapper(contMapper)
contActor.GetProperty().SetColor(.8,.4,.4)
# Compare against standard contouring
contour4 = vtk.vtkContourFilter()
contour4.SetInputConnection(extract.GetOutputPort())
contour4.SetValue(0,0.5)
cont4Mapper = vtk.vtkPolyDataMapper()
cont4Mapper.SetInputConnection(contour4.GetOutputPort())
cont4Mapper.ScalarVisibilityOff()
cont4Actor = vtk.vtkActor()
cont4Actor.SetMapper(cont4Mapper)
cont4Actor.GetProperty().SetColor(.8,.4,.4)
# Timing comparisons
timer = vtk.vtkTimerLog()
timer.StartTimer()
stree.BuildTree()
timer.StopTimer()
streetime = timer.GetElapsedTime()
timer.StartTimer()
contour.Update()
timer.StopTimer()
time = timer.GetElapsedTime()
timer.StartTimer()
contourST.Update()
timer.StopTimer()
timeST = timer.GetElapsedTime()
timer.StartTimer()
contour4.Update()
timer.StopTimer()
time4 = timer.GetElapsedTime()
print("Contouring comparison")
print("\tNumber of threads used: {0}".format(contour.GetNumberOfThreadsUsed()))
print("\tMerge points: {0}".format(mergePoints))
print("\tInterpolate attributes: {0}".format(interpolateAttr))
print("\tCompute Normals: {0}".format(computeNormals))
print("\tBuild scalar tree: {0}".format(streetime))
print("\tLinear 3D contouring (No scalar tree): {0}".format(time))
print("\t\tNumber of points: {0}".format(contour.GetOutput().GetNumberOfPoints()))
print("\t\tNumber of cells: {0}".format(contour.GetOutput().GetNumberOfCells()))
print("\tLinear 3D contouring (With scalar tree): {0}".format(timeST))
print("\t\tNumber of points: {0}".format(contour.GetOutput().GetNumberOfPoints()))
print("\t\tNumber of cells: {0}".format(contour.GetOutput().GetNumberOfCells()))
print("\tStandard contouring: {0}".format(time4))
print("\t\tNumber of points: {0}".format(contour4.GetOutput().GetNumberOfPoints()))
print("\t\tNumber of cells: {0}".format(contour4.GetOutput().GetNumberOfCells()))
# Define graphics objects
renWin = vtk.vtkRenderWindow()
renWin.SetSize(400,200)
renWin.SetMultiSamples(0)
ren1 = vtk.vtkRenderer()
ren1.SetViewport(0,0,0.5,1)
ren1.SetBackground(1,1,1)
cam1 = ren1.GetActiveCamera()
ren4 = vtk.vtkRenderer()
ren4.SetViewport(0.5,0,1,1)
ren4.SetBackground(1,1,1)
ren4.SetActiveCamera(cam1)
renWin.AddRenderer(ren1)
renWin.AddRenderer(ren4)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
ren1.AddActor(contActor)
ren4.AddActor(cont4Actor)
renWin.Render()
ren1.ResetCamera()
renWin.Render()
iren.Initialize()
iren.Start()
# --- end of script --
This diff is collapsed.
......@@ -37,6 +37,11 @@
* many situations the results of the fast path are quite good and do not
* require additional processing.
*
* Finally note that an option exists to use a vtkScalarTree, which is an
* object that accelerates isosurface extraction, at an initial cost of
* building the scalar tree. (This feature is useful for exploratory
* isosurface extraction when the isovalue is frequently changed.)
*
* @warning The fast path simply produces output points and triangles (the
* fast path executes when MergePoints if off; InterpolateAttributes is off;
* and ComputeNormals is off). Since the fast path does not merge points, it
......@@ -81,8 +86,8 @@
*
* @sa
* vtkContourGrid vtkContourFilter vtkFlyingEdges3D vtkMarchingCubes
* vtkPolyDataNormals vtkStaticEdgeLocatorTemplate.h
*/
* vtkPolyDataNormals vtkStaticEdgeLocatorTemplate.h vtkScalarTree
*/
#ifndef vtkContour3DLinearGrid_h
#define vtkContour3DLinearGrid_h
......@@ -92,6 +97,7 @@
#include "vtkContourValues.h" // Needed for inline methods
class vtkUnstructuredGrid;
class vtkScalarTree;
class VTKFILTERSCORE_EXPORT vtkContour3DLinearGrid : public vtkPolyDataAlgorithm
......@@ -168,6 +174,26 @@ public:
*/
vtkMTimeType GetMTime() override;
//@{
/**
* Enable the use of a scalar tree to accelerate contour extraction. By
* default this is off. If enabled, and a scalar tree is not specified, then
* a vtkSpanSpace instance will be constructed and used.
*/
vtkSetMacro(UseScalarTree,vtkTypeBool);
vtkGetMacro(UseScalarTree,vtkTypeBool);
vtkBooleanMacro(UseScalarTree,vtkTypeBool);
//@}
//@{
/**
* Specify the scalar tree to use. By default a vtkSpanSpace scalar tree is
* used.
*/
virtual void SetScalarTree(vtkScalarTree*);
vtkGetObjectMacro(ScalarTree,vtkScalarTree);
//@}
//@{
/**
* Force sequential processing (i.e. single thread) of the contouring
......@@ -213,6 +239,9 @@ protected:
int NumberOfThreadsUsed;
bool LargeIds; //indicate whether integral ids are large(==true) or not
vtkTypeBool UseScalarTree;
vtkScalarTree *ScalarTree;
int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
......
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