Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

400 lines
12 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: BoxClipTetrahedra.cxx,v $
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.
=========================================================================*/
/*----------------------------------------------------------------------------
Copyright (c) Sandia Corporation
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/
// This test exercises several ways a plane may clip a tetrahedra. One of the
// things tested is the "winding" of the tetrahedra. There are two rotationally
// independent ways to specify a tetrahedra:
//
// v3 v3
// /|\ /|\ //
// / | \ / | \ //
// / | \ / | \ //
// v2/_ _|_ _\v1 v1/_ _|_ _\v2 //
// \ | / \ | / //
// \ | / \ | / //
// \ | / \ | / //
// \|/ \|/ //
// v0 v0 //
//
// I'm calling these rotationally independent vertex specifications windings for
// short. VTK expects the winding on the left. We will test to make sure the
// winding on the right does not occur.
#include "vtkActor.h"
#include "vtkBoxClipDataSet.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkDataSetSurfaceFilter.h"
#include "vtkDoubleArray.h"
#include "vtkMath.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkUnstructuredGrid.h"
#include "vtkRegressionTestImage.h"
#include "vtkSmartPointer.h"
#define VTK_CREATE(type, var) \
vtkSmartPointer<type> var = vtkSmartPointer<type>::New()
static double tetrahedraPoints[4*3] = {
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
0.0, 1.0, 0.5
};
// All possible cell connectivites with the correct winding.
static vtkIdType tetrahedra[12][4] = {
{ 0, 1, 2, 3 },
{ 2, 0, 1, 3 },
{ 1, 2, 0, 3 },
{ 0, 3, 1, 2 },
{ 1, 0, 3, 2 },
{ 3, 1, 0, 2 },
{ 0, 2, 3, 1 },
{ 3, 0, 2, 1 },
{ 2, 3, 0, 1 },
{ 1, 3, 2, 0 },
{ 2, 1, 3, 0 },
{ 3, 2, 1, 0 }
};
static double minusx[] = { -1.0, 0.0, 0.0 };
static double minusy[] = { 0.0, -1.0, 0.0 };
static double minusz[] = { 0.0, 0.0, -1.0 };
static double plusx[] = { 1.0, 0.0, 0.0 };
static double plusy[] = { 0.0, 1.0, 0.0 };
static double plusz[] = { 0.0, 0.0, 1.0 };
static int NUM_CLIP_BOXES = 8;
class BadWinding
{
public:
BadWinding(vtkUnstructuredGrid *data) {
this->Data = data;
this->Data->Register(NULL);
}
~BadWinding() {
this->Data->UnRegister(NULL);
}
BadWinding(const BadWinding &bw) {
this->Data = bw.Data;
this->Data->Register(NULL);
}
void operator=(const BadWinding &bw) {
this->Data->UnRegister(NULL);
this->Data = bw.Data;
this->Data->Register(NULL);
}
vtkUnstructuredGrid *Data;
};
static void CheckWinding(vtkUnstructuredGrid *data)
{
data->Update();
vtkPoints *points = data->GetPoints();
vtkCellArray *cells = data->GetCells();
cells->InitTraversal();
vtkIdType npts, *pts;
while (cells->GetNextCell(npts, pts))
{
if (npts != 4)
{
cout << "Weird. I got something that is not a tetrahedra." << endl;
continue;
}
double p0[3], p1[3], p2[3], p3[3];
points->GetPoint(pts[0], p0);
points->GetPoint(pts[1], p1);
points->GetPoint(pts[2], p2);
points->GetPoint(pts[3], p3);
// If the winding is correct, the normal to triangle p0,p1,p2 should point
// towards p3.
double v0[3], v1[3];
v0[0] = p1[0] - p0[0]; v0[1] = p1[1] - p0[1]; v0[2] = p1[2] - p0[2];
v1[0] = p2[0] - p0[0]; v1[1] = p2[1] - p0[1]; v1[2] = p2[2] - p0[2];
double n[3];
vtkMath::Cross(v0, v1, n);
double d[3];
d[0] = p3[0] - p0[0]; d[1] = p3[1] - p0[1]; d[2] = p3[2] - p0[2];
if (vtkMath::Dot(n, d) < 0)
{
throw BadWinding(data);
}
}
}
static vtkSmartPointer<vtkUnstructuredGrid> MakeTetrahedron(int num)
{
VTK_CREATE(vtkDoubleArray, pointArray);
pointArray->SetArray(tetrahedraPoints, 4*3, 1);
pointArray->SetNumberOfComponents(3);
pointArray->SetNumberOfTuples(4);
VTK_CREATE(vtkPoints, points);
points->SetData(pointArray);
VTK_CREATE(vtkUnstructuredGrid, ugrid);
ugrid->SetPoints(points);
ugrid->InsertNextCell(VTK_TETRA, 4, tetrahedra[num]);
return ugrid;
}
static void PlaceRenderer(vtkRenderer *renderer, int boxnum, int tetnum,
int boxtype)
{
renderer->SetViewport(tetnum/24.0 + 0.5*(boxtype%2),
1.0 - ( (double)boxnum/NUM_CLIP_BOXES
+ (double)(boxtype/2 + 1)/(2*NUM_CLIP_BOXES) ),
(tetnum + 1)/24.0 + 0.5*(boxtype%2),
1.0 - ( (double)boxnum/NUM_CLIP_BOXES
+ (double)(boxtype/2)/(2*NUM_CLIP_BOXES) ));
}
static void TestBox(vtkRenderWindow *renwin, int boxnum,
double minx, double maxx,
double miny, double maxy,
double minz, double maxz)
{
int i;
// Add tests for axis oriented box and no clipped output.
for (i = 0; i < 12; i++)
{
vtkSmartPointer<vtkUnstructuredGrid> input = MakeTetrahedron(i);
CheckWinding(input);
VTK_CREATE(vtkBoxClipDataSet, clipper);
clipper->SetInput(input);
clipper->GenerateClippedOutputOff();
clipper->SetBoxClip(minx, maxx, miny, maxy, minz, maxz);
clipper->Update();
CheckWinding(clipper->GetOutput());
VTK_CREATE(vtkDataSetSurfaceFilter, surface);
surface->SetInputConnection(0, clipper->GetOutputPort(0));
VTK_CREATE(vtkPolyDataMapper, mapper);
mapper->SetInputConnection(0, surface->GetOutputPort(0));
VTK_CREATE(vtkActor, actor);
actor->SetMapper(mapper);
VTK_CREATE(vtkRenderer, renderer);
renderer->AddActor(actor);
renderer->SetBackground(0.0, 0.5, 0.5);
PlaceRenderer(renderer, boxnum, i, 0);
renderer->ResetCamera();
renwin->AddRenderer(renderer);
vtkCamera *camera = renderer->GetActiveCamera();
camera->Azimuth(25.0);
camera->Elevation(-25.0);
}
// Add tests for axis oriented box and clipped output.
for (i = 0; i < 12; i++)
{
vtkSmartPointer<vtkUnstructuredGrid> input = MakeTetrahedron(i);
CheckWinding(input);
VTK_CREATE(vtkBoxClipDataSet, clipper);
clipper->SetInput(input);
clipper->GenerateClippedOutputOn();
clipper->SetBoxClip(minx, maxx, miny, maxy, minz, maxz);
clipper->Update();
CheckWinding(clipper->GetOutput());
CheckWinding(clipper->GetClippedOutput());
VTK_CREATE(vtkDataSetSurfaceFilter, surface1);
surface1->SetInputConnection(0, clipper->GetOutputPort(0));
VTK_CREATE(vtkPolyDataMapper, mapper1);
mapper1->SetInputConnection(0, surface1->GetOutputPort(0));
VTK_CREATE(vtkActor, actor1);
actor1->SetMapper(mapper1);
VTK_CREATE(vtkDataSetSurfaceFilter, surface2);
surface2->SetInput(clipper->GetClippedOutput());
VTK_CREATE(vtkPolyDataMapper, mapper2);
mapper2->SetInputConnection(0, surface2->GetOutputPort(0));
VTK_CREATE(vtkActor, actor2);
actor2->SetMapper(mapper2);
actor2->GetProperty()->SetColor(1.0, 0.5, 0.5);
VTK_CREATE(vtkRenderer, renderer);
renderer->AddActor(actor1);
renderer->AddActor(actor2);
renderer->SetBackground(0.0, 0.5, 0.5);
PlaceRenderer(renderer, boxnum, i, 1);
renderer->ResetCamera();
renwin->AddRenderer(renderer);
vtkCamera *camera = renderer->GetActiveCamera();
camera->Azimuth(25.0);
camera->Elevation(-25.0);
}
double minpoint[3], maxpoint[3];
minpoint[0] = minx; minpoint[1] = miny; minpoint[2] = minz;
maxpoint[0] = maxx; maxpoint[1] = maxy; maxpoint[2] = maxz;
// Add tests for arbitrarily oriented box and no clipped output.
for (i = 0; i < 12; i++)
{
vtkSmartPointer<vtkUnstructuredGrid> input = MakeTetrahedron(i);
CheckWinding(input);
VTK_CREATE(vtkBoxClipDataSet, clipper);
clipper->SetInput(input);
clipper->GenerateClippedOutputOff();
clipper->SetBoxClip(minusx, minpoint, minusy, minpoint, minusz, minpoint,
plusx, maxpoint, plusy, maxpoint, plusz, maxpoint);
clipper->Update();
CheckWinding(clipper->GetOutput());
VTK_CREATE(vtkDataSetSurfaceFilter, surface);
surface->SetInputConnection(0, clipper->GetOutputPort(0));
VTK_CREATE(vtkPolyDataMapper, mapper);
mapper->SetInputConnection(0, surface->GetOutputPort(0));
VTK_CREATE(vtkActor, actor);
actor->SetMapper(mapper);
VTK_CREATE(vtkRenderer, renderer);
renderer->AddActor(actor);
renderer->SetBackground(0.0, 0.5, 0.5);
PlaceRenderer(renderer, boxnum, i, 2);
renderer->ResetCamera();
renwin->AddRenderer(renderer);
vtkCamera *camera = renderer->GetActiveCamera();
camera->Azimuth(25.0);
camera->Elevation(-25.0);
}
// Add tests for arbitrarily oriented box and clipped output.
for (i = 0; i < 12; i++)
{
vtkSmartPointer<vtkUnstructuredGrid> input = MakeTetrahedron(i);
CheckWinding(input);
VTK_CREATE(vtkBoxClipDataSet, clipper);
clipper->SetInput(input);
clipper->GenerateClippedOutputOn();
clipper->SetBoxClip(minusx, minpoint, minusy, minpoint, minusz, minpoint,
plusx, maxpoint, plusy, maxpoint, plusz, maxpoint);
clipper->Update();
CheckWinding(clipper->GetOutput());
CheckWinding(clipper->GetClippedOutput());
VTK_CREATE(vtkDataSetSurfaceFilter, surface1);
surface1->SetInputConnection(0, clipper->GetOutputPort(0));
VTK_CREATE(vtkPolyDataMapper, mapper1);
mapper1->SetInputConnection(0, surface1->GetOutputPort(0));
VTK_CREATE(vtkActor, actor1);
actor1->SetMapper(mapper1);
VTK_CREATE(vtkDataSetSurfaceFilter, surface2);
surface2->SetInput(clipper->GetClippedOutput());
VTK_CREATE(vtkPolyDataMapper, mapper2);
mapper2->SetInputConnection(0, surface2->GetOutputPort(0));
VTK_CREATE(vtkActor, actor2);
actor2->SetMapper(mapper2);
actor2->GetProperty()->SetColor(1.0, 0.5, 0.5);
VTK_CREATE(vtkRenderer, renderer);
renderer->AddActor(actor1);
renderer->AddActor(actor2);
renderer->SetBackground(0.0, 0.5, 0.5);
PlaceRenderer(renderer, boxnum, i, 3);
renderer->ResetCamera();
renwin->AddRenderer(renderer);
vtkCamera *camera = renderer->GetActiveCamera();
camera->Azimuth(25.0);
camera->Elevation(-25.0);
}
}
int BoxClipTetrahedra(int argc, char *argv[])
{
VTK_CREATE(vtkRenderWindow, renwin);
renwin->SetSize(960, 640);
VTK_CREATE(vtkRenderWindowInteractor, iren);
iren->SetRenderWindow(renwin);
try
{
TestBox(renwin, 0, 0.15, 2.0, -2.0, 2.0, -2.0, 2.0);
TestBox(renwin, 1, -2.0, 0.15, -2.0, 2.0, -2.0, 2.0);
TestBox(renwin, 2, -2.0, 2.0, -2.0, 2.0, -2.0, 0.4);
TestBox(renwin, 3, -2.0, 2.0, -2.0, 2.0, 0.4, 2.0);
TestBox(renwin, 4, -2.0, 2.0, -2.0, 2.0, -2.0, 0.5);
TestBox(renwin, 5, -2.0, 2.0, -2.0, 2.0, 0.5, 2.0);
TestBox(renwin, 6, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0);
TestBox(renwin, 7, 0.0, 2.0, -2.0, 2.0, -2.0, 2.0);
}
catch (BadWinding bw)
{
cout << "Encountered a bad winding. Aborting test." << endl;
return 1;
}
// Run the regression test.
renwin->Render();
int retVal = vtkRegressionTestImage(renwin);
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
return 0;
}
return !retVal;
}