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

Merge topic 'FlyingEdges'

d3bea4f5 Refining tests and test images
9112341a Rebased; tweaked tests
ec13363c Used 200grit to polish the code (bugs fixes)
55a7c0e0 Reduce size of dataset processed by TestFlyingEdges3D
9d816358 Fixed skipping non-intersecting slices.
b1b0b635 Get ThreadedSynchronizedTemplates3D to work with more than 4GB.
e897682a COMP: Member template function use on Mac
b3606ce7 Refactored code and thread over slices
...
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !645
parents 249b304a d3bea4f5
......@@ -25,6 +25,8 @@ set(Module_SRCS
vtkExecutionTimer.cxx
vtkFeatureEdges.cxx
vtkFieldDataToAttributeDataFilter.cxx
vtkFlyingEdges2D.cxx
vtkFlyingEdges3D.cxx
vtkGlyph2D.cxx
vtkGlyph3D.cxx
vtkHedgeHog.cxx
......
......@@ -16,6 +16,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
TestDelaunay3D.cxx,NO_VALID
TestExecutionTimer.cxx,NO_VALID
TestFeatureEdges.cxx,NO_VALID
TestFlyingEdges.cxx
TestGlyph3D.cxx
TestHedgeHog.cxx,NO_VALID
TestImplicitPolyDataDistance.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestFlyingEdges.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.
=========================================================================*/
// Description
// This test creates a wavelet dataset and creates isosurfaces using
// vtkFlyingEdges3D
#include "vtkActor.h"
#include "vtkFlyingEdges3D.h"
#include "vtkNew.h"
#include "vtkPolyDataMapper.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRTAnalyticSource.h"
#include "vtkTesting.h"
int TestFlyingEdges(int argc, char *argv[])
{
// Create the sample dataset
vtkNew<vtkRTAnalyticSource> wavelet;
wavelet->SetWholeExtent(-63, 64,
-63, 64,
-63, 64);
wavelet->SetCenter(0.0, 0.0, 0.0);
wavelet->Update();
vtkNew<vtkFlyingEdges3D> flyingEdges;
flyingEdges->SetInputConnection(wavelet->GetOutputPort());
flyingEdges->GenerateValues(6, 128.0, 225.0);
flyingEdges->ComputeNormalsOn();
flyingEdges->ComputeGradientsOn();
flyingEdges->ComputeScalarsOn();
flyingEdges->SetArrayComponent(0);
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(flyingEdges->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper.GetPointer());
vtkNew<vtkRenderer> ren;
ren->AddActor(actor.GetPointer());
vtkNew<vtkRenderWindow> renWin;
renWin->SetSize(399, 401);
renWin->SetMultiSamples(0);
renWin->AddRenderer(ren.GetPointer());
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin.GetPointer());
ren->ResetCamera();
renWin->Render();
int retVal = vtkRegressionTestImage(renWin.GetPointer());
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
return !retVal;
}
......@@ -16,6 +16,8 @@ vtk_add_test_python(
QuadricDecimation.py
StreamPolyData.py
TestElevationFilter.py
TestFlyingEdges2D.py
TestFlyingEdges3D.py
TestGridSynchronizedTemplates3D.py
TestMarchingSquares.py
TestRectilinearSynchronizedTemplates.py
......
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
# 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)
# Pipeline
reader = vtk.vtkPNGReader()
reader.SetFileName("" + str(VTK_DATA_ROOT) + "/Data/fullhead15.png")
iso = vtk.vtkFlyingEdges2D()
iso.SetInputConnection(reader.GetOutputPort())
iso.GenerateValues(12,500,1150)
isoMapper = vtk.vtkPolyDataMapper()
isoMapper.SetInputConnection(iso.GetOutputPort())
isoMapper.ScalarVisibilityOff()
isoActor = vtk.vtkActor()
isoActor.SetMapper(isoMapper)
isoActor.GetProperty().SetColor(1,1,1)
outline = vtk.vtkOutlineFilter()
outline.SetInputConnection(reader.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(isoActor)
ren1.SetBackground(0,0,0)
renWin.SetSize(400,400)
ren1.ResetCamera()
iren.Initialize()
renWin.Render()
# --- end of script --
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
# 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
sphere = vtk.vtkSphere()
sphere.SetCenter( 0.0,0.0,0.0)
sphere.SetRadius(0.25)
# Iso-surface to create geometry. This uses a very small volume to stress
# boundary conditions in vtkFlyingEdges; i.e., we want the sphere isosurface
# to intersect the boundary.
sample = vtk.vtkSampleFunction()
sample.SetImplicitFunction(sphere)
sample.SetModelBounds(-0.5,0.5, -0.5,0.5, -0.5,0.5)
sample.SetSampleDimensions(3,3,3)
iso = vtk.vtkFlyingEdges3D()
iso.SetInputConnection(sample.GetOutputPort())
iso.SetValue(0,0.25)
iso.ComputeNormalsOn()
iso.ComputeGradientsOn()
isoMapper = vtk.vtkPolyDataMapper()
isoMapper.SetInputConnection(iso.GetOutputPort())
isoMapper.ScalarVisibilityOff()
isoActor = vtk.vtkActor()
isoActor.SetMapper(isoMapper)
isoActor.GetProperty().SetColor(1,1,1)
isoActor.GetProperty().SetOpacity(1)
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(isoActor)
ren1.SetBackground(0,0,0)
renWin.SetSize(400,400)
ren1.ResetCamera()
iren.Initialize()
renWin.Render()
# --- end of script --
This diff is collapsed.
/*=========================================================================
Program: Visualization Toolkit
Module: vtkFlyingEdges2D.h
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.
=========================================================================*/
// .NAME vtkFlyingEdges2D - generate isoline(s) from a structured points set
// .SECTION Description
// vtkFlyingEdges2D is a reference implementation of the 2D version of the
// flying edges algorithm. It is designed to be highly scalable (i.e.,
// parallelizable) for large data. It implements certain performance
// optimizations including computational trimming to rapidly eliminate
// processing of data regions, packed bit representation of case table
// values, single edge intersection, elimination of point merging, and
// elimination of any reallocs (due to dynamic data insertion). Note that
// computational trimming is a method to reduce total computational cost in
// which partial computational results can be used to eliminate future
// computations.
//
// This is a four-pass algorithm. The first pass processes all x-edges and
// builds x-edge case values (which, when the two x-edges defining a pixel
// are combined, are equivalent to vertex-based case table except edge-based
// approaches are separable to parallel computing). Next x-pixel rows are
// processed to gather information from y-edges (basically to count the
// number of edge intersections and lines generated). In the third pass a
// prefix sum is used to count and allocate memory for the output
// primitives. Finally in the fourth pass output primitives are generated into
// pre-allocated arrays. This implementation uses pixel cell axes (a x-y dyad
// located at the pixel origin) to ensure that each edge is intersected at
// most one time.
//
// See the paper "Flying Edges: A High-Performance Scalable Isocontouring
// Algorithm" by Schroeder, Maynard, Geveci. Proc. of LDAV 2015. Chicago, IL.
// .SECTION Caveats
// This filter is specialized to 2D images. This implementation can produce
// degenerate line segments (i.e., zero-length line segments).
//
// This class has been threaded with vtkSMPTools. Using TBB or other
// non-sequential type (set in the CMake variable
// VTK_SMP_IMPLEMENTATION_TYPE) may improve performance significantly.
// .SECTION See Also
// vtkContourFilter vtkFlyingEdges3D vtkSynchronizedTemplates2D
// vtkMarchingSquares
#ifndef __vtkFlyingEdges2D_h
#define __vtkFlyingEdges2D_h
#include "vtkFiltersCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
#include "vtkContourValues.h" // Needed for direct access to ContourValues
class vtkImageData;
class VTKFILTERSCORE_EXPORT vtkFlyingEdges2D : public vtkPolyDataAlgorithm
{
public:
static vtkFlyingEdges2D *New();
vtkTypeMacro(vtkFlyingEdges2D,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Because we delegate to vtkContourValues.
unsigned long int GetMTime();
// Description:
// Set a particular contour value at contour number i. The index i ranges
// between 0<=i<NumberOfContours.
void SetValue(int i, double value)
{this->ContourValues->SetValue(i,value);}
// Description:
// Get the ith contour value.
double GetValue(int i)
{return this->ContourValues->GetValue(i);}
// Description:
// Get a pointer to an array of contour values. There will be
// GetNumberOfContours() values in the list.
double *GetValues()
{return this->ContourValues->GetValues();}
// Description:
// Fill a supplied list with contour values. There will be
// GetNumberOfContours() values in the list. Make sure you allocate
// enough memory to hold the list.
void GetValues(double *contourValues)
{this->ContourValues->GetValues(contourValues);}
// Description:
// Set the number of contours to place into the list. You only really
// need to use this method to reduce list size. The method SetValue()
// will automatically increase list size as needed.
void SetNumberOfContours(int number)
{this->ContourValues->SetNumberOfContours(number);}
// Description:
// Get the number of contours in the list of contour values.
int GetNumberOfContours()
{return this->ContourValues->GetNumberOfContours();}
// Description:
// Generate numContours equally spaced contour values between specified
// range. Contour values will include min/max range values.
void GenerateValues(int numContours, double range[2])
{this->ContourValues->GenerateValues(numContours, range);}
// Description:
// Generate numContours equally spaced contour values between specified
// range. Contour values will include min/max range values.
void GenerateValues(int numContours, double rangeStart, double rangeEnd)
{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);}
// Description:
// Option to set the point scalars of the output. The scalars will be the
// iso value of course. By default this flag is on.
vtkSetMacro(ComputeScalars,int);
vtkGetMacro(ComputeScalars,int);
vtkBooleanMacro(ComputeScalars,int);
// Description:
// Set/get which component of the scalar array to contour on; defaults to 0.
vtkSetMacro(ArrayComponent, int);
vtkGetMacro(ArrayComponent, int);
protected:
vtkFlyingEdges2D();
~vtkFlyingEdges2D();
virtual int RequestData(vtkInformation *, vtkInformationVector **,
vtkInformationVector *);
virtual int FillInputPortInformation(int port, vtkInformation *info);
vtkContourValues *ContourValues;
int ComputeScalars;
int ArrayComponent;
private:
vtkFlyingEdges2D(const vtkFlyingEdges2D&); // Not implemented.
void operator=(const vtkFlyingEdges2D&); // Not implemented.
};
#endif
This diff is collapsed.
/*=========================================================================
Program: Visualization Toolkit
Module: vtkFlyingEdges3D.h
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.
=========================================================================*/
// .NAME vtkFlyingEdges3D - generate isosurface from 3D image data (volume)
// .SECTION Description
// vtkFlyingEdges3D is a reference implementation of the 3D version of the
// flying edges algorithm. It is designed to be highly scalable (i.e.,
// parallelizable) for large data. It implements certain performance
// optimizations including computational trimming to rapidly eliminate
// processing of data regions, packed bit representation of case table
// values, single edge intersection, elimination of point merging, and
// elimination of any reallocs (due to dynamic data insertion). Note that
// computational trimming is a method to reduce total computational cost in
// which partial computational results can be used to eliminate future
// computations.
//
// This is a four-pass algorithm. The first pass processes all x-edges and
// builds x-edge case values (which, when the four x-edges defining a voxel
// are combined, are equivalent to vertex-based case table except edge-based
// approaches are separable in support of parallel computing). Next x-voxel
// rows are processed to gather information from yz-edges (basically to count
// the number of y-z edge intersections and triangles generated). In the third
// pass a prefix sum is used to count and allocate memory for the output
// primitives. Finally in the fourth pass output primitives are generated into
// pre-allocated arrays. This implementation uses voxel cell axes (a x-y-z
// triad located at the voxel origin) to ensure that each edge is intersected
// at most one time. Note that this implementation also reuses the VTK
// Marching Cubes case table, although the vertex-based MC table is
// transformed into an edge-based table on object instantiation.
//
// See the paper "Flying Edges: A High-Performance Scalable Isocontouring
// Algorithm" by Schroeder, Maynard, Geveci. Proc. of LDAV 2015. Chicago, IL.
// .SECTION Caveats
// This filter is specialized to 3D volumes. This implementation can produce
// degenerate triangles (i.e., zero-area triangles).
//
// This class has been threaded with vtkSMPTools. Using TBB or other
// non-sequential type (set in the CMake variable
// VTK_SMP_IMPLEMENTATION_TYPE) may improve performance significantly.
// .SECTION See Also
// vtkContourFilter vtkFlyingEdges2D vtkSynchronizedTemplates3D
// vtkMarchingCubes vtkSMPFlyingEdges3D
#ifndef __vtkFlyingEdges3D_h
#define __vtkFlyingEdges3D_h
#include "vtkFiltersCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
#include "vtkContourValues.h" // Passes calls through
class vtkImageData;
class VTKFILTERSCORE_EXPORT vtkFlyingEdges3D : public vtkPolyDataAlgorithm
{
public:
static vtkFlyingEdges3D *New();
vtkTypeMacro(vtkFlyingEdges3D,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Because we delegate to vtkContourValues.
unsigned long int GetMTime();
// Description:
// Set/Get the computation of normals. Normal computation is fairly
// expensive in both time and storage. If the output data will be processed
// by filters that modify topology or geometry, it may be wise to turn
// Normals and Gradients off.
vtkSetMacro(ComputeNormals,int);
vtkGetMacro(ComputeNormals,int);
vtkBooleanMacro(ComputeNormals,int);
// Description:
// Set/Get the computation of gradients. Gradient computation is fairly
// expensive in both time and storage. Note that if ComputeNormals is on,
// gradients will have to be calculated, but will not be stored in the
// output dataset. If the output data will be processed by filters that
// modify topology or geometry, it may be wise to turn Normals and
// Gradients off.
vtkSetMacro(ComputeGradients,int);
vtkGetMacro(ComputeGradients,int);
vtkBooleanMacro(ComputeGradients,int);
// Description:
// Set/Get the computation of scalars.
vtkSetMacro(ComputeScalars,int);
vtkGetMacro(ComputeScalars,int);
vtkBooleanMacro(ComputeScalars,int);
// Description:
// Set a particular contour value at contour number i. The index i ranges
// between 0<=i<NumberOfContours.
void SetValue(int i, double value) {this->ContourValues->SetValue(i,value);}
// Description:
// Get the ith contour value.
double GetValue(int i) {return this->ContourValues->GetValue(i);}
// Description:
// Get a pointer to an array of contour values. There will be
// GetNumberOfContours() values in the list.
double *GetValues() {return this->ContourValues->GetValues();}
// Description:
// Fill a supplied list with contour values. There will be
// GetNumberOfContours() values in the list. Make sure you allocate
// enough memory to hold the list.
void GetValues(double *contourValues) {
this->ContourValues->GetValues(contourValues);}
// Description:
// Set the number of contours to place into the list. You only really
// need to use this method to reduce list size. The method SetValue()
// will automatically increase list size as needed.
void SetNumberOfContours(int number) {
this->ContourValues->SetNumberOfContours(number);}
// Description:
// Get the number of contours in the list of contour values.
int GetNumberOfContours() {
return this->ContourValues->GetNumberOfContours();}
// Description:
// Generate numContours equally spaced contour values between specified
// range. Contour values will include min/max range values.
void GenerateValues(int numContours, double range[2]) {
this->ContourValues->GenerateValues(numContours, range);}
// Description:
// Generate numContours equally spaced contour values between specified
// range. Contour values will include min/max range values.
void GenerateValues(int numContours, double rangeStart, double rangeEnd)
{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);}
// Description:
// Set/get which component of the scalar array to contour on; defaults to 0.
vtkSetMacro(ArrayComponent, int);
vtkGetMacro(ArrayComponent, int);
protected:
vtkFlyingEdges3D();
~vtkFlyingEdges3D();
int ComputeNormals;
int ComputeGradients;
int ComputeScalars;
int ArrayComponent;
vtkContourValues *ContourValues;
virtual int RequestData(vtkInformation *, vtkInformationVector **,
vtkInformationVector *);
virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **,
vtkInformationVector *);
virtual int FillInputPortInformation(int port, vtkInformation *info);
private:
vtkFlyingEdges3D(const vtkFlyingEdges3D&); // Not implemented.
void operator=(const vtkFlyingEdges3D&); // Not implemented.
};
#endif
......@@ -852,8 +852,8 @@ void vtkThreadedSynchronizedTemplates3D::ThreadedExecute(vtkImageData *data,
DoThreadedContour functor(this, exExt, data, inScalars, nPieces);
vtkSMPTools::For( 0, nPieces, functor );
int p = 0;
for (int i = 0; i < functor.GetNumberOfOutputPieces(); ++i)
vtkIdType p = 0;
for (vtkIdType i = 0; i < functor.GetNumberOfOutputPieces(); ++i)
{
vtkPolyData* piece = functor.GetOutputPiece(i);
output->SetBlock(p++, piece);
......
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