Update branch from master after trailing whitespaces and tabs removal

This commit is contained in:
Sébastien Loriot 2020-03-26 19:38:52 +01:00
commit cf9629fc4b
5 changed files with 143 additions and 8 deletions

View File

@ -3,4 +3,4 @@
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - CGAL and Boost Property Maps" PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - CGAL and Boost Property Maps"
INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/property_map.h INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/property_map.h
EXCLUDE += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Dynamic_property_map.h EXCLUDE += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Dynamic_property_map.h
EXAMPLE_PATH = ${CGAL_Point_set_processing_3_EXAMPLE_DIR} EXAMPLE_PATH += ${CGAL_Point_set_processing_3_EXAMPLE_DIR}

View File

@ -1,11 +1,13 @@
namespace CGAL { namespace CGAL {
/*! /*!
\mainpage User Manual \mainpage User Manual
\anchor Chapter_CGAL_and_Boost_Property_Maps \anchor Chapter_CGAL_and_Boost_Property_Maps
\anchor chapterProperty_map \anchor chapterProperty_map
\cgalAutoToc
\authors Andreas Fabri and Laurent Saboret \authors Andreas Fabri and Laurent Saboret
\section Property_mapA A Short Introduction to the Boost Property Maps Library \section Property_mapA A Short Introduction to the Boost Property Maps Library
@ -25,15 +27,15 @@ Property maps in the Boost manuals: <A HREF="https://www.boost.org/libs/property
Some algorithms in \cgal take as input parameters iterator ranges and property maps to access information attached to elements of the sequence. Some algorithms in \cgal take as input parameters iterator ranges and property maps to access information attached to elements of the sequence.
For example, the algorithms of chapters \ref Chapter_Point_Set_Processing "Point Set Processing" and For example, the algorithms of chapters \ref Chapter_Point_Set_Processing "Point Set Processing" and
\ref Chapter_Poisson_Surface_Reconstruction "Poisson Surface Reconstruction" \ref Chapter_Poisson_Surface_Reconstruction "Poisson Surface Reconstruction"
take as input parameters iterator ranges and property take as input parameters iterator ranges and property
maps to access each point's position and normal. Position and normal maps to access each point's position and normal. Position and normal
might be represented in various ways, e.g., as a class derived from might be represented in various ways, e.g., as a class derived from
the \cgal point class, or as a `std::pair<Point_3<K>, Vector_3<K> >`, the \cgal point class, or as a `std::pair<Point_3<K>, Vector_3<K> >`,
or as a `boost::tuple<..,Point_3<K>, ..., Vector_3<K> >`. or as a `boost::tuple<..,Point_3<K>, ..., Vector_3<K> >`.
This component provides property maps to support these cases: This component provides property maps to support these cases:
- `Identity_property_map<T>` - `Identity_property_map<T>`
- `First_of_pair_property_map<Pair>` and `Second_of_pair_property_map<Pair>` - `First_of_pair_property_map<Pair>` and `Second_of_pair_property_map<Pair>`
@ -55,6 +57,20 @@ The following example reads a point set from an input file and writes it to a fi
The following example reads a point set in the `xyz` format and computes the average spacing. %Index, position and color are stored in a tuple and accessed through property maps. The following example reads a point set in the `xyz` format and computes the average spacing. %Index, position and color are stored in a tuple and accessed through property maps.
\cgalExample{Point_set_processing_3/average_spacing_example.cpp} \cgalExample{Point_set_processing_3/average_spacing_example.cpp}
*/ \section Property_mapCustom Writing Custom Property Maps
Property maps are especially useful when using predefined data
structures that are not part of the \cgal library: algorithms written
with property maps can be called on these data structures provided the
user writes the required property maps, without the need to create
deep copies of potentially large data into \cgal formats.
The following example shows how to write a readable point map and a
read-write normal map to run \cgal normal estimation and orientation
algorithm on raw `double` arrays:
\cgalExample{Property_map/custom_property_map.cpp}
*/
} /* namespace CGAL */ } /* namespace CGAL */

View File

@ -2,4 +2,5 @@
\example Point_set_processing_3/remove_outliers_example.cpp \example Point_set_processing_3/remove_outliers_example.cpp
\example Point_set_processing_3/read_write_xyz_point_set_example.cpp \example Point_set_processing_3/read_write_xyz_point_set_example.cpp
\example Point_set_processing_3/average_spacing_example.cpp \example Point_set_processing_3/average_spacing_example.cpp
\example Property_map/custom_property_map.cpp
*/ */

View File

@ -9,7 +9,7 @@ find_package( CGAL QUIET COMPONENTS )
if ( NOT CGAL_FOUND ) if ( NOT CGAL_FOUND )
message(STATUS "This project requires the CGAL library, and will not be compiled.") message(STATUS "This project requires the CGAL library, and will not be compiled.")
return() return()
endif() endif()
@ -20,7 +20,7 @@ if ( NOT Boost_FOUND )
message(STATUS "This project requires the Boost library, and will not be compiled.") message(STATUS "This project requires the Boost library, and will not be compiled.")
return() return()
endif() endif()
@ -32,4 +32,10 @@ endif()
create_single_source_cgal_program( "dynamic_properties.cpp" ) create_single_source_cgal_program( "dynamic_properties.cpp" )
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
if (EIGEN3_FOUND)
create_single_source_cgal_program( "custom_property_map.cpp" )
CGAL_target_use_Eigen(custom_property_map)
endif()

View File

@ -0,0 +1,112 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/jet_estimate_normals.h>
#include <CGAL/mst_orient_normals.h>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = Kernel::Point_3;
using Vector_3 = Kernel::Vector_3;
using Generator = CGAL::Random_points_on_sphere_3<Point_3>;
// Example of readable property map to get CGAL::Point_3 objects from
// 3 coordinate arrays
struct Custom_point_map
{
using key_type = std::size_t; // The iterator's value type is an index
using value_type = Point_3; // The object manipulated by the algorithm is a Point_3
using reference = Point_3; // The object does not exist in memory, so there's no reference
using category = boost::readable_property_map_tag; // The property map is only used for reading
double *x, *y, *z;
Custom_point_map (double* x = nullptr, double* y = nullptr, double* z = nullptr)
: x(x), y(y), z(z) { }
// The get() function returns the object expected by the algorithm (here, Point_3)
friend Point_3 get (const Custom_point_map& map, std::size_t idx)
{
return Point_3 (map.x[idx], map.y[idx], map.z[idx]);
}
};
// Example of read-write property map to get CGAL::Vector_3 objects from
// a buffer array and put CGAL::Vector_3 values in this buffer
struct Custom_normal_map
{
using key_type = std::size_t; // The iterator's value type is an index
using value_type = Vector_3; // The object manipulated by the algorithm is a Vector_3
using reference = Vector_3; // The object does not exist in memory, so there's no reference
using category = boost::read_write_property_map_tag; // The property map is used both
// for reading and writing data
double *buffer;
Custom_normal_map (double* buffer = nullptr)
: buffer (buffer) { }
// The get() function returns the object expected by the algorithm (here, Vector_3)
friend Vector_3 get (const Custom_normal_map& map, std::size_t idx)
{
return Vector_3 (map.buffer[idx * 3 ],
map.buffer[idx * 3 + 1],
map.buffer[idx * 3 + 2]);
}
// The put() function updated the user's data structure from the
// object handled by the algorithm (here Vector_3)
friend void put (const Custom_normal_map& map, std::size_t idx, const Vector_3& vector_3)
{
map.buffer[idx * 3 ] = vector_3.x();
map.buffer[idx * 3 + 1] = vector_3.y();
map.buffer[idx * 3 + 2] = vector_3.z();
}
};
int main()
{
constexpr std::size_t nb_points = 1000;
// in this example, points are stored as separate coordinate arrays
double x[nb_points];
double y[nb_points];
double z[nb_points];
// generate random points
Generator generator;
for (std::size_t i = 0; i < nb_points; ++ i)
{
Point_3 p = *(generator ++ );
x[i] = p.x();
y[i] = p.y();
z[i] = p.z();
}
// normals are stored as a contiguous double array
double normals[3 *nb_points];
// we use a vector of indices to access arrays
std::vector<std::size_t> indices;
indices.reserve (nb_points);
for (std::size_t i = 0; i < nb_points; ++ i)
indices.push_back(i);
// estimate and orient normals using directly user's data structure
// instead of creating deep copies using Point_3 and Vector_3
CGAL::jet_estimate_normals<CGAL::Sequential_tag>
(indices, 12,
CGAL::parameters::point_map (Custom_point_map(x,y,z)).
normal_map (Custom_normal_map(normals)));
CGAL::mst_orient_normals
(indices, 12,
CGAL::parameters::point_map (Custom_point_map(x,y,z)).
normal_map (Custom_normal_map(normals)));
// Display first 10 points+normals
for (std::size_t i = 0; i < 10; ++ i)
std::cerr << "Point(" << i << ") = " << x[i] << " " << y[i] << " " << z[i]
<< "\tNormal(" << i << ") = "
<< normals[3*i] << " " << normals[3*i+1] << " " << normals[3*i+2] << std::endl;
return EXIT_SUCCESS;
}