/*=========================================================================
 *
 *  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 \doxygen{PointSet} class uses an internal container to manage the
//  storage of \doxygen{Point}s. It is more efficient, in general, to manage
//  points by using the access methods provided directly on the points
//  container. The following example illustrates how to interact with the
//  point container and how to use point iterators.
//
//  Software Guide : EndLatex


#include "itkPointSet.h"

int
main(int, char *[])
{
  using PointSetType = itk::PointSet<unsigned short, 3>;

  //  Software Guide : BeginLatex
  //
  //  The type is defined by the \emph{traits} of the \code{PointSet}
  //  class. The following line conveniently takes the \code{PointsContainer}
  //  type from the \code{PointSet} traits and declares it in the global
  //  namespace.
  //
  //  \index{itk::PointSet!PointsContainer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  using PointsContainer = PointSetType::PointsContainer;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The actual type of \code{PointsContainer} depends on what style of
  //  \code{PointSet} is being used. The dynamic \code{PointSet} uses
  //  \doxygen{MapContainer} while the static \code{PointSet} uses
  //  \doxygen{VectorContainer}. The vector and map containers are basically
  //  ITK wrappers around the \href{https://www.sgi.com/tech/stl/}{STL}
  //  classes \href{https://www.sgi.com/tech/stl/Map.html}{\code{std::map}}
  //  and \href{https://www.sgi.com/tech/stl/Vector.html}{\code{std::vector}}.
  //  By default, \code{PointSet} uses a static style, and therefore the
  //  default type of point container is \code{VectorContainer}.  Both map and
  //  vector containers are templated over the type of element they contain.
  //  In this case they are templated over \code{PointType}. Containers are
  //  reference counted objects, created with the \code{New()} method and
  //  assigned to a \doxygen{SmartPointer}. The following line creates a point
  //  container compatible with the type of the \code{PointSet} from which the
  //  trait has been taken.
  //
  //  \index{PointsContainer!New()}
  //  \index{PointsContainer!Pointer}
  //
  //  Software Guide : EndLatex


  // Software Guide : BeginCodeSnippet
  auto points = PointsContainer::New();
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  \code{Point}s can now be defined using the \code{PointType} trait from
  //  the \code{PointSet}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  using PointType = PointSetType::PointType;
  PointType p0;
  PointType p1;
  p0[0] = -1.0;
  p0[1] = 0.0;
  p0[2] = 0.0; // Point 0 = {-1,0,0 }
  p1[0] = 1.0;
  p1[1] = 0.0;
  p1[2] = 0.0; // Point 1 = { 1,0,0 }
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  The created points can be inserted in the \code{PointsContainer} using
  //  the generic method \code{InsertElement()} which requires an identifier
  //  to be provided for each point.
  //
  //  \index{PointsContainer!InsertElement()}
  //  \index{PointsContainer!InsertElement()}
  //  \index{itk::VectorContainer!InsertElement()}
  //  \index{itk::MapContainer!InsertElement()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  unsigned int pointId = 0;
  points->InsertElement(pointId++, p0);
  points->InsertElement(pointId++, p1);
  // Software Guide : EndCodeSnippet

  auto pointSet = PointSetType::New();

  //  Software Guide : BeginLatex
  //
  //  Finally, the \code{PointsContainer} can be assigned to the
  //  \code{PointSet}. This will substitute any previously existing
  //  \code{PointsContainer} assigned to the \code{PointSet}. The assignment
  //  is done using the \code{SetPoints()} method.
  //
  //  \index{itk::PointSet!SetPoints()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  pointSet->SetPoints(points);
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  The \code{PointsContainer} object can be obtained from the
  //  \code{PointSet} using the \code{GetPoints()} method.  This method
  //  returns a pointer to the actual container owned by the PointSet which is
  //  then assigned to a \code{SmartPointer}.
  //
  //  \index{itk::PointSet!GetPoints()}
  //  \index{PointsContainer!Pointer}
  //
  //  Software Guide : EndLatex


  // Software Guide : BeginCodeSnippet
  PointsContainer::Pointer points2 = pointSet->GetPoints();
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  The most efficient way to sequentially visit the points is to use the
  //  iterators provided by PointsContainer. The \code{Iterator} type belongs
  //  to the traits of the PointsContainer classes. It behaves pretty much
  //  like the STL iterators.\footnote{If you dig deep enough into the code,
  //  you will discover that these iterators are actually ITK wrappers around
  //  STL iterators.}  The Points iterator is not a reference counted class,
  //  so it is created directly from the traits without using SmartPointers.
  //
  //  \index{PointsContainer!Iterator}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  using PointsIterator = PointsContainer::Iterator;
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  The subsequent use of the iterator follows what you may expect from a
  //  STL iterator. The iterator to the first point is obtained from the
  //  container with the \code{Begin()} method and assigned to another
  //  iterator.
  //
  //  \index{PointsContainer!Begin()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  PointsIterator pointIterator = points->Begin();
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  The \code{++} operator on the iterator can be used to advance from one
  //  point to the next. The actual value of the Point to which the iterator
  //  is pointing can be obtained with the \code{Value()} method. The loop for
  //  walking through all the points can be controlled by comparing the
  //  current iterator with the iterator returned by the \code{End()} method
  //  of the PointsContainer. The following lines illustrate the typical loop
  //  for walking through the points.
  //
  //  \index{PointsContainer!End()}
  //  \index{PointsContainer!Iterator}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  PointsIterator end = points->End();
  while (pointIterator != end)
  {
    PointType p = pointIterator.Value(); // access the point
    std::cout << p << std::endl;         // print the point
    ++pointIterator;                     // advance to next point
  }
  // Software Guide : EndCodeSnippet


  //  Software Guide : BeginLatex
  //
  //  Note that as in STL, the iterator returned by the \code{End()} method is
  //  not a valid iterator. This is called a past-end iterator in order to
  //  indicate that it is the value resulting from advancing one step after
  //  visiting the last element in the container.
  //
  //  The number of elements stored in a container can be queried with the
  //  \code{Size()} method. In the case of the PointSet, the following two
  //  lines of code are equivalent, both of them returning the number of
  //  points in the PointSet.
  //
  //  \index{itk::PointSet!GetNumberOfPoints()}
  //  \index{itk::PointSet!GetPoints()}
  //  \index{PointsContainer!Size()}
  //
  //  Software Guide : EndLatex


  // Software Guide : BeginCodeSnippet
  std::cout << pointSet->GetNumberOfPoints() << std::endl;
  std::cout << pointSet->GetPoints()->Size() << std::endl;
  // Software Guide : EndCodeSnippet

  return EXIT_SUCCESS;
}
