ITK  5.4.0
Insight Toolkit
Examples/DataRepresentation/Mesh/MeshCellVisitor2.cxx
/*=========================================================================
*
* 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.
*
*=========================================================================*/
// Software Guide : BeginLatex
//
// The following section illustrates a realistic example of the use of Cell
// visitors on the \doxygen{Mesh}. A set of different visitors is defined
// here, each visitor associated with a particular type of cell. All the
// visitors are registered with a MultiVisitor class which is passed to the
// mesh.
//
// The first step is to include the \code{CellInterfaceVisitor} header file.
//
// \index{itk::Mesh!CellVisitor}
// \index{itk::Mesh!CellInterfaceVisitor}
// \index{CellVisitor}
// \index{CellInterfaceVisitor}
//
// Software Guide : EndLatex
#include "itkMesh.h"
#include "itkLineCell.h"
// Software Guide : BeginCodeSnippet
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The typical mesh types are now declared.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
using PixelType = float;
using MeshType = itk::Mesh<PixelType, 3>;
using CellType = MeshType::CellType;
using VertexType = itk::VertexCell<CellType>;
using LineType = itk::LineCell<CellType>;
using TriangleType = itk::TriangleCell<CellType>;
using TetrahedronType = itk::TetrahedronCell<CellType>;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Then, custom CellVisitor classes should be declared. The only requirement
// on the declaration of each visitor class is to provide a method named
// \code{Visit()}. This method expects as arguments a cell identifier and a
// pointer to the \emph{specific} cell type for which this visitor is
// intended.
//
// \index{itk::Mesh!CellInterfaceVisitor}
// \index{CellInterfaceVisitor!requirements}
// \index{CellInterfaceVisitor!Visit()}
//
// Software Guide : EndLatex
// Software Guide : BeginLatex
//
// The following Vertex visitor simply prints out the identifier of the
// point with which the cell is associated. Note that the cell uses the
// method \code{GetPointId()} without any arguments. This method is only
// defined on the VertexCell.
//
// \index{itk::CellInterface!GetPointId()}
// \index{GetPointId()}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
class CustomVertexVisitor
{
public:
void
Visit(unsigned long cellId, VertexType * t)
{
std::cout << "cell " << cellId << " is a Vertex " << std::endl;
std::cout << " associated with point id = ";
std::cout << t->GetPointId() << std::endl;
}
virtual ~CustomVertexVisitor() = default;
};
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The following Line visitor computes the length of the line. Note
// that this visitor is slightly more complicated since it needs to get
// access to the actual mesh in order to get point coordinates from the
// point identifiers returned by the line cell. This is done by holding a
// pointer to the mesh and querying the mesh each time point coordinates are
// required. The mesh pointer is set up in this case with the
// \code{SetMesh()} method.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
class CustomLineVisitor
{
public:
CustomLineVisitor()
: m_Mesh(nullptr)
{}
virtual ~CustomLineVisitor() = default;
void
SetMesh(MeshType * mesh)
{
m_Mesh = mesh;
}
void
Visit(unsigned long cellId, LineType * t)
{
std::cout << "cell " << cellId << " is a Line " << std::endl;
LineType::PointIdIterator pit = t->PointIdsBegin();
m_Mesh->GetPoint(*pit++, &p0);
m_Mesh->GetPoint(*pit++, &p1);
const double length = p0.EuclideanDistanceTo(p1);
std::cout << " length = " << length << std::endl;
}
private:
};
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The Triangle visitor below prints out the identifiers of its points.
// Note the use of the \code{PointIdIterator} and the \code{PointIdsBegin()}
// and \code{PointIdsEnd()} methods.
//
// \index{CellInterface!PointIdsBegin()}
// \index{CellInterface!PointIdsEnd()}
// \index{CellInterface!iterating points}
// \index{PointIdsBegin()}
// \index{PointIdsEnd()}
//
// Software Guide : EndLatex
#ifndef CustomTriangleVisitorDefine
# define CustomTriangleVisitorDefine
// Software Guide : BeginCodeSnippet
class CustomTriangleVisitor
{
public:
void
Visit(unsigned long cellId, TriangleType * t)
{
std::cout << "cell " << cellId << " is a Triangle " << std::endl;
LineType::PointIdIterator pit = t->PointIdsBegin();
LineType::PointIdIterator end = t->PointIdsEnd();
while (pit != end)
{
std::cout << " point id = " << *pit << std::endl;
++pit;
}
}
virtual ~CustomTriangleVisitor() = default;
};
// Software Guide : EndCodeSnippet
#endif
// Software Guide : BeginLatex
//
// The TetrahedronVisitor below simply returns the number of faces on this
// figure. Note that \code{GetNumberOfFaces()} is a method exclusive of 3D
// cells.
//
// \index{GetNumberOfFaces()!TetrahedronCell}
// \index{TetrahedronCell!GetNumberOfFaces()}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
class CustomTetrahedronVisitor
{
public:
void
Visit(unsigned long cellId, TetrahedronType * t)
{
std::cout << "cell " << cellId << " is a Tetrahedron " << std::endl;
std::cout << " number of faces = ";
std::cout << t->GetNumberOfFaces() << std::endl;
}
virtual ~CustomTetrahedronVisitor() = default;
};
// Software Guide : EndCodeSnippet
int
main(int, char *[])
{
auto mesh = MeshType::New();
// Creating the points and inserting them in the mesh
//
point0[0] = -1;
point0[1] = -1;
point0[2] = -1;
point1[0] = 1;
point1[1] = 1;
point1[2] = -1;
point2[0] = 1;
point2[1] = -1;
point2[2] = 1;
point3[0] = -1;
point3[1] = 1;
point3[2] = 1;
mesh->SetPoint(0, point0);
mesh->SetPoint(1, point1);
mesh->SetPoint(2, point2);
mesh->SetPoint(3, point3);
// Creating and associating the Tetrahedron
//
CellType::CellAutoPointer cellpointer;
cellpointer.TakeOwnership(new TetrahedronType);
cellpointer->SetPointId(0, 0);
cellpointer->SetPointId(1, 1);
cellpointer->SetPointId(2, 2);
cellpointer->SetPointId(3, 3);
mesh->SetCell(0, cellpointer);
// Creating and associating the Triangles
//
cellpointer.TakeOwnership(new TriangleType);
cellpointer->SetPointId(0, 0);
cellpointer->SetPointId(1, 1);
cellpointer->SetPointId(2, 2);
mesh->SetCell(1, cellpointer);
cellpointer.TakeOwnership(new TriangleType);
cellpointer->SetPointId(0, 0);
cellpointer->SetPointId(1, 2);
cellpointer->SetPointId(2, 3);
mesh->SetCell(2, cellpointer);
cellpointer.TakeOwnership(new TriangleType);
cellpointer->SetPointId(0, 0);
cellpointer->SetPointId(1, 3);
cellpointer->SetPointId(2, 1);
mesh->SetCell(3, cellpointer);
cellpointer.TakeOwnership(new TriangleType);
cellpointer->SetPointId(0, 3);
cellpointer->SetPointId(1, 2);
cellpointer->SetPointId(2, 1);
mesh->SetCell(4, cellpointer);
// Creating and associating the Edges
//
cellpointer.TakeOwnership(new LineType);
cellpointer->SetPointId(0, 0);
cellpointer->SetPointId(1, 1);
mesh->SetCell(5, cellpointer);
cellpointer.TakeOwnership(new LineType);
cellpointer->SetPointId(0, 1);
cellpointer->SetPointId(1, 2);
mesh->SetCell(6, cellpointer);
cellpointer.TakeOwnership(new LineType);
cellpointer->SetPointId(0, 2);
cellpointer->SetPointId(1, 0);
mesh->SetCell(7, cellpointer);
cellpointer.TakeOwnership(new LineType);
cellpointer->SetPointId(0, 1);
cellpointer->SetPointId(1, 3);
mesh->SetCell(8, cellpointer);
cellpointer.TakeOwnership(new LineType);
cellpointer->SetPointId(0, 3);
cellpointer->SetPointId(1, 2);
mesh->SetCell(9, cellpointer);
cellpointer.TakeOwnership(new LineType);
cellpointer->SetPointId(0, 3);
cellpointer->SetPointId(1, 0);
mesh->SetCell(10, cellpointer);
// Creating and associating the Vertices
//
cellpointer.TakeOwnership(new VertexType);
cellpointer->SetPointId(0, 0);
mesh->SetCell(11, cellpointer);
cellpointer.TakeOwnership(new VertexType);
cellpointer->SetPointId(0, 1);
mesh->SetCell(12, cellpointer);
cellpointer.TakeOwnership(new VertexType);
cellpointer->SetPointId(0, 2);
mesh->SetCell(13, cellpointer);
cellpointer.TakeOwnership(new VertexType);
cellpointer->SetPointId(0, 3);
mesh->SetCell(14, cellpointer);
// Simple verification of the number of points and cells inserted
//
std::cout << "# Points= " << mesh->GetNumberOfPoints() << std::endl;
std::cout << "# Cell = " << mesh->GetNumberOfCells() << std::endl;
// Software Guide : BeginLatex
//
// \index{itk::Mesh!Cell\-Interface\-Visitor\-Implementation}
// \index{itk::Mesh!CellInterfaceVisitor}
// \index{itk::Mesh!CellVisitor}
// \index{CellVisitor}
//
// With the cell visitors we proceed now to instantiate CellVisitor
// implementations. The visitor classes defined above are used as template
// arguments of the cell visitor implementation.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
using VertexVisitorInterfaceType =
MeshType::CellTraits,
VertexType,
CustomVertexVisitor>;
using LineVisitorInterfaceType =
MeshType::CellTraits,
LineType,
CustomLineVisitor>;
using TriangleVisitorInterfaceType =
MeshType::CellTraits,
TriangleType,
CustomTriangleVisitor>;
using TetrahedronVisitorInterfaceType =
MeshType::CellTraits,
TetrahedronType,
CustomTetrahedronVisitor>;
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Note that the actual \code{CellInterfaceVisitorImplementation} is
// templated over the PixelType, the CellTraits, the CellType to be visited
// and the Visitor class defining what to do with the cell.
//
// A visitor implementation class can now be created using the normal
// invocation to its \code{New()} method and assigning the result to a
// \doxygen{SmartPointer}.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
auto vertexVisitor = VertexVisitorInterfaceType::New();
auto lineVisitor = LineVisitorInterfaceType::New();
auto triangleVisitor = TriangleVisitorInterfaceType::New();
auto tetrahedronVisitor = TetrahedronVisitorInterfaceType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Remember that the LineVisitor requires the pointer to the mesh object
// since it needs to get access to actual point coordinates. This is done
// by invoking the \code{SetMesh()} method defined above.
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
lineVisitor->SetMesh(mesh);
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Looking carefully you will notice that the \code{SetMesh()} method is
// declared in \code{CustomLineVisitor} but we are invoking it on
// \code{LineVisitorInterfaceType}. This is possible thanks to the way in
// which the VisitorInterfaceImplementation is defined. This class derives
// from the visitor type provided by the user as the fourth template
// parameter. \code{LineVisitorInterfaceType} is then a derived class of
// \code{CustomLineVisitor}.
//
// Software Guide : EndLatex
// Software Guide : BeginLatex
//
// The set of visitors should now be registered with the MultiVisitor class
// that will walk through the cells and delegate action to every registered
// visitor when the appropriate cell type is encountered. The following
// lines create a MultiVisitor object.
//
// \index{CellMultiVisitorType}
// \index{MultiVisitor}
// \index{itk::Mesh!MultiVisitor}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
using CellMultiVisitorType = CellType::MultiVisitor;
auto multiVisitor = CellMultiVisitorType::New();
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Every visitor implementation is registered with the Mesh using the
// \code{AddVisitor()} method.
//
// \index{itk::Mesh!AddVisitor()}
// \index{AddVisitor()!itk::Mesh}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
multiVisitor->AddVisitor(vertexVisitor);
multiVisitor->AddVisitor(lineVisitor);
multiVisitor->AddVisitor(triangleVisitor);
multiVisitor->AddVisitor(tetrahedronVisitor);
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// Finally, the iteration over the cells is triggered by calling the method
// \code{Accept()} on the Mesh class.
//
// \index{itk::Mesh!Accept()}
// \index{Accept()!itk::Mesh!}
//
// Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
mesh->Accept(multiVisitor);
// Software Guide : EndCodeSnippet
// Software Guide : BeginLatex
//
// The \code{Accept()} method will iterate over all the cells and for each
// one will invite the MultiVisitor to attempt an action on the cell. If no
// visitor is interested on the current cell type, the cell is just ignored
// and skipped.
//
// Software Guide : EndLatex
return EXIT_SUCCESS;
}
Pointer
SmartPointer< Self > Pointer
Definition: itkAddImageFilter.h:93
itk::VertexCell
Represents a single vertex for a Mesh.
Definition: itkVertexCell.h:42
itk::GTest::TypedefsAndConstructors::Dimension2::PointType
ImageBaseType::PointType PointType
Definition: itkGTestTypedefsAndConstructors.h:51
itkLineCell.h
itk::TetrahedronCell
TetrahedronCell represents a tetrahedron for a Mesh.
Definition: itkTetrahedronCell.h:40
itk::CellInterfaceVisitorImplementation
A template class used to implement a visitor object.
Definition: itkCellInterfaceVisitor.h:100
itkMesh.h
itk::TriangleCell
Definition: itkTriangleCell.h:46
itk::Point::EuclideanDistanceTo
RealType EuclideanDistanceTo(const Point< TCoordRepB, VPointDimension > &pa) const
Definition: itkPoint.h:298
itk::LineCell
Represents a line segment for a Mesh.
Definition: itkLineCell.h:45
itk::Mesh
Implements the N-dimensional mesh structure.
Definition: itkMesh.h:126
New
static Pointer New()
itkCellInterfaceVisitor.h
itkTetrahedronCell.h