Commit bca039e7 authored by T.J. Corona's avatar T.J. Corona
Browse files

Add vtkLinearToQuadraticCellsFilter.

vtkLinearToQuadraticCellsFilter takes an unstructured grid comprised of linear
cells and degree elevates each of the cells to quadratic. Additional points
are simply interpolated from the existing points (there is no snapping to an
external model).
parent 6df2eaec
......@@ -4,6 +4,7 @@ set(Module_SRCS
vtkHierarchicalDataSetGeometryFilter.cxx
vtkImageDataGeometryFilter.cxx
vtkImageDataToUniformGrid.cxx
vtkLinearToQuadraticCellsFilter.cxx
vtkProjectSphereFilter.cxx
vtkRectilinearGridGeometryFilter.cxx
vtkStructuredGridGeometryFilter.cxx
......
......@@ -2,6 +2,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
TestExtractSurfaceNonLinearSubdivision.cxx
TestDataSetSurfaceFieldData.cxx,NO_VALID
TestImageDataToUniformGrid.cxx,NO_VALID
TestLinearToQuadraticCellsFilter.cxx
TestProjectSphereFilter.cxx,NO_VALID
TestStructuredAMRNeighbor.cxx,NO_VALID
TestUniformGridGhostDataGenerator.cxx,NO_VALID
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestLinearToQuadraticCellsFilter.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 <vtkCamera.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkCellIterator.h>
#include <vtkClipDataSet.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkDoubleArray.h>
#include <vtkGenericCell.h>
#include <vtkLinearToQuadraticCellsFilter.h>
#include <vtkPointData.h>
#include <vtkPointLocator.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRegressionTestImage.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkTestUtilities.h>
#include <vtkTetra.h>
#include <vtkUnstructuredGrid.h>
#include <vtkVersion.h>
namespace
{
void AddTetra(const double* p0,
const double* p1,
const double* p2,
const double* p3,
vtkPointLocator* pointLocator,
vtkCellArray* cells)
{
vtkSmartPointer<vtkTetra> t =
vtkSmartPointer<vtkTetra>::New();
static vtkIdType bIndices[4][4] = {{0,0,0,1},
{1,0,0,0},
{0,1,0,0},
{0,0,1,0}};
vtkIdType order = 1;
vtkIdType nPoints = 4;
t->GetPointIds()->SetNumberOfIds(nPoints);
t->GetPoints()->SetNumberOfPoints(nPoints);
t->Initialize();
double p[3];
vtkIdType pId;
vtkIdType* bIndex;
for (vtkIdType i = 0; i < nPoints; i++)
{
bIndex = bIndices[i];
for (vtkIdType j = 0; j < 3; j++)
{
p[j] = (p0[j]*bIndex[3])/order + (p1[j]*bIndex[0])/order +
(p2[j]*bIndex[1])/order + (p3[j]*bIndex[2])/order;
}
pointLocator->InsertUniquePoint(p, pId);
t->GetPointIds()->SetId(i,pId);
}
cells->InsertNextCell(t);
}
}
int TestLinearToQuadraticCellsFilter(int argc, char* argv[])
{
// This test constructs a meshed cube comprised of linear tetrahedra and
// degree elevates the cells to quadratic tetrahedra. The resulting wireframe
// image depicts the subsequent linearization of these cells, so it should
// look like a <2*nX> x <2*nY> x <2*nZ> tetrahedralized cube.
vtkIdType nX = 2;
vtkIdType nY = 2;
vtkIdType nZ = 2;
vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid =
vtkSmartPointer<vtkUnstructuredGrid>::New();
vtkSmartPointer<vtkPoints> pointArray =
vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPointLocator> pointLocator =
vtkSmartPointer<vtkPointLocator>::New();
double bounds[6] = {-1.,1.,-1.,1.,-1.,1.};
pointLocator->InitPointInsertion(pointArray,bounds);
vtkSmartPointer<vtkCellArray> cellArray =
vtkSmartPointer<vtkCellArray>::New();
double p[8][3];
double dx = (bounds[1] - bounds[0])/nX;
double dy = (bounds[3] - bounds[2])/nY;
double dz = (bounds[5] - bounds[4])/nZ;
for (vtkIdType i = 0; i < 8; i++)
{
for (vtkIdType j = 0; j < 3; j++)
{
p[i][j] = bounds[2*j];
}
}
p[1][0] += dx;
p[2][0] += dx;
p[2][1] += dy;
p[3][1] += dy;
p[5][0] += dx;
p[5][2] += dz;
p[6][0] += dx;
p[6][1] += dy;
p[6][2] += dz;
p[7][1] += dy;
p[7][2] += dz;
for (vtkIdType xInc = 0; xInc < nX; xInc++)
{
p[0][1] = p[1][1] = p[4][1] = p[5][1] = bounds[2];
p[2][1] = p[3][1] = p[6][1] = p[7][1] = bounds[2] + dy;
for (vtkIdType yInc = 0; yInc < nY; yInc++)
{
p[0][2] = p[1][2] = p[2][2] = p[3][2] = bounds[4];
p[4][2] = p[5][2] = p[6][2] = p[7][2] = bounds[4] + dz;
for (vtkIdType zInc = 0; zInc < nZ; zInc++)
{
AddTetra(p[0],p[1],p[2],p[5], pointLocator, cellArray);
AddTetra(p[0],p[2],p[3],p[7], pointLocator, cellArray);
AddTetra(p[0],p[5],p[7],p[4], pointLocator, cellArray);
AddTetra(p[2],p[5],p[6],p[7], pointLocator, cellArray);
AddTetra(p[0],p[2],p[5],p[7], pointLocator, cellArray);
for (vtkIdType i = 0; i < 8; i++)
{
p[i][2] += dz;
}
}
for (vtkIdType i = 0; i < 8; i++)
{
p[i][1] += dy;
}
}
for (vtkIdType i = 0; i < 8; i++)
{
p[i][0] += dx;
}
}
unstructuredGrid->SetPoints(pointArray);
unstructuredGrid->SetCells(VTK_TETRA, cellArray);
vtkIdType nPoints = unstructuredGrid->GetPoints()->GetNumberOfPoints();
vtkSmartPointer<vtkDoubleArray> radiant =
vtkSmartPointer<vtkDoubleArray>::New();
radiant->SetName("Distance from Origin");
radiant->SetNumberOfTuples(nPoints);
vtkSmartPointer<vtkDoubleArray> elevation =
vtkSmartPointer<vtkDoubleArray>::New();
elevation->SetName("Elevation");
elevation->SetNumberOfTuples(nPoints);
double maxDist = 0;
for (vtkIdType i = 0; i < nPoints; i++)
{
double xyz[3];
unstructuredGrid->GetPoints()->GetPoint(i,xyz);
double dist = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1] + xyz[2]*xyz[2]);
maxDist = (dist > maxDist ? dist : maxDist);
radiant->SetTypedTuple(i, &dist);
elevation->SetTypedTuple(i, &xyz[2]);
}
unstructuredGrid->GetPointData()->AddArray(radiant);
unstructuredGrid->GetPointData()->AddArray(elevation);
unstructuredGrid->GetPointData()->SetScalars(radiant);
vtkSmartPointer<vtkLinearToQuadraticCellsFilter> degreeElevate =
vtkSmartPointer<vtkLinearToQuadraticCellsFilter>::New();
degreeElevate->SetInputData(unstructuredGrid);
// Visualize
vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
surfaceFilter->SetInputConnection(degreeElevate->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(surfaceFilter->GetOutputPort());
mapper->SetScalarRange(maxDist*.5,maxDist);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetRepresentationToWireframe();
actor->GetProperty()->SetLineWidth(4);
vtkSmartPointer<vtkCamera> camera =
vtkSmartPointer<vtkCamera>::New();
camera->SetPosition(3.*maxDist, 3.*maxDist, -3.*maxDist);
camera->SetFocalPoint(.0, .0, 0.);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->SetActiveCamera(camera);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderWindow->Render();
int retVal = vtkRegressionTestImage(renderWindow);
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
renderWindowInteractor->Start();
}
return !retVal;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkLinearToQuadraticCellsFilter.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 "vtkLinearToQuadraticCellsFilter.h"
#include "vtkAlgorithm.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCellIterator.h"
#include "vtkGenericCell.h"
#include "vtkHexahedron.h"
#include "vtkIncrementalPointLocator.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkLine.h"
#include "vtkMergePoints.h"
#include "vtkPointData.h"
#include "vtkPointLocator.h"
#include "vtkPolygon.h"
#include "vtkPyramid.h"
#include "vtkQuad.h"
#include "vtkTriangle.h"
#include "vtkTetra.h"
#include "vtkWedge.h"
#include "vtkQuadraticEdge.h"
#include "vtkQuadraticHexahedron.h"
#include "vtkQuadraticPolygon.h"
#include "vtkQuadraticPyramid.h"
#include "vtkQuadraticQuad.h"
#include "vtkQuadraticTetra.h"
#include "vtkQuadraticTriangle.h"
#include "vtkQuadraticWedge.h"
#include "vtkUnsignedCharArray.h"
#include "vtkUnstructuredGrid.h"
vtkStandardNewMacro(vtkLinearToQuadraticCellsFilter);
namespace
{
void DegreeElevate(vtkCell* lowerOrderCell,
vtkIncrementalPointLocator* pointLocator,
vtkUnsignedCharArray *types, vtkIdTypeArray *locations,
vtkCellArray* cells, vtkPointData *inPd, vtkPointData *outPd,
vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd)
{
double lowerOrderCoeffs[VTK_CELL_SIZE];
vtkCell* higherOrderCell = NULL;
switch (lowerOrderCell->GetCellType())
{
#define DegreeElevateCase(LowerOrderCellType, HigherOrderCell) \
case LowerOrderCellType: \
higherOrderCell = HigherOrderCell::New(); \
break
DegreeElevateCase(VTK_LINE, vtkQuadraticEdge);
DegreeElevateCase(VTK_TRIANGLE, vtkQuadraticTriangle);
DegreeElevateCase(VTK_QUAD, vtkQuadraticQuad);
DegreeElevateCase(VTK_POLYGON, vtkQuadraticPolygon);
DegreeElevateCase(VTK_TETRA, vtkQuadraticTetra);
DegreeElevateCase(VTK_HEXAHEDRON, vtkQuadraticHexahedron);
DegreeElevateCase(VTK_WEDGE, vtkQuadraticWedge);
DegreeElevateCase(VTK_PYRAMID, vtkQuadraticPyramid);
#undef DegreeElevateMacro
default:
vtkGenericWarningMacro(
<< "vtkLinearToQuadraticCellsFilter does not currently support degree elevating cell type " << lowerOrderCell->GetCellType() << ".");
break;
}
if (higherOrderCell == NULL)
{
return;
}
double *higherOrderPCoords = higherOrderCell->GetParametricCoords();
for (vtkIdType hp = 0; hp < higherOrderCell->GetNumberOfPoints(); hp++)
{
lowerOrderCell->InterpolateFunctions(higherOrderPCoords + (hp*3),
lowerOrderCoeffs);
double higherOrderPoint[3] = {0.,0.,0.};
double lowerOrderPoint[3];
for (vtkIdType lp=0; lp<lowerOrderCell->GetNumberOfPoints(); lp++)
{
// NB: vtkGenericCell creates a local copy of the cell's points, so we
// must use local indexing here (i.e. <lp> instead of
// <lowerOrderCell->GetPointIds()->GetId(lp)>).
lowerOrderCell->GetPoints()->GetPoint(lp, lowerOrderPoint);
;
for (int i = 0; i < 3; i++)
{
higherOrderPoint[i] += lowerOrderPoint[i] * lowerOrderCoeffs[lp];
}
}
vtkIdType pId;
pointLocator->InsertUniquePoint(higherOrderPoint, pId);
higherOrderCell->GetPointIds()->SetId(hp,pId);
outPd->InterpolatePoint(inPd, pId, lowerOrderCell->GetPointIds(),
lowerOrderCoeffs);
}
vtkIdType newCellId = cells->InsertNextCell(higherOrderCell);
locations->InsertNextValue(cells->GetTraversalLocation());
types->InsertNextValue(higherOrderCell->GetCellType());
outCd->CopyData(inCd,cellId,newCellId);
higherOrderCell->Delete();
}
}
//----------------------------------------------------------------------------
vtkLinearToQuadraticCellsFilter::vtkLinearToQuadraticCellsFilter()
{
this->Locator = NULL;
this->OutputPointsPrecision = DEFAULT_PRECISION;
}
//----------------------------------------------------------------------------
vtkLinearToQuadraticCellsFilter::~vtkLinearToQuadraticCellsFilter()
{
if ( this->Locator )
{
this->Locator->UnRegister(this);
this->Locator = NULL;
}
}
//----------------------------------------------------------------------------
// Specify a spatial locator for merging points. By default,
// an instance of vtkMergePoints is used.
void vtkLinearToQuadraticCellsFilter::SetLocator(
vtkIncrementalPointLocator *locator)
{
if (this->Locator == locator)
{
return;
}
if (this->Locator)
{
this->Locator->UnRegister(this);
this->Locator = NULL;
}
if (locator)
{
locator->Register(this);
}
this->Locator = locator;
this->Modified();
}
//----------------------------------------------------------------------------
void vtkLinearToQuadraticCellsFilter::CreateDefaultLocator()
{
if (this->Locator == NULL)
{
this->Locator = vtkMergePoints::New();
}
}
//----------------------------------------------------------------------------
// Overload standard modified time function.
unsigned long vtkLinearToQuadraticCellsFilter::GetMTime()
{
unsigned long mTime=this->Superclass::GetMTime();
unsigned long time;
if (this->Locator != NULL)
{
time = this->Locator->GetMTime();
mTime = (time > mTime ? time : mTime);
}
return mTime;
}
//----------------------------------------------------------------------------
int vtkLinearToQuadraticCellsFilter::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and ouptut
vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkNew<vtkUnsignedCharArray> outputCellTypes;
vtkNew<vtkIdTypeArray> outputCellLocations;
vtkNew<vtkCellArray> outputCellConnectivities;
output->SetPoints(vtkNew<vtkPoints>().GetPointer());
// Set the desired precision for the points in the output.
if (this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
{
output->GetPoints()->SetDataType(input->GetPoints()->GetDataType());
}
else if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
{
output->GetPoints()->SetDataType(VTK_FLOAT);
}
else if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
{
output->GetPoints()->SetDataType(VTK_DOUBLE);
}
// locator used to merge potentially duplicate points
if (this->Locator == NULL)
{
this->CreateDefaultLocator();
}
this->Locator->InitPointInsertion(output->GetPoints(), input->GetBounds());
vtkIdType estimatedSize = input->GetNumberOfCells();
estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024
if (estimatedSize < 1024)
{
estimatedSize = 1024;
}
output->GetPointData()->InterpolateAllocate(
input->GetPointData(),estimatedSize,estimatedSize/2);
output->GetCellData()->CopyAllocate(
input->GetCellData(),estimatedSize,estimatedSize/2);
vtkGenericCell *cell = vtkGenericCell::New();
vtkCellIterator *it = input->NewCellIterator();
for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextCell())
{
it->GetCell(cell);
DegreeElevate(cell, this->Locator, outputCellTypes.GetPointer(),
outputCellLocations.GetPointer(),
outputCellConnectivities.GetPointer(),
input->GetPointData(), output->GetPointData(),
input->GetCellData(), it->GetCellId(), output->GetCellData());
}
it->Delete();
cell->Delete();
output->SetCells(outputCellTypes.GetPointer(),
outputCellLocations.GetPointer(),
outputCellConnectivities.GetPointer());
this->Locator->Initialize();//release any extra memory
output->Squeeze();
return 1;
}
//----------------------------------------------------------------------------
void vtkLinearToQuadraticCellsFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkLinearToQuadraticCellsFilter.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 vtkLinearToQuadraticCellsFilter - degree elevate the cells of a linear unstructured grid.
//
// .SECTION Description
// vtkLinearToQuadraticCellsFilter takes an unstructured grid comprised of
// linear cells and degree elevates each of the cells to quadratic. Additional
// points are simply interpolated from the existing points (there is no snapping
// to an external model).
#ifndef vtkLinearToQuadraticCellsFilter_h
#define vtkLinearToQuadraticCellsFilter_h
#include "vtkFiltersGeometryModule.h" // For export macro
#include "vtkUnstructuredGridAlgorithm.h"
class vtkIncrementalPointLocator;
class VTKFILTERSGEOMETRY_EXPORT vtkLinearToQuadraticCellsFilter :
public vtkUnstructuredGridAlgorithm
{
public:
vtkTypeMacro(vtkLinearToQuadraticCellsFilter,vtkUnstructuredGridAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
static vtkLinearToQuadraticCellsFilter *New();
// Description:
// Specify a spatial locator for merging points. By default, an