Commit a998a796 authored by Will Schroeder's avatar Will Schroeder Committed by Kitware Robot

Merge topic 'UGrid-Optimized-Span-Space'

b549faf1 Span space improvements and integration methods
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard's avatarRobert Maynard <robert.maynard@kitware.com>
Merge-request: !5002
parents d8011ccc b549faf1
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