std::vector<double> computeDistances(MeshType::Pointer mesh1, MeshType::Pointer mesh2, unsigned numberOfSamplingPoints) { #if (ITK_VERSION_MAJOR == 4 && ITK_VERSION_MINOR >= 4) typedef itk::PointsLocator< MeshType::PointsContainer > PointsLocatorType; #else typedef itk::PointsLocator<int, 3, double, MeshType::PointsContainer > PointsLocatorType; #endif PointsLocatorType::Pointer ptLocator = PointsLocatorType::New(); ptLocator->SetPoints(mesh2->GetPoints()); ptLocator->Initialize(); // we assume that the mesh points are approximately uniformely distributed. // TODO replace with a real uniform sampling std::vector<double> distanceValues; double totalDist = 0; vnl_random randGen; for (unsigned i = 0; i < numberOfSamplingPoints; i++) { unsigned ptId = randGen.lrand32(mesh1->GetNumberOfPoints() - 1); MeshType::PointType sourcePt = mesh1->GetPoint(ptId); int closestPointId = ptLocator->FindClosestPoint(sourcePt); MeshType::PointType targetPt = mesh2->GetPoint(closestPointId); distanceValues.push_back(computeEuclideanPointDist(sourcePt, targetPt)); } return distanceValues; }
BinaryImageType::Pointer meshToBinaryImage(MeshType::Pointer mesh, unsigned imageResolution, double imageMargin) { typedef itk::TriangleMeshToBinaryImageFilter<MeshType, BinaryImageType> TriangleMeshToBinaryImageFilterType; // We transform the mesh to a binary image TriangleMeshToBinaryImageFilterType::Pointer meshToBinImageFilter = TriangleMeshToBinaryImageFilterType::New(); // we choose the image slightly larger than the bounding box of the mesh const MeshType::BoundingBoxType* boundingBox = mesh->GetBoundingBox(); PointType minPt = boundingBox->GetMinimum(); for (unsigned d = 0; d < 3; d++) {minPt.SetElement(d, minPt.GetElement(d) - imageMargin); } PointType maxPt = boundingBox->GetMaximum(); for (unsigned d = 0; d < 3; d++) {maxPt.SetElement(d, maxPt.GetElement(d) + imageMargin); } meshToBinImageFilter->SetOrigin(minPt); TriangleMeshToBinaryImageFilterType::SizeType size; for (unsigned d = 0; d < 3; d++) { size[d] = imageResolution; } meshToBinImageFilter->SetSize(size); TriangleMeshToBinaryImageFilterType::SpacingType spacing; for (unsigned d = 0; d < 3; d++) { spacing[d] = (maxPt[d] - minPt[d]) / size[d]; } meshToBinImageFilter->SetSpacing(spacing); meshToBinImageFilter->SetInput(mesh); meshToBinImageFilter->Update(); return meshToBinImageFilter->GetOutput(); }
MeshType::Pointer cloneMesh(const MeshType* mesh) { // cloning is cumbersome - therefore we let itk do the job for, and use perform a // Mesh transform using the identity transform. This should result in a perfect clone. typedef itk::IdentityTransform<MeshType::PixelType, 3> IdentityTransformType; typedef itk::TransformMeshFilter<MeshType, MeshType, IdentityTransformType> TransformMeshFilterType; TransformMeshFilterType::Pointer tf = TransformMeshFilterType::New(); tf->SetInput(mesh); IdentityTransformType::Pointer idTrans = IdentityTransformType::New(); tf->SetTransform(idTrans); tf->Update(); MeshType::Pointer clone = tf->GetOutput(); clone->DisconnectPipeline(); return clone; }
/* * mexFunction(): entry point for the mex function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // interface to deal with input arguments from Matlab enum InputIndexType {IN_TRI, IN_X, IN_RES, IN_SIZE, IN_ORIGIN, InputIndexType_MAX}; MatlabImportFilter::Pointer matlabImport = MatlabImportFilter::New(); matlabImport->ConnectToMatlabFunctionInput(nrhs, prhs); // check the number of input arguments matlabImport->CheckNumberOfArguments(2, InputIndexType_MAX); // register the inputs for this function at the import filter typedef MatlabImportFilter::MatlabInputPointer MatlabInputPointer; MatlabInputPointer inTRI = matlabImport->RegisterInput(IN_TRI, "TRI"); MatlabInputPointer inX = matlabImport->RegisterInput(IN_X, "X"); // (x, y, z) MatlabInputPointer inRES = matlabImport->RegisterInput(IN_RES, "RES"); // (r, c, s) MatlabInputPointer inSIZE = matlabImport->RegisterInput(IN_SIZE, "SIZE"); // (r, c, s) MatlabInputPointer inORIGIN = matlabImport->RegisterInput(IN_ORIGIN, "ORIGIN"); // (x, y, z) // interface to deal with outputs to Matlab enum OutputIndexType {OUT_IM, OutputIndexType_MAX}; MatlabExportFilter::Pointer matlabExport = MatlabExportFilter::New(); matlabExport->ConnectToMatlabFunctionOutput(nlhs, plhs); // check that the number of outputs the user is asking for is valid matlabExport->CheckNumberOfArguments(0, OutputIndexType_MAX); // register the outputs for this function at the export filter typedef MatlabExportFilter::MatlabOutputPointer MatlabOutputPointer; MatlabOutputPointer outIM = matlabExport->RegisterOutput(OUT_IM, "IM"); // if any input point set is empty, the outputs are empty too if (mxIsEmpty(inTRI->pm) || mxIsEmpty(inX->pm)) { matlabExport->CopyEmptyArrayToMatlab(outIM); return; } // get number of rows in inputs X and TRI mwSize nrowsX = mxGetM(inX->pm); mwSize nrowsTRI = mxGetM(inTRI->pm); // instantiate mesh MeshType::Pointer mesh = MeshType::New(); // read vertices PointSetType::Pointer xDef = PointSetType::New(); // default: empty point set PointSetType::Pointer x = PointSetType::New(); x->GetPoints()->CastToSTLContainer() = matlabImport->ReadVectorOfVectorsFromMatlab<PointType::CoordRepType, PointType> (inX, xDef->GetPoints()->CastToSTLContainer()); #ifdef DEBUG std::cout << "Number of X points read = " << x->GetNumberOfPoints() << std::endl; #endif // assertion check if (nrowsX != x->GetNumberOfPoints()) { mexErrMsgTxt(("Input " + inX->name + ": Number of points read different from number of points provided by user").c_str()); } // swap XY coordinates to make them compliant with ITK convention // (see important programming note at the help header above) matlabImport->SwapXYInVectorOfVectors<PointType::CoordRepType, std::vector<PointType> > (x->GetPoints()->CastToSTLContainer(), x->GetNumberOfPoints()); // populate mesh with vertices mesh->SetPoints(x->GetPoints()); // read triangles PointType triDef; triDef.Fill(mxGetNaN()); for (mwIndex i = 0; i < nrowsTRI; ++i) { PointType triangle = matlabImport->ReadRowVectorFromMatlab<CoordType, PointType>(inTRI, i, triDef); // create a triangle cell to read the vertex indices of the current input triangle CellAutoPointer cell; cell.TakeOwnership(new TriangleType); // assign to the 0, 1, 2 elements in the triangle cell the vertex // indices that we have just read. Note that we have to substract // 1 to convert Matlab's index convention 1, 2, 3, ... to C++ // convention 0, 1, 2, ... cell->SetPointId(0, triangle[0] - 1); cell->SetPointId(1, triangle[1] - 1); cell->SetPointId(2, triangle[2] - 1); // insert cell into the mesh mesh->SetCell(i, cell); } #ifdef DEBUG std::cout << "Number of triangles read = " << mesh->GetNumberOfCells() << std::endl; #endif // assertion check if (nrowsTRI != mesh->GetNumberOfCells()) { mexErrMsgTxt(("Input " + inTRI->name + ": Number of triangles read different from number of triangles provided by user").c_str()); } // get user input parameters for the output rasterization ImageType::SpacingType spacingDef; spacingDef.Fill(1.0); ImageType::SpacingType spacing = matlabImport-> ReadRowVectorFromMatlab<ImageType::SpacingValueType, ImageType::SpacingType>(inRES, spacingDef); ImageType::SizeType sizeDef; sizeDef.Fill(10); ImageType::SizeType size = matlabImport-> ReadRowVectorFromMatlab<ImageType::SizeValueType, ImageType::SizeType>(inSIZE, sizeDef); ImageType::PointType originDef; originDef.Fill(0.0); ImageType::PointType origin = matlabImport-> ReadRowVectorFromMatlab<ImageType::PointType::ValueType, ImageType::PointType>(inORIGIN, originDef); // (see important programming note at the help header above) matlabImport->SwapXYInVector<ImageType::PointType::ValueType, ImageType::PointType>(origin); // instantiate rasterization filter MeshFilterType::Pointer meshFilter = MeshFilterType::New(); // smallest voxel side length ImageType::SpacingValueType minSpacing = spacing[0]; for (mwIndex i = 1; i < Dimension; ++i) { minSpacing = std::min(minSpacing, spacing[i]); } // pass input parameters to the filter meshFilter->SetInput(mesh); meshFilter->SetSpacing(spacing); meshFilter->SetSize(size); meshFilter->SetOrigin(origin); meshFilter->SetTolerance(minSpacing / 10.0); meshFilter->SetInsideValue(1); meshFilter->SetOutsideValue(0); ImageType::IndexType start; start.Fill(0); meshFilter->SetIndex(start); // convert image size from itk::Size format to std::vector<mwSize> // so that we can use it in GraftItkImageOntoMatlab std::vector<mwSize> sizeStdVector(Dimension); for (unsigned int i = 0; i < Dimension; ++i) { sizeStdVector[i] = size[i]; } // graft ITK filter output onto Matlab output matlabExport->GraftItkImageOntoMatlab<PixelType, Dimension> (outIM, meshFilter->GetOutput(), sizeStdVector); #ifdef DEBUG std::cout << "Resolution (spacing) = " << meshFilter->GetSpacing() << std::endl; std::cout << "Size = " << meshFilter->GetSize() << std::endl; std::cout << "Origin = " << meshFilter->GetOrigin() << std::endl; #endif // run rasterization meshFilter->Update(); }
void mitk::SurfaceStampImageFilter::SurfaceStamp(int time) { mitk::Image::Pointer inputImage = this->GetInput(); const mitk::TimeGeometry *surfaceTimeGeometry = GetInput()->GetTimeGeometry(); const mitk::TimeGeometry *imageTimeGeometry = inputImage->GetTimeGeometry(); // Convert time step from image time-frame to surface time-frame mitk::TimePointType matchingTimePoint = imageTimeGeometry->TimeStepToTimePoint(time); mitk::TimeStepType surfaceTimeStep = surfaceTimeGeometry->TimePointToTimeStep(matchingTimePoint); vtkPolyData *polydata = m_Surface->GetVtkPolyData(surfaceTimeStep); if (!polydata) mitkThrow() << "Polydata is null."; vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); transformFilter->SetInputData(polydata); // transformFilter->ReleaseDataFlagOn(); vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); BaseGeometry::Pointer geometry = surfaceTimeGeometry->GetGeometryForTimeStep(surfaceTimeStep); transform->PostMultiply(); transform->Concatenate(geometry->GetVtkTransform()->GetMatrix()); // take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below. BaseGeometry::Pointer imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time); transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse()); transformFilter->SetTransform(transform); transformFilter->Update(); polydata = transformFilter->GetOutput(); if (!polydata || !polydata->GetNumberOfPoints()) mitkThrow() << "Polydata retrieved from transformation is null or has no points."; MeshType::Pointer mesh = MeshType::New(); mesh->SetCellsAllocationMethod(MeshType::CellsAllocatedDynamicallyCellByCell); unsigned int numberOfPoints = polydata->GetNumberOfPoints(); mesh->GetPoints()->Reserve(numberOfPoints); vtkPoints *points = polydata->GetPoints(); MeshType::PointType point; for (unsigned int i = 0; i < numberOfPoints; i++) { double *aux = points->GetPoint(i); point[0] = aux[0]; point[1] = aux[1]; point[2] = aux[2]; mesh->SetPoint(i, point); } // Load the polygons into the itk::Mesh typedef MeshType::CellAutoPointer CellAutoPointerType; typedef MeshType::CellType CellType; typedef itk::TriangleCell<CellType> TriangleCellType; typedef MeshType::PointIdentifier PointIdentifierType; typedef MeshType::CellIdentifier CellIdentifierType; // Read the number of polygons CellIdentifierType numberOfPolygons = 0; numberOfPolygons = polydata->GetNumberOfPolys(); PointIdentifierType numberOfCellPoints = 3; CellIdentifierType i = 0; for (i = 0; i < numberOfPolygons; i++) { vtkIdList *cellIds; vtkCell *vcell = polydata->GetCell(i); cellIds = vcell->GetPointIds(); CellAutoPointerType cell; auto *triangleCell = new TriangleCellType; PointIdentifierType k; for (k = 0; k < numberOfCellPoints; k++) { triangleCell->SetPointId(k, cellIds->GetId(k)); } cell.TakeOwnership(triangleCell); mesh->SetCell(i, cell); } if (!mesh->GetNumberOfPoints()) mitkThrow() << "Generated itk mesh is empty."; if (m_MakeOutputBinary) { this->SurfaceStampBinaryOutputProcessing(mesh); } else { AccessFixedDimensionByItk_1(inputImage, SurfaceStampProcessing, 3, mesh); } }