// Copyright (c) 2015 Geometry Factory // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Point_set_processing_3/include/CGAL/IO/read_ply_points.h $ // $Id: read_ply_points.h c253679 2020-04-18T16:27:58+02:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Simon Giraudot #ifndef CGAL_READ_PLY_POINTS_H #define CGAL_READ_PLY_POINTS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { #ifdef DOXYGEN_RUNNING // Document some parts from Stream_support here for convenience /** \ingroup PkgPointSetProcessing3IOPly Class used to identify a %PLY property as a type and a name. \sa `read_ply_points_with_properties()` */ template struct PLY_property { typedef T type; const char* name; PLY_property (const char* name) : name (name) { } }; /** \ingroup PkgPointSetProcessing3IOPly Generates a %PLY property handler to read 3D points. Points are constructed from the input using 3 %PLY properties of type `FT` and named `x`, `y` and `z`. `FT` is `float` if the points use `CGAL::Simple_cartesian` and `double` otherwise. \sa `read_ply_points_with_properties()` \tparam PointMap the property map used to store points. */ template std::tuple::Kernel::Construct_point_3, PLY_property, PLY_property, PLY_property > make_ply_point_reader(PointMap point_map); /** \ingroup PkgPointSetProcessing3IOPly Generates a %PLY property handler to read 3D normal vectors. Vectors are constructed from the input using 3 PLY properties of type `FT` and named `nx`, `ny` and `nz`. `FT` is `float` if the points use `CGAL::Simple_cartesian` and `double` otherwise. \sa `read_ply_points_with_properties()` \tparam VectorMap the property map used to store vectors. */ template std::tuple::Kernel::Construct_vector_3, PLY_property, PLY_property, PLY_property > make_ply_normal_reader(VectorMap normal_map); #endif // DOXYGEN_RUNNING /** \ingroup PkgPointSetProcessingIOPly Reads user-selected points properties from a .ply stream (ASCII or binary). Potential additional point properties and faces are ignored. Properties are handled through a variadic list of property handlers. A `PropertyHandler` can either be: - A `std::pair >` if the user wants to read a %PLY property as a scalar value T (for example, storing an `int` %PLY property into an `int` variable). - A `std::tuple...>` if the user wants to use one or several PLY properties to construct a complex object (for example, storing 3 `uchar` %PLY properties into a %Color object that can for example be a `std::array`). In that case, the second element of the tuple should be a functor that constructs the value type of `PropertyMap` from N objects of types `T`. \sa `make_ply_point_reader()` \sa `make_ply_normal_reader()` \cgalRequiresCPP11 \tparam OutputIteratorValueType type of objects that can be put in `OutputIterator`. It is default to `value_type_traits::%type` and can be omitted when the default is fine. \tparam OutputIterator iterator over output points. \tparam PropertyHandler handlers to recover properties. \return `true` on success. */ template bool read_ply_points_with_properties (std::istream& stream, OutputIterator output, PropertyHandler&& ... properties) { typedef typename value_type_traits::type OutputValueType; if(!stream) { std::cerr << "Error: cannot open file" << std::endl; return false; } internal::PLY::PLY_reader reader; if (!(reader.init (stream))) { stream.setstate(std::ios::failbit); return false; } for (std::size_t i = 0; i < reader.number_of_elements(); ++ i) { internal::PLY::PLY_element& element = reader.element(i); for (std::size_t j = 0; j < element.number_of_items(); ++ j) { for (std::size_t k = 0; k < element.number_of_properties(); ++ k) { internal::PLY::PLY_read_number* property = element.property(k); property->get (stream); if (stream.fail()) return false; } if (element.name() == "vertex" || element.name() == "vertices") { OutputValueType new_element; internal::PLY::process_properties (element, new_element, std::forward(properties)...); *(output ++) = new_element; } } } return true; } /// \cond SKIP_IN_MANUAL template bool read_ply_points_with_properties (std::istream& stream, OutputIterator output, PropertyHandler&& ... properties) { typedef typename value_type_traits::type OutputValueType; return read_ply_points_with_properties (stream, output, std::forward(properties)...); } /// \endcond /** \ingroup PkgPointSetProcessing3IOPly Reads points (positions + normals, if available) from a .ply stream (ASCII or binary). Potential additional point properties and faces are ignored. \tparam OutputIteratorValueType type of objects that can be put in `OutputIterator`. It is default to `value_type_traits::%type` and can be omitted when the default is fine. \tparam OutputIterator iterator over output points. \param stream input stream. \param output output iterator over points. \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below \cgalNamedParamsBegin \cgalParamNBegin{point_map} \cgalParamDescription{a property map associating points to the elements of the point range} \cgalParamType{a model of `WritablePropertyMap` with value type `geom_traits::Point_3`} \cgalParamDefault{`CGAL::Identity_property_map`} \cgalParamNEnd \cgalParamNBegin{normal_map} \cgalParamDescription{a property map associating normals to the elements of the poing range} \cgalParamType{a model of `ReadWritePropertyMap` with value type `geom_traits::Vector_3`} \cgalParamDefault{If this parameter is omitted, normals in the input stream are ignored.} \cgalParamNEnd \cgalParamNBegin{geom_traits} \cgalParamDescription{an instance of a geometric traits class} \cgalParamType{a model of `Kernel`} \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} \cgalParamNEnd \cgalNamedParamsEnd \return true on success. \cgalRequiresCPP11 */ template < typename OutputIteratorValueType, typename OutputIterator, #ifdef DOXYGEN_RUNNING typename NamedParameters #else typename CGAL_BGL_NP_TEMPLATE_PARAMETERS #endif > bool read_ply_points(std::istream& stream, OutputIterator output, #ifdef DOXYGEN_RUNNING const NamedParameters& np) #else const CGAL_BGL_NP_CLASS& np) #endif { using parameters::choose_parameter; using parameters::get_parameter; typedef Point_set_processing_3::Fake_point_range PointRange; // basic geometric types typedef typename CGAL::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetNormalMap::type NormalMap; bool has_normals = !(boost::is_same::NoMap>::value); PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map)); NormalMap normal_map = choose_parameter(get_parameter(np, internal_np::normal_map)); if (has_normals) return read_ply_points_with_properties (stream, output, make_ply_point_reader (point_map), make_ply_normal_reader (normal_map)); // else return read_ply_points_with_properties (stream, output, make_ply_point_reader (point_map)); } /// \cond SKIP_IN_MANUAL // variant with default NP template bool read_ply_points( std::istream& stream, ///< input stream. OutputIterator output) ///< output iterator over points. { return read_ply_points (stream, output, CGAL::parameters::all_default()); } // variant with default output iterator value type template bool read_ply_points( std::istream& stream, ///< input stream. OutputIterator output, const CGAL_BGL_NP_CLASS& np) { return read_ply_points::type> (stream, output, np); } // variant with default NP and output iterator value type template bool read_ply_points( std::istream& stream, ///< input stream. OutputIterator output) { return read_ply_points::type> (stream, output, CGAL::parameters::all_default()); } #ifndef CGAL_NO_DEPRECATED_CODE // deprecated API template < typename OutputIteratorValueType, typename OutputIterator, typename PointMap, typename NormalMap > CGAL_DEPRECATED_MSG("you are using the deprecated V1 API of CGAL::read_ply_points_and_normals(), please update your code") bool read_ply_points_and_normals(std::istream& stream, ///< input stream. OutputIterator output, ///< output iterator over points. PointMap point_map, ///< property map: value_type of OutputIterator -> Point_3. NormalMap normal_map) ///< property map: value_type of OutputIterator -> Vector_3. { return read_ply_points (stream, output, CGAL::parameters::point_map (point_map). normal_map (normal_map)); } // deprecated API template < typename OutputIterator, typename PointMap, typename NormalMap > CGAL_DEPRECATED_MSG("you are using the deprecated V1 API of CGAL::read_ply_points_and_normals(), please update your code") bool read_ply_points_and_normals(std::istream& stream, ///< input stream. OutputIterator output, ///< output iterator over points. PointMap point_map, ///< property map: value_type of OutputIterator -> Point_3. NormalMap normal_map) ///< property map: value_type of OutputIterator -> Vector_3. { return read_ply_points::type> (stream, output, CGAL::parameters::point_map (point_map). normal_map (normal_map)); } // deprecated API template < typename OutputIteratorValueType, typename OutputIterator, typename NormalMap > CGAL_DEPRECATED_MSG("you are using the deprecated V1 API of CGAL::read_ply_points_and_normals(), please update your code") bool read_ply_points_and_normals(std::istream& stream, ///< input stream. OutputIterator output, ///< output iterator over points. NormalMap normal_map) ///< property map: value_type of OutputIterator -> Vector_3. { return read_ply_points (stream, output, CGAL::parameters::normal_map (normal_map)); } // deprecated API template < typename OutputIterator, typename NormalMap > CGAL_DEPRECATED_MSG("you are using the deprecated V1 API of CGAL::read_ply_points_and_normals(), please update your code") bool read_ply_points_and_normals(std::istream& stream, ///< input stream. OutputIterator output, ///< output iterator over points. NormalMap normal_map) ///< property map: value_type of OutputIterator -> Vector_3. { return read_ply_points::type> (stream, output, CGAL::parameters::normal_map (normal_map)); } // deprecated API template CGAL_DEPRECATED_MSG("you are using the deprecated V1 API of CGAL::read_ply_points(), please update your code") bool read_ply_points( std::istream& stream, ///< input stream. OutputIterator output, ///< output iterator over points. PointMap point_map) ///< property map: value_type of OutputIterator -> Point_3. { return read_ply_points (stream, output, CGAL::parameters::point_map (point_map)); } // deprecated API template < typename OutputIterator, typename PointMap > CGAL_DEPRECATED_MSG("you are using the deprecated V1 API of CGAL::read_ply_points(), please update your code") bool read_ply_points(std::istream& stream, ///< input stream. OutputIterator output, ///< output iterator over points. PointMap point_map) ///< property map: value_type of OutputIterator -> Point_3. { return read_ply_points::type> (stream, output, CGAL::parameters::point_map (point_map)); } #endif // CGAL_NO_DEPRECATED_CODE /// \endcond } //namespace CGAL #undef TRY_TO_GENERATE_POINT_PROPERTY #undef TRY_TO_GENERATE_SIZED_FACE_PROPERTY #undef TRY_TO_GENERATE_FACE_PROPERTY #endif // CGAL_READ_PLY_POINTS_H