Commit 172ec1b5 authored by Cory Quammen's avatar Cory Quammen Committed by Bill Lorensen
Browse files

ENH: Added boolean operation filters for poly data

Adds classes and tests from the VTK Journal:
http://www.midasjournal.org/browse/publication/797
Boolean Operations on Surfaces in VTK Without External Libraries
Quammen C., Weigle C., Taylor II R.M.
The University of North Carolina at Chapel Hill

Change-Id: I899be4b251a0791e28fdf66c0b69084ff5346bc5
parent 95c71ba1
......@@ -26,6 +26,7 @@ vtkBandedPolyDataContourFilter.cxx
vtkBlankStructuredGrid.cxx
vtkBlankStructuredGridWithImage.cxx
vtkBlockIdScalars.cxx
vtkBooleanOperationPolyDataFilter.cxx
vtkBoxClipDataSet.cxx
vtkBrownianPoints.cxx
vtkButterflySubdivisionFilter.cxx
......@@ -75,6 +76,7 @@ vtkDijkstraGraphGeodesicPath.cxx
vtkDijkstraImageGeodesicPath.cxx
vtkDiscreteMarchingCubes.cxx
vtkDiskSource.cxx
vtkDistancePolyDataFilter.cxx
vtkEdgePoints.cxx
vtkEdgeSubdivisionCriterion.cxx
vtkElevationFilter.cxx
......@@ -140,9 +142,11 @@ vtkIdFilter.cxx
vtkImageDataGeometryFilter.cxx
vtkImageDataToPointSet.cxx
vtkImageMarchingCubes.cxx
vtkImplicitPolyDataDistance.cxx
vtkImplicitTextureCoords.cxx
vtkInterpolateDataSetAttributes.cxx
vtkInterpolatingSubdivisionFilter.cxx
vtkIntersectionPolyDataFilter.cxx
vtkKdTreeSelector.cxx
vtkLevelIdScalars.cxx
vtkLinearExtrusionFilter.cxx
......
......@@ -47,6 +47,7 @@ IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY)
TestTessellator.cxx
TestUncertaintyTubeFilter.cxx
TestDecimatePolylineFilter.cxx
TestImplicitPolyDataDistance.cxx
)
IF(VTK_USE_BOOST)
......@@ -93,6 +94,10 @@ IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY)
UnstructuredGridGradients.cxx
UnstructuredGridCellGradients.cxx
UnstructuredGridFastGradients.cxx
TestBooleanOperationPolyDataFilter.cxx
TestBooleanOperationPolyDataFilter2.cxx
TestDistancePolyDataFilter.cxx
TestIntersectionPolyDataFilter.cxx
)
IF (VTK_USE_PARALLEL)
SET(MyTests ${MyTests}
......@@ -100,8 +105,9 @@ IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY)
)
ENDIF (VTK_USE_PARALLEL)
ENDIF (VTK_DATA_ROOT)
CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests}
EXTRA_INCLUDE vtkTestDriver.h)
INCLUDE(${VTK_SOURCE_DIR}/Rendering/vtkTestingObjectFactory.cmake)
ADD_EXECUTABLE(${KIT}CxxTests ${Tests})
TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkRendering vtkIO)
IF (VTK_USE_PARALLEL)
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestBooleanOperationPolyDataFilter.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.
=========================================================================*/
#include <vtkActor.h>
#include <vtkBooleanOperationPolyDataFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
static vtkActor* GetBooleanOperationActor( double x, int operation )
{
double centerSeparation = 0.15;
vtkSmartPointer<vtkSphereSource> sphere1 =
vtkSmartPointer<vtkSphereSource>::New();
sphere1->SetCenter(-centerSeparation + x, 0.0, 0.0);
vtkSmartPointer<vtkSphereSource> sphere2 =
vtkSmartPointer<vtkSphereSource>::New();
sphere2->SetCenter( centerSeparation + x, 0.0, 0.0);
vtkSmartPointer<vtkBooleanOperationPolyDataFilter> boolFilter =
vtkSmartPointer<vtkBooleanOperationPolyDataFilter>::New();
boolFilter->SetOperation( operation );
boolFilter->SetInputConnection( 0, sphere1->GetOutputPort() );
boolFilter->SetInputConnection( 1, sphere2->GetOutputPort() );
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection( boolFilter->GetOutputPort( 0 ) );
mapper->ScalarVisibilityOff();
vtkActor *actor = vtkActor::New();
actor->SetMapper( mapper );
return actor;
}
int TestBooleanOperationPolyDataFilter(int, char *[])
{
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renWin =
vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renWinInteractor->SetRenderWindow( renWin );
vtkActor *unionActor =
GetBooleanOperationActor( -2.0, vtkBooleanOperationPolyDataFilter::UNION );
renderer->AddActor( unionActor );
unionActor->Delete();
vtkActor *intersectionActor =
GetBooleanOperationActor( 0.0, vtkBooleanOperationPolyDataFilter::INTERSECTION );
renderer->AddActor( intersectionActor );
intersectionActor->Delete();
vtkActor *differenceActor =
GetBooleanOperationActor( 2.0, vtkBooleanOperationPolyDataFilter::DIFFERENCE );
renderer->AddActor( differenceActor );
differenceActor->Delete();
renWin->Render();
renWinInteractor->Start();
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestBooleanOperationPolyDataFilter.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.
=========================================================================*/
#include <vtkActor.h>
#include <vtkAppendPolyData.h>
#include <vtkBooleanOperationPolyDataFilter.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkDistancePolyDataFilter.h>
#include <vtkIntersectionPolyDataFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkReverseSense.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkThreshold.h>
static vtkActor* GetBooleanOperationActor( double x, int operation )
{
double centerSeparation = 0.15;
vtkSmartPointer<vtkSphereSource> sphere1 =
vtkSmartPointer<vtkSphereSource>::New();
sphere1->SetCenter(-centerSeparation + x, 0.0, 0.0);
vtkSmartPointer<vtkSphereSource> sphere2 =
vtkSmartPointer<vtkSphereSource>::New();
sphere2->SetCenter( centerSeparation + x, 0.0, 0.0);
vtkSmartPointer<vtkIntersectionPolyDataFilter> intersection =
vtkSmartPointer<vtkIntersectionPolyDataFilter>::New();
intersection->SetInputConnection( 0, sphere1->GetOutputPort() );
intersection->SetInputConnection( 1, sphere2->GetOutputPort() );
vtkSmartPointer<vtkDistancePolyDataFilter> distance =
vtkSmartPointer<vtkDistancePolyDataFilter>::New();
distance->SetInputConnection( 0, intersection->GetOutputPort( 1 ) );
distance->SetInputConnection( 1, intersection->GetOutputPort( 2 ) );
vtkSmartPointer<vtkThreshold> thresh1 =
vtkSmartPointer<vtkThreshold>::New();
thresh1->AllScalarsOn();
thresh1->SetInputArrayToProcess
( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Distance" );
thresh1->SetInputConnection( distance->GetOutputPort( 0 ) );
vtkSmartPointer<vtkThreshold> thresh2 =
vtkSmartPointer<vtkThreshold>::New();
thresh2->AllScalarsOn();
thresh2->SetInputArrayToProcess
( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Distance" );
thresh2->SetInputConnection( distance->GetOutputPort( 1 ) );
if ( operation == vtkBooleanOperationPolyDataFilter::UNION )
{
thresh1->ThresholdByUpper( 0.0 );
thresh2->ThresholdByUpper( 0.0 );
}
else if ( operation == vtkBooleanOperationPolyDataFilter::INTERSECTION )
{
thresh1->ThresholdByLower( 0.0 );
thresh2->ThresholdByLower( 0.0 );
}
else // Difference
{
thresh1->ThresholdByUpper( 0.0 );
thresh2->ThresholdByLower( 0.0 );
}
vtkSmartPointer<vtkDataSetSurfaceFilter> surface1 =
vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
surface1->SetInputConnection( thresh1->GetOutputPort() );
vtkSmartPointer<vtkDataSetSurfaceFilter> surface2 =
vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
surface2->SetInputConnection( thresh2->GetOutputPort() );
vtkSmartPointer<vtkReverseSense> reverseSense =
vtkSmartPointer<vtkReverseSense>::New();
reverseSense->SetInputConnection( surface2->GetOutputPort() );
if ( operation == 2 ) // difference
{
reverseSense->ReverseCellsOn();
reverseSense->ReverseNormalsOn();
}
vtkSmartPointer<vtkAppendPolyData> appender =
vtkSmartPointer<vtkAppendPolyData>::New();
appender->SetInputConnection( surface1->GetOutputPort() );
if ( operation == 2)
{
appender->AddInputConnection( reverseSense->GetOutputPort() );
}
else
{
appender->AddInputConnection( surface2->GetOutputPort() );
}
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection( appender->GetOutputPort() );
mapper->ScalarVisibilityOff();
vtkActor *actor = vtkActor::New();
actor->SetMapper( mapper );
return actor;
}
int TestBooleanOperationPolyDataFilter2(int, char *[])
{
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renWin =
vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renWinInteractor->SetRenderWindow( renWin );
vtkActor *unionActor =
GetBooleanOperationActor( -2.0, vtkBooleanOperationPolyDataFilter::UNION );
renderer->AddActor( unionActor );
unionActor->Delete();
vtkActor *intersectionActor =
GetBooleanOperationActor( 0.0, vtkBooleanOperationPolyDataFilter::INTERSECTION );
renderer->AddActor( intersectionActor );
intersectionActor->Delete();
vtkActor *differenceActor =
GetBooleanOperationActor( 2.0, vtkBooleanOperationPolyDataFilter::DIFFERENCE );
renderer->AddActor( differenceActor );
differenceActor->Delete();
renWin->Render();
renWinInteractor->Start();
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestDistancePolyDataFilter.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.
=========================================================================*/
#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkDistancePolyDataFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSphereSource.h>
#include <vtkPointData.h>
#include <vtkScalarBarActor.h>
int TestDistancePolyDataFilter(int, char*[])
{
vtkSmartPointer<vtkSphereSource> model1 =
vtkSmartPointer<vtkSphereSource>::New();
model1->SetPhiResolution(11);
model1->SetThetaResolution(11);
model1->SetCenter (0.0, 0.0, 0.0);
vtkSmartPointer<vtkSphereSource> model2 =
vtkSmartPointer<vtkSphereSource>::New();
model2->SetPhiResolution(11);
model2->SetThetaResolution(11);
model2->SetCenter (0.2, 0.3, 0.0);
vtkSmartPointer<vtkDistancePolyDataFilter> distanceFilter =
vtkSmartPointer<vtkDistancePolyDataFilter>::New();
distanceFilter->SetInputConnection( 0, model1->GetOutputPort() );
distanceFilter->SetInputConnection( 1, model2->GetOutputPort() );
distanceFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection( distanceFilter->GetOutputPort() );
mapper->SetScalarRange(
distanceFilter->GetOutput()->GetPointData()->GetScalars()->GetRange()[0],
distanceFilter->GetOutput()->GetPointData()->GetScalars()->GetRange()[1]);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper( mapper );
vtkSmartPointer<vtkPolyDataMapper> mapper2 =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper2->SetInputConnection( distanceFilter->GetOutputPort(1) );
mapper2->SetScalarRange(
distanceFilter->GetSecondDistanceOutput()->GetPointData()->GetScalars()->GetRange()[0],
distanceFilter->GetSecondDistanceOutput()->GetPointData()->GetScalars()->GetRange()[1]);
vtkSmartPointer<vtkActor> actor2 =
vtkSmartPointer<vtkActor>::New();
actor2->SetMapper( mapper2 );
vtkSmartPointer<vtkScalarBarActor> scalarBar =
vtkSmartPointer<vtkScalarBarActor>::New();
scalarBar->SetLookupTable(mapper->GetLookupTable());
scalarBar->SetTitle("Distance");
scalarBar->SetNumberOfLabels(5);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renWin =
vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renWinInteractor->SetRenderWindow( renWin );
renderer->AddActor( actor );
renderer->AddActor( actor2 );
renderer->AddActor2D(scalarBar);
renWin->Render();
distanceFilter->Print(std::cout);
renWinInteractor->Start();
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestImplicitPolyDataDistance.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.
=========================================================================*/
#include <vtkSmartPointer.h>
#include <vtkImplicitPolyDataDistance.h>
#include <vtkPlaneSource.h>
#include <vector>
int TestImplicitPolyDataDistance(int, char*[])
{
vtkSmartPointer<vtkPlaneSource> plane =
vtkSmartPointer<vtkPlaneSource>::New();
plane->SetXResolution(5);
plane->SetYResolution(5);
plane->Update();
vtkSmartPointer<vtkImplicitPolyDataDistance> distance =
vtkSmartPointer<vtkImplicitPolyDataDistance>::New();
distance->SetInput(plane->GetOutput());
// Evaluate at a few points
std::vector<double *> probes;
{
double *probe = new double[3];
probe[0] = probe[1] = 0.0;
probe[2] = 1.0;
probes.push_back(probe);
}
{
double *probe = new double[3];
probe[0] = probe[1] = 0.0;
probe[2] = -1.0;
probes.push_back(probe);
}
{
double *probe = new double[3];
probe[0] = 1.0;
probe[1] = 1.0;
probe[2] = 1.0;
probes.push_back(probe);
}
// Probe at each of the polydata points
for (int i = 0; i < plane->GetOutput()->GetNumberOfPoints(); ++i)
{
double *point = new double[3];
plane->GetOutput()->GetPoint(i, point);
probes.push_back(point);
}
std::vector<double*>::iterator it = probes.begin();
for ( ; it != probes.end(); ++it)
{
double *p = *it;
double result = distance->EvaluateFunction(p);
double gradient[3];
distance->EvaluateGradient(p, gradient);
std::cout << "(" << p[0] << ", " << p[1] << ", " << p[2] << "): "
<< result
<< " gradient(" << gradient[0] << ", "
<< gradient[1] << ", "
<< gradient[2] << ")"
<< std::endl;
}
distance->Print(std::cout);
it = probes.begin();
for ( ; it != probes.end(); ++it)
{
delete [] *it;
}
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestIntersectionPolyDataFilter.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.
=========================================================================*/
#include <vtkIntersectionPolyDataFilter.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
int TestIntersectionPolyDataFilter(int, char *[])
{
vtkSmartPointer<vtkSphereSource> sphereSource1 =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource1->SetCenter(0.0, 0.0, 0.0);
sphereSource1->SetRadius(2.0);
sphereSource1->SetPhiResolution(11);
sphereSource1->SetThetaResolution(21);
sphereSource1->Update();
vtkSmartPointer<vtkPolyDataMapper> sphere1Mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sphere1Mapper->SetInputConnection( sphereSource1->GetOutputPort() );
sphere1Mapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> sphere1Actor =
vtkSmartPointer<vtkActor>::New();
sphere1Actor->SetMapper( sphere1Mapper );
sphere1Actor->GetProperty()->SetOpacity(.3);
sphere1Actor->GetProperty()->SetColor(1,0,0);
sphere1Actor->GetProperty()->SetInterpolationToFlat();
vtkSmartPointer<vtkSphereSource> sphereSource2 =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource2->SetCenter(1.0, 0.0, 0.0);
sphereSource2->SetRadius(2.0);
vtkSmartPointer<vtkPolyDataMapper> sphere2Mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sphere2Mapper->SetInputConnection( sphereSource2->GetOutputPort() );
sphere2Mapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> sphere2Actor =
vtkSmartPointer<vtkActor>::New();
sphere2Actor->SetMapper( sphere2Mapper );
sphere2Actor->GetProperty()->SetOpacity(.3);
sphere2Actor->GetProperty()->SetColor(0,1,0);
sphere2Actor->GetProperty()->SetInterpolationToFlat();
vtkSmartPointer<vtkIntersectionPolyDataFilter> intersectionPolyDataFilter =
vtkSmartPointer<vtkIntersectionPolyDataFilter>::New();
intersectionPolyDataFilter->SetInputConnection( 0, sphereSource1->GetOutputPort() );
intersectionPolyDataFilter->SetInputConnection( 1, sphereSource2->GetOutputPort() );
intersectionPolyDataFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> intersectionMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
intersectionMapper->SetInputConnection( intersectionPolyDataFilter->GetOutputPort() );
intersectionMapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> intersectionActor =
vtkSmartPointer<vtkActor>::New();
intersectionActor->SetMapper( intersectionMapper );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddViewProp(sphere1Actor);
renderer->AddViewProp(sphere2Actor);
renderer->AddViewProp(intersectionActor);
renderer->SetBackground(.1, .2, .3);
vtkSmartPointer<vtkRenderWindow> renderWindow
= vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renWinInteractor->SetRenderWindow( renderWindow );
intersectionPolyDataFilter->Print(std::cout);
renderWindow->Render();
renWinInteractor->Start();
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBooleanOperationPolyDataFilter.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.
=========================================================================*/