/*========================================================================= Program: Visualization Toolkit Module: TestParametricSpline.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 "vtkParametricSpline.h" #include "vtkCardinalSpline.h" #include "vtkKochanekSpline.h" #include "vtkPoints.h" #include "vtkMath.h" #include "vtkMathUtilities.h" #include #include "vtkTestErrorObserver.h" void TestPrint(); int TestSetGet(); int TestConstraints(); int TestErrors(); int TestMisc(); int TestSetPoints(vtkPoints *, bool closed = false); void GeneratePoints(int, vtkSmartPointer&); void GenerateRandomPoints(int, vtkSmartPointer&); int UnitTestParametricSpline(int,char *[]) { int status = 0; vtkSmartPointer points = vtkSmartPointer::New(); GeneratePoints(100, points); TestPrint(); status += TestErrors(); status += TestSetGet(); status += TestConstraints(); status += TestSetPoints(points); status += TestSetPoints(points, true); status += TestMisc(); return status == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } void GeneratePoints(int npts, vtkSmartPointer &points) { points->SetNumberOfPoints(npts); double deltaX = vtkMath::Pi() * 2.0 / (npts - 1); double deltaZ = 2.0 / (npts - 1); for (int n = 0; n < npts; ++n) { double x[3]; x[0] = -vtkMath::Pi() + n * deltaX; x[1] = std::sin(x[0]); x[2] = -1.0 + n * deltaZ; points->SetPoint(n, x[0], x[1], x[2]); } } int TestSetPoints(vtkPoints *points, bool closed) { int status = 0; vtkSmartPointer pspline = vtkSmartPointer::New(); if (closed) { pspline->ClosedOn(); } else { pspline->ClosedOff(); } int npts = points->GetNumberOfPoints(); pspline->SetNumberOfPoints(npts); double length = 0.0; vtkPoints* knots = vtkPoints::New(VTK_DOUBLE); knots->SetNumberOfPoints(npts); double xm1[3] = {0.0,0.0,0.0}; double x[3]; for (int n = 0; n < npts; ++n) { points->GetPoint(n, x); pspline->SetPoint(n, x[0], x[1], x[2]); if (n > 0) { length += std::sqrt(vtkMath::Distance2BetweenPoints(x, xm1)); } xm1[0] = x[0]; xm1[1] = x[1]; xm1[2] = x[2]; } if (closed) { points->GetPoint(0, x); points->GetPoint(npts - 1, xm1); length += std::sqrt(vtkMath::Distance2BetweenPoints(x, xm1)); } double tolerance = 4.0*std::numeric_limits::epsilon(); pspline->ParameterizeByLengthOff(); for (int n = 0; n < npts; ++n) { double t[3]; if (closed) { t[0] = static_cast(n) / static_cast((npts)); } else { t[0] = static_cast(n) / static_cast((npts - 1)); } t[1] = t[2] = 0.0; points->GetPoint(n, x); double result[3]; pspline->Evaluate(t, result, nullptr); if (!vtkMathUtilities::FuzzyCompare(x[0], result[0], tolerance) || !vtkMathUtilities::FuzzyCompare(x[1], result[1], tolerance) || !vtkMathUtilities::FuzzyCompare(x[2], result[2], tolerance)) { std::cout << "TestSetPoints(by point id): Expected " << x[0] << ", " << x[1] << ", " << x[2] << " but got " << result[0] << ", " << result[1] << ", " << result[2] << std::endl; ++status; } } // Test with externally created points tolerance = 8.0*std::numeric_limits::epsilon(); pspline->SetPoints(points); pspline->ParameterizeByLengthOn(); double totalLength = length; length = 0.0; for (int n = 0; n < npts; ++n) { points->GetPoint(n, x); if (n > 0) { length += std::sqrt(vtkMath::Distance2BetweenPoints(x, xm1)); } double t[3]; t[0] = length / totalLength; t[1] = t[2] = 0.0; double result[3]; pspline->Evaluate(t, result, nullptr); if (!vtkMathUtilities::FuzzyCompare(x[0], result[0], tolerance) || !vtkMathUtilities::FuzzyCompare(x[1], result[1], tolerance) || !vtkMathUtilities::FuzzyCompare(x[2], result[2], tolerance)) { std::cout << "TestSetPoints(by length): Expected " << x[0] << ", " << x[1] << ", " << x[2] << " but got " << result[0] << ", " << result[1] << ", " << result[2] << std::endl; ++status; } xm1[0] = x[0]; xm1[1] = x[1]; xm1[2] = x[2]; } knots->Delete(); return status; } int TestErrors() { int status = 0; vtkSmartPointer errorObserver = vtkSmartPointer::New(); vtkSmartPointer pspline = vtkSmartPointer::New(); pspline->AddObserver(vtkCommand::ErrorEvent, errorObserver); double x[3]; x[0] = 0.0; x[1] = 0.0; x[2] = 0.0; double result[3]; pspline->Evaluate(x, result, nullptr); // Check for model bounds error if (errorObserver->GetError()) { std::cout << "Caught expected error: " << errorObserver->GetErrorMessage(); } else { std::cout << "Failed to catch expected 'Please specify points' error" << std::endl; ++status; } errorObserver->Clear(); pspline->SetNumberOfPoints(0); pspline->EvaluateScalar(x, nullptr, nullptr); if (errorObserver->GetError()) { std::cout << "Caught expected error: " << errorObserver->GetErrorMessage(); } else { std::cout << "Failed to catch expected 'Please specify at least one point' error" << std::endl; ++status; } errorObserver->Clear(); pspline->SetXSpline(nullptr); pspline->Evaluate(x, result, nullptr); if (errorObserver->GetError()) { std::cout << "Caught expected error: " << errorObserver->GetErrorMessage(); } else { std::cout << "Failed to catch expected 'Please specify spline' error" << std::endl; ++status; } errorObserver->Clear(); return status; } int TestSetGet() { int status = 0; vtkSmartPointer pspline = vtkSmartPointer::New(); if (pspline->GetDimension() != 1) { std::cout << "GetDimension: expected 1 but got " << pspline->GetDimension()<< std::endl; ++status; } if (pspline->GetParameterizeByLength() != 1) { std::cout << "GetParameterizeByLength: expected 1 but got " << pspline->GetParameterizeByLength()<< std::endl; ++status; } if (pspline->GetPoints() != nullptr) { std::cout << "GetPoints: Expected nullptr but got " << pspline->GetPoints() << std::endl; ++status; } std::string className; className = pspline->GetXSpline()->GetClassName(); if (className != "vtkCardinalSpline") { std::cout << "GetXSpline: Expected " << "vtkCardinalSpline" << " but got " << className << std::endl; ++status; } className = pspline->GetYSpline()->GetClassName(); if (className != "vtkCardinalSpline") { std::cout << "GetYSpline: Expected " << "vtkCardinalSpline" << " but got " << className << std::endl; ++status; } className = pspline->GetZSpline()->GetClassName(); if (className != "vtkCardinalSpline") { std::cout << "GetZSpline: Expected " << "vtkCardinalSpline" << " but got " << className << std::endl; ++status; } // Now change the spline tyeps vtkSmartPointer xSpline = vtkSmartPointer::New(); pspline->SetXSpline(xSpline); className = pspline->GetXSpline()->GetClassName(); if (className != "vtkKochanekSpline") { std::cout << "GetXSpline: Expected " << "vtkKochanekSpline" << " but got " << className << std::endl; ++status; } vtkSmartPointer ySpline = vtkSmartPointer::New(); pspline->SetYSpline(ySpline); className = pspline->GetYSpline()->GetClassName(); if (className != "vtkKochanekSpline") { std::cout << "GetYSpline: Expected " << "vtkKochanekSpline" << " but got " << className << std::endl; ++status; } vtkSmartPointer zSpline = vtkSmartPointer::New(); pspline->SetZSpline(zSpline); className = pspline->GetZSpline()->GetClassName(); if (className != "vtkKochanekSpline") { std::cout << "GetZSpline: Expected " << "vtkKochanekSpline" << " but got " << className << std::endl; ++status; } return status; } int TestConstraints() { int status = 0; vtkSmartPointer pspline = vtkSmartPointer::New(); pspline->SetNumberOfPoints(2); double x[3], result[3]; x[0] = x[1] = x[2] = 0.0; pspline->SetPoint(0, x[0], x[1], x[2]); pspline->SetPoint(1, x[0], x[1], x[2]); pspline->SetLeftConstraint(2); pspline->SetLeftValue(0.0); pspline->SetRightConstraint(2); pspline->SetRightValue(0.0); // Force initialize pspline->Evaluate(x, result, nullptr); if (pspline->GetXSpline()->GetLeftConstraint() != pspline->GetLeftConstraint()) { std::cout << "GetXSpline->GetLeftContraint: Expected " << pspline->GetLeftConstraint() << " but got " << pspline->GetXSpline()->GetLeftConstraint() << std::endl; ++status; } if (pspline->GetXSpline()->GetLeftValue() != pspline->GetLeftValue()) { std::cout << "GetXSpline->GetLeftValue: Expected " << pspline->GetLeftValue() << " but got " << pspline->GetXSpline()->GetLeftValue() << std::endl; ++status; } if (pspline->GetYSpline()->GetLeftConstraint() != pspline->GetLeftConstraint()) { std::cout << "GetYSpline->GetLeftContraint: Expected " << pspline->GetLeftConstraint() << " but got " << pspline->GetYSpline()->GetLeftConstraint() << std::endl; ++status; } if (pspline->GetYSpline()->GetLeftValue() != pspline->GetLeftValue()) { std::cout << "GetYSpline->GetLeftValue: Expected " << pspline->GetLeftValue() << " but got " << pspline->GetYSpline()->GetLeftValue() << std::endl; ++status; } if (pspline->GetZSpline()->GetLeftConstraint() != pspline->GetLeftConstraint()) { std::cout << "GetZSpline->GetLeftContraint: Expected " << pspline->GetLeftConstraint() << " but got " << pspline->GetZSpline()->GetLeftConstraint() << std::endl; ++status; } if (pspline->GetZSpline()->GetLeftValue() != pspline->GetLeftValue()) { std::cout << "GetZSpline->GetLeftValue: Expected " << pspline->GetLeftValue() << " but got " << pspline->GetZSpline()->GetLeftValue() << std::endl; ++status; } return status; } int TestMisc() { int status = 0; vtkSmartPointer pspline = vtkSmartPointer::New(); pspline->SetNumberOfPoints(1); double x[3]; x[0] = 1.0; x[1] = 0.0; x[2] = 0.0; if (pspline->EvaluateScalar(x, nullptr, nullptr) != x[0]) { std::cout << "EvaluateScalar: Expected " << x[0] << " but got " << pspline->EvaluateScalar(x, nullptr, nullptr) << std::endl; ++status; } return status; } void TestPrint() { vtkSmartPointer pspline = vtkSmartPointer::New(); // First test uninitialized spline pspline->Print(std::cout); // With Points double x[3]; x[0] = x[1] = x[2] = 0.0; pspline->SetNumberOfPoints(1); pspline->SetPoint(0, x[0], x[1], x[2]); pspline->Print(std::cout); // With nullptr Splines pspline->SetXSpline(nullptr); pspline->SetYSpline(nullptr); pspline->SetZSpline(nullptr); pspline->Print(std::cout); }