/*========================================================================= * * 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 was designed to interact with the // \code{Image} class. For this reason it was found convenient to allow the // points in the set to hold values that could be computed from images. The // value associated with the point is referred as \code{PixelType} in order // to make it consistent with image terminology. Users can define the type as // they please thanks to the flexibility offered by the Generic Programming // approach used in the toolkit. The \code{PixelType} is the first template // parameter of the PointSet. // // \index{itk::PointSet!PixelType} // // Software Guide : EndLatex #include "itkPointSet.h" int main(int, char *[]) { // Software Guide : BeginLatex // // The following code defines a particular type for a pixel type and // instantiates a PointSet class with it. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet using PixelType = unsigned short; using PointSetType = itk::PointSet; // Software Guide : EndCodeSnippet // A point set is instantiated here auto pointSet = PointSetType::New(); // Software Guide : BeginLatex // // Data can be inserted into the PointSet using the \code{SetPointData()} // method. This method requires the user to provide an identifier. The data // in question will be associated to the point holding the same identifier. // It is the user's responsibility to verify the appropriate matching // between inserted data and inserted points. The following line // illustrates the use of the \code{SetPointData()} method. // // \index{itk::PointSet!SetPointData()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet unsigned int dataId = 0; PixelType value = 79; pointSet->SetPointData(dataId++, value); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Data associated with points can be read from the PointSet using the // \code{GetPointData()} method. This method requires the user to provide // the identifier to the point and a valid pointer to a location where the // pixel data can be safely written. In case the identifier does not match // any existing identifier on the PointSet the method will return // \code{false} and the pixel value returned will be invalid. It is the // user's responsibility to check the returned boolean value before // attempting to use it. // // \index{itk::PointSet!GetPointData()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet const bool found = pointSet->GetPointData(dataId, &value); if (found) { std::cout << "Pixel value = " << value << std::endl; } // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The \code{SetPointData()} and \code{GetPointData()} methods are not the // most efficient way to get access to point data. It is far more efficient // to use the Iterators provided by the \code{PointDataContainer}. // // Data associated with points is internally stored in // \code{PointDataContainer}s. In the same way as with points, the actual // container type used depend on whether the style of the PointSet is // static or dynamic. Static point sets will use an // \doxygen{VectorContainer} while dynamic point sets will use an // \doxygen{MapContainer}. The type of the data container is defined as // one of the traits in the PointSet. The following declaration illustrates // how the type can be taken from the traits and used to conveniently // declare a similar type on the global namespace. // // \index{itk::PointSet!PointDataContainer} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet using PointDataContainer = PointSetType::PointDataContainer; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Using the type it is now possible to create an instance of the data // container. This is a standard reference counted object, henceforth it // uses the \code{New()} method for creation and assigns the newly created // object to a SmartPointer. // // \index{PointDataContainer!New()} // \index{PointDataContainer!Pointer} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet auto pointData = PointDataContainer::New(); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Pixel data can be inserted in the container with the method // \code{InsertElement()}. This method requires an identified to be // provided for each point data. // // \index{PointDataContainer!InsertElement()} // \index{itk::VectorContainer!InsertElement()} // \index{itk::MapContainer!InsertElement()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet unsigned int pointId = 0; PixelType value0 = 34; PixelType value1 = 67; pointData->InsertElement(pointId++, value0); pointData->InsertElement(pointId++, value1); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Finally the PointDataContainer can be assigned to the PointSet. This // will substitute any previously existing PointDataContainer on the // PointSet. The assignment is done using the \code{SetPointData()} method. // // \index{itk::PointSet!SetPointData()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet pointSet->SetPointData(pointData); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The PointDataContainer can be obtained from the PointSet using the // \code{GetPointData()} method. This method returns a pointer (assigned // to a SmartPointer) to the actual container owned by the PointSet. // // \index{itk::PointSet!GetPointData()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet PointDataContainer::Pointer pointData2 = pointSet->GetPointData(); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The most efficient way to sequentially visit the data associated with // points is to use the iterators provided by \code{PointDataContainer}. // The \code{Iterator} type belongs to the traits of the PointsContainer // classes. The iterator is not a reference counted class, so it is just // created directly from the traits without using SmartPointers. // // \index{PointDataContainer!Iterator} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet using PointDataIterator = PointDataContainer::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{PointDataContainer!Begin()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet PointDataIterator pointDataIterator = pointData2->Begin(); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The \code{++} operator on the iterator can be used to advance from one // data point to the next. The actual value of the PixelType to which the // iterator is pointing can be obtained with the \code{Value()} // method. The loop for walking through all the point data 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 point data. // // \index{PointDataContainer!End()} // \index{PointDataContainer!increment ++} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet PointDataIterator end = pointData2->End(); while (pointDataIterator != end) { PixelType p = pointDataIterator.Value(); // access the pixel data std::cout << p << std::endl; // print the pixel data ++pointDataIterator; // advance to next pixel/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 \emph{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. // // Software Guide : EndLatex return EXIT_SUCCESS; }