/*========================================================================= Program: Visualization Toolkit Module: TestInterpolationDerivs.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. =========================================================================*/ #define VTK_EPSILON 1e-10 #include #include "vtkLagrangeTriangle.h" #include #include "vtkPoints.h" #include "vtkSmartPointer.h" #include "vtkClipDataSet.h" #include "vtkDataSetSurfaceFilter.h" #include "vtkDoubleArray.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkUnstructuredGrid.h" #define VISUAL_DEBUG 1 #ifdef VISUAL_DEBUG #include #include #include #include #include #include #include #include #include #include #endif #include #include namespace { vtkSmartPointer CreateTriangle(int nPoints) { vtkSmartPointer t = vtkSmartPointer::New(); t->GetPointIds()->SetNumberOfIds(nPoints); t->GetPoints()->SetNumberOfPoints(nPoints); t->Initialize(); double* points = t->GetParametricCoords(); for (vtkIdType i=0;iGetPointIds()->SetId(i,i); t->GetPoints()->SetPoint(i,&points[3*i]); } return t; } int TestInterpolationFunction(vtkSmartPointer cell, double eps = VTK_EPSILON) { int numPts = cell->GetNumberOfPoints(); double *sf = new double[numPts]; double *coords = cell->GetParametricCoords(); int r = 0; for(int i=0;iInterpolateFunctions(point, sf); // virtual function for(int j=0;j eps) { std::cout << "fabs(sf[" << j << "] - 1): " << fabs(sf[j] - 1) << std::endl; ++r; } } else { if( fabs(sf[j] - 0) > eps ) { std::cout << "fabs(sf[" << j << "] - 0): " << fabs(sf[j] - 0) << std::endl; ++r; } } } if( fabs(sum - 1) > eps ) { std::cout<<"fabs("<GetParametricCenter(center); cell->InterpolateFunctions(center, sf); // virtual function double sum = 0.; for(int j=0;j eps ) { std::cout<<"center: fabs("< tri, double pcoords[3], double* derivs, double eps = VTK_EPSILON) { vtkIdType nPoints = tri->GetPoints()->GetNumberOfPoints(); double* valp = new double[nPoints]; double* valm = new double[nPoints]; double pcoordsp[3], pcoordsm[3]; for (vtkIdType i=0;i<3;i++) { pcoordsp[i] = pcoordsm[i] = pcoords[i]; } pcoordsp[0] += eps; tri->InterpolateFunctions(pcoordsp,valp); pcoordsm[0] -= eps; tri->InterpolateFunctions(pcoordsm,valm); for (vtkIdType idx = 0; idx < nPoints; idx++) { derivs[idx] = (valp[idx] - valm[idx])/(2.*eps); } for (vtkIdType i=0;i<3;i++) { pcoordsp[i] = pcoordsm[i] = pcoords[i]; } pcoordsp[1] += eps; tri->InterpolateFunctions(pcoordsp,valp); pcoordsm[1] -= eps; tri->InterpolateFunctions(pcoordsm,valm); for (vtkIdType idx = 0; idx < nPoints; idx++) { derivs[nPoints + idx] = (valp[idx] - valm[idx])/(2.*eps); } delete [] valp; delete [] valm; } int TestInterpolationDerivs(vtkSmartPointer cell, double eps = VTK_EPSILON) { int numPts = cell->GetNumberOfPoints(); int dim = cell->GetCellDimension(); double *derivs = new double[dim*numPts]; double *derivs_n = new double[dim*numPts]; double *coords = cell->GetParametricCoords(); int r = 0; for(int i=0;iInterpolateDerivs(point, derivs); InterpolateDerivsNumeric(cell, point, derivs_n, 1.e-10); for(int j=0;j 1.e-5*(fabs(derivs[j]) > numPts ? fabs(derivs[j]) : numPts)) { std::cout<<"Different from numeric! "< eps*numPts ) { std::cout<<"nonzero! "<GetParametricCenter(center); cell->InterpolateDerivs(center, derivs); double sum = 0.; for(int j=0;j eps ) { std::cout<<"center: nonzero!"<GetValue(); sequence->Next(); value[0] = radius*cos(theta) + offset[0]; value[1] = radius*sin(theta) + offset[1]; } void RandomSphere(vtkMinimalStandardRandomSequence* sequence, double radius, double* offset, double* value) { double theta = 2.*vtkMath::Pi()*sequence->GetValue(); sequence->Next(); double phi = vtkMath::Pi()*sequence->GetValue(); sequence->Next(); value[0] = radius*cos(theta)*sin(phi) + offset[0]; value[1] = radius*sin(theta)*sin(phi) + offset[1]; value[2] = radius*cos(phi) + offset[2]; } static int testNum = 0; vtkIdType IntersectWithCell(unsigned nTest, vtkMinimalStandardRandomSequence* sequence, bool threeDimensional, double radius, double* offset, vtkCell* cell #ifdef VISUAL_DEBUG ,vtkSmartPointer renderWindow #endif ) { double p[2][3]; p[0][2] = p[1][2] = 0.; double tol = 1.e-7; double t; double intersect[3]; double pcoords[3]; int subId; vtkIdType counter = 0; vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer vertices = vtkSmartPointer::New(); for (unsigned i=0;iIntersectWithLine(p[0],p[1],tol,t,intersect,pcoords,subId)) { counter++; vtkIdType pid = points->InsertNextPoint(intersect); vertices->InsertNextCell(1,&pid); } } #ifdef VISUAL_DEBUG vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetPosition(0, 0, 2); camera->SetFocalPoint(offset[0],offset[1],offset[2]); vtkSmartPointer renderer = vtkSmartPointer::New(); renderer->SetActiveCamera(camera); renderWindow->AddRenderer(renderer); double dim[4]; ViewportRange(testNum++,dim); renderer->SetViewport(dim[0],dim[2],dim[1],dim[3]); vtkSmartPointer point = vtkSmartPointer::New(); point->SetPoints(points); point->SetVerts(vertices); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputData(point); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); renderer->AddActor(actor); renderer->ResetCamera(); renderWindow->Render(); #endif return counter; } vtkIdType TestClip(vtkCell* cell #ifdef VISUAL_DEBUG ,vtkSmartPointer renderWindow #endif ) { vtkSmartPointer unstructuredGrid = vtkSmartPointer::New(); unstructuredGrid->SetPoints(cell->GetPoints()); vtkSmartPointer cellArray = vtkSmartPointer::New(); cellArray->InsertNextCell(cell); unstructuredGrid->SetCells(cell->GetCellType(), cellArray); vtkSmartPointer radiant = vtkSmartPointer::New(); radiant->SetName("Distance from Origin"); radiant->SetNumberOfTuples(cell->GetPointIds()->GetNumberOfIds()); double maxDist = 0.; for (vtkIdType i = 0; i < cell->GetPointIds()->GetNumberOfIds();i++) { double xyz[3]; cell->GetPoints()->GetPoint(i,xyz); double dist = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1] + xyz[2]*xyz[2]); radiant->SetTypedTuple(i, &dist); maxDist = (dist > maxDist ? dist : maxDist); } unstructuredGrid->GetPointData()->AddArray(radiant); unstructuredGrid->GetPointData()->SetScalars(radiant); vtkSmartPointer clip = vtkSmartPointer::New(); clip->SetValue(maxDist*.5); clip->SetInputData(unstructuredGrid); vtkSmartPointer surfaceFilter = vtkSmartPointer::New(); surfaceFilter->SetInputConnection(clip->GetOutputPort()); surfaceFilter->Update(); vtkPolyData* polydata = surfaceFilter->GetOutput(); #ifdef VISUAL_DEBUG vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetPosition(.5*maxDist, .5*maxDist, -2.*maxDist); camera->SetFocalPoint(.5*maxDist, .5*maxDist, 0); vtkSmartPointer renderer = vtkSmartPointer::New(); renderer->SetActiveCamera(camera); renderWindow->AddRenderer(renderer); double dim[4]; ViewportRange(testNum++,dim); renderer->SetViewport(dim[0],dim[2],dim[1],dim[3]); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputData(polydata); mapper->SetScalarRange(maxDist*.5,maxDist); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); renderer->AddActor(actor); renderWindow->Render(); #endif return polydata->GetNumberOfPoints(); } } int TestLagrangeTriangle(int argc, char* argv[]) { #ifdef VISUAL_DEBUG vtkSmartPointer renderWindow = vtkSmartPointer::New(); renderWindow->SetSize(500,500); vtkSmartPointer renderWindowInteractor = vtkSmartPointer::New(); renderWindowInteractor->SetRenderWindow(renderWindow); #endif int r = 0; static const vtkIdType nIntersections = 78; static const vtkIdType nClippedElems[11]= {0,4,5,12,13,21,25,8}; vtkIdType nPointsForOrder[8] = {-1,3,6,10,15,21,28,7}; for (vtkIdType order = 1; order <= 7; ++order) { vtkSmartPointer t = CreateTriangle(nPointsForOrder[order]); if (t->GetPoints()->GetNumberOfPoints() != 7) { for (vtkIdType i=0;iGetPoints()->GetNumberOfPoints();i++) { vtkIdType bindex[3] = {static_cast(t->GetPoints()->GetPoint(i)[0]*order + .5), static_cast(t->GetPoints()->GetPoint(i)[1]*order + .5), 0}; bindex[2] = order - bindex[0] - bindex[1]; vtkIdType idx = t->ToIndex(bindex); if (i != idx) { std::cout<<"index mismatch for order "<ToBarycentricIndex(i,bindex_); if (bindex[0] != bindex_[0] || bindex[1] != bindex_[1] || bindex[2] != bindex_[2]) { std::cout<<"barycentric index mismatch for order "<SetSeed(1); unsigned nTest = 1.e3; double radius = 1.2; double center[3] = {0.5,0.5,0.}; // interestingly, triangles are invisible edge-on. Test in 3D vtkIdType nHits = IntersectWithCell(nTest,sequence,true,radius,center,t #ifdef VISUAL_DEBUG ,renderWindow #endif ); sequence->Delete(); r += (nHits == nIntersections) ? 0 : 1; if (r) { std::cout< renderer = vtkSmartPointer::New(); renderWindow->AddRenderer(renderer); double dim[4]; ViewportRange(testNum++,dim); renderer->SetViewport(dim[0],dim[2],dim[1],dim[3]); renderer->SetBackground(0.,0.,0.); } renderWindowInteractor->Initialize(); int retVal = vtkRegressionTestImage(renderWindow.GetPointer()); if ( retVal == vtkRegressionTester::DO_INTERACTOR) { renderWindowInteractor->Start(); retVal = vtkRegressionTester::PASSED; } r += (retVal == vtkRegressionTester::PASSED) ? 0 : 1; #endif return r; }