/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkMeshFileTestHelper_h #define itkMeshFileTestHelper_h /* * This file is contains helper functions for the ITK MeshIO module testing. * It should not be considered as part of the toolkit API and it may change at * any time without notice. We mean it. */ #include "itkMeshFileReader.h" #include "itkMeshFileWriter.h" #include "itksys/SystemTools.hxx" template int TestPointsContainer(typename TMesh::PointsContainerPointer points0, typename TMesh::PointsContainerPointer points1) { using MeshType = TMesh; using PointsContainerConstIterator = typename MeshType::PointsContainerConstIterator; if (points0.IsNotNull() && points1.IsNotNull()) { if (points0->Size() != points1->Size()) { std::cerr << "Input mesh and output mesh have different number of points!" << std::endl; return EXIT_FAILURE; } PointsContainerConstIterator pt0 = points0->Begin(); PointsContainerConstIterator pt1 = points1->Begin(); const double tol = 1e-6; while ((pt0 != points0->End()) && (pt1 != points1->End())) { if (pt0->Index() != pt1->Index()) { std::cerr << "Input mesh and output mesh are different in points!" << std::endl; std::cerr << "Input point ID = " << pt0.Index() << std::endl; std::cerr << "Output point ID = " << pt1.Index() << std::endl; return EXIT_FAILURE; } if (pt0.Value().SquaredEuclideanDistanceTo(pt1.Value()) > tol) { std::cerr << "Input mesh and output mesh are different in points!" << std::endl; std::cerr << "Input point = " << pt0.Value() << std::endl; std::cerr << "Output point = " << pt1.Value() << std::endl; return EXIT_FAILURE; } ++pt0; ++pt1; } } else { if (points0 != points1.GetPointer()) { std::cerr << "Input mesh and output mesh are different in points!" << std::endl; std::cerr << "points0 = " << points0.GetPointer() << std::endl; std::cerr << "points1 = " << points1.GetPointer() << std::endl; return EXIT_FAILURE; } } return EXIT_SUCCESS; } template int TestCellsContainer(typename TMesh::CellsContainerPointer cells0, typename TMesh::CellsContainerPointer cells1) { using MeshType = TMesh; using CellsContainerConstIterator = typename MeshType::CellsContainerConstIterator; using CellPointIdIterator = typename MeshType::CellType::PointIdIterator; if (cells0.IsNotNull() && cells1.IsNotNull()) { if (cells0->Size() != cells1->Size()) { std::cerr << "Input mesh and output mesh have different number of cells!" << std::endl; return EXIT_FAILURE; } CellsContainerConstIterator ceIt0 = cells0->Begin(); CellsContainerConstIterator ceIt1 = cells1->Begin(); while ((ceIt0 != cells0->End()) && (ceIt1 != cells1->End())) { if (ceIt0.Value()->GetType() != ceIt1.Value()->GetType()) { std::cerr << "Input mesh and output mesh are different in cell type!" << std::endl; return EXIT_FAILURE; } if (ceIt0.Index() != ceIt1.Index()) { std::cerr << "Input mesh and output mesh have different cell IDs" << std::endl; std::cerr << "Input mesh cell ID: " << ceIt0.Index() << std::endl; std::cerr << "Output mesh cell ID: " << ceIt1.Index() << std::endl; return EXIT_FAILURE; } CellPointIdIterator pit0 = ceIt0.Value()->PointIdsBegin(); CellPointIdIterator pit1 = ceIt1.Value()->PointIdsBegin(); while (pit0 != ceIt0.Value()->PointIdsEnd()) { if (*pit0 != *pit1) { std::cerr << "Input mesh and output mesh are different in cells!" << std::endl; return EXIT_FAILURE; } ++pit0; ++pit1; } ++ceIt0; ++ceIt1; } } else { if (cells0 != cells1.GetPointer()) { std::cerr << "Input mesh and output mesh are different in cells!" << std::endl; std::cerr << "cells0 = " << cells0.GetPointer() << std::endl; std::cerr << "cells1 = " << cells1.GetPointer() << std::endl; return EXIT_FAILURE; } } return EXIT_SUCCESS; } template int TestPointDataContainer(typename TMesh::PointDataContainerPointer pointData0, typename TMesh::PointDataContainerPointer pointData1) { using MeshType = TMesh; using PointDataContainerIterator = typename MeshType::PointDataContainerIterator; if (pointData0.IsNotNull() && pointData1.IsNotNull()) { if (pointData0->Size() != pointData1->Size()) { std::cerr << "Input mesh and output mesh have different number of point data!" << std::endl; return EXIT_FAILURE; } PointDataContainerIterator pdIt0 = pointData0->Begin(); PointDataContainerIterator pdIt1 = pointData1->Begin(); while ((pdIt0 != pointData0->End()) && (pdIt1 != pointData1->End())) { if (pdIt0->Index() != pdIt1->Index()) { std::cerr << "Input mesh and output mesh are different in point data!" << std::endl; std::cerr << "Input point ID = " << pdIt0.Index() << std::endl; std::cerr << "Output point ID = " << pdIt1.Index() << std::endl; return EXIT_FAILURE; } if (itk::Math::NotExactlyEquals(pdIt0.Value(), pdIt1.Value())) { std::cerr << "Input mesh and output mesh are different in point data!" << std::endl; std::cerr << "Input = " << pdIt0.Value() << std::endl; std::cerr << "Output = " << pdIt1.Value() << std::endl; return EXIT_FAILURE; } ++pdIt0; ++pdIt1; } } else { if (pointData0 != pointData1.GetPointer()) { std::cerr << "Input mesh and output mesh are different in point data!" << std::endl; std::cerr << "pointData0 = " << pointData0.GetPointer() << std::endl; std::cerr << "pointData1 = " << pointData1.GetPointer() << std::endl; return EXIT_FAILURE; } } return EXIT_SUCCESS; } template int TestCellDataContainer(typename TMesh::CellDataContainerPointer cellData0, typename TMesh::CellDataContainerPointer cellData1) { using MeshType = TMesh; using CellDataContainerIterator = typename MeshType::CellDataContainerIterator; if (cellData0.IsNotNull() && cellData1.IsNotNull()) { if (cellData0->Size() != cellData1->Size()) { std::cerr << "Input mesh and output mesh have different number of cell data!" << std::endl; return EXIT_FAILURE; } CellDataContainerIterator cdIt0 = cellData0->Begin(); CellDataContainerIterator cdIt1 = cellData1->Begin(); while (cdIt0 != cellData0->End()) { if (cdIt0->Index() != cdIt1->Index()) { std::cerr << "Input mesh and output mesh are different in cell data!" << std::endl; std::cerr << "Input cell ID = " << cdIt0.Index() << std::endl; std::cerr << "Output cell ID = " << cdIt1.Index() << std::endl; return EXIT_FAILURE; } if (itk::Math::NotExactlyEquals(cdIt0.Value(), cdIt1.Value())) { std::cerr << "Input mesh and output mesh are different in cell data!" << std::endl; std::cerr << "Input = " << cdIt0.Value() << std::endl; std::cerr << "Output = " << cdIt1.Value() << std::endl; return EXIT_FAILURE; } ++cdIt0; ++cdIt1; } } else { if (cellData0 != cellData1.GetPointer()) { std::cerr << "Input mesh and output mesh are different in cell data!" << std::endl; std::cerr << "pointData0 = " << cellData0.GetPointer() << std::endl; std::cerr << "pointData1 = " << cellData1.GetPointer() << std::endl; return EXIT_FAILURE; } } return EXIT_SUCCESS; } template int test(char * inputFileName, char * outputFileName, bool isBinary) { using MeshType = TMesh; using MeshFileReaderType = itk::MeshFileReader; using MeshFileReaderPointer = typename MeshFileReaderType::Pointer; using MeshFileWriterType = itk::MeshFileWriter; using MeshFileWriterPointer = typename MeshFileWriterType::Pointer; MeshFileReaderPointer reader = MeshFileReaderType::New(); reader->SetFileName(inputFileName); try { reader->Update(); } catch (const itk::ExceptionObject & err) { std::cerr << "Read file " << inputFileName << " failed " << std::endl; std::cerr << err << std::endl; return EXIT_FAILURE; } reader->GetMeshIO()->Print(std::cout); if (TMesh::PointDimension != reader->GetMeshIO()->GetPointDimension()) { std::cerr << "Unexpected PointDimension" << std::endl; return EXIT_FAILURE; } MeshFileWriterPointer writer = MeshFileWriterType::New(); if (itksys::SystemTools::GetFilenameLastExtension(inputFileName) == itksys::SystemTools::GetFilenameLastExtension(outputFileName)) { writer->SetMeshIO(reader->GetModifiableMeshIO()); } writer->SetFileName(outputFileName); writer->SetInput(reader->GetOutput()); // NOTE ALEX: we should document the usage if (isBinary) { writer->SetFileTypeAsBINARY(); } try { writer->Update(); } catch (const itk::ExceptionObject & err) { std::cerr << "Write file " << outputFileName << " failed " << std::endl; std::cerr << err << std::endl; return EXIT_FAILURE; } if (!itksys::SystemTools::FilesDiffer(inputFileName, outputFileName)) { return EXIT_SUCCESS; } auto reader1 = MeshFileReaderType::New(); reader1->SetFileName(outputFileName); try { reader1->Update(); } catch (const itk::ExceptionObject & err) { std::cerr << "Read file " << outputFileName << " failed " << std::endl; std::cerr << err << std::endl; return EXIT_FAILURE; } // Test points if (TestPointsContainer(reader->GetOutput()->GetPoints(), reader1->GetOutput()->GetPoints()) == EXIT_FAILURE) { return EXIT_FAILURE; } // Test cells if (TestCellsContainer(reader->GetOutput()->GetCells(), reader1->GetOutput()->GetCells()) == EXIT_FAILURE) { return EXIT_FAILURE; } // Test point data if (TestPointDataContainer(reader->GetOutput()->GetPointData(), reader1->GetOutput()->GetPointData()) == EXIT_FAILURE) { return EXIT_FAILURE; } // Test cell data if (TestCellDataContainer(reader->GetOutput()->GetCellData(), reader1->GetOutput()->GetCellData()) == EXIT_FAILURE) { return EXIT_FAILURE; } return EXIT_SUCCESS; } #endif