From ac3dbad721c5e851f5c4bd59a7298d45f14165bd Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 6 Oct 2015 15:01:50 +0200 Subject: [PATCH 01/24] Skeleton of new read_ply_points.h file --- .../include/CGAL/IO/read_ply_points.h | 278 ++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 Point_set_processing_3/include/CGAL/IO/read_ply_points.h diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h new file mode 100644 index 00000000000..e079ccd5731 --- /dev/null +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -0,0 +1,278 @@ +#ifndef CGAL_READ_PLY_POINTS_H +#define CGAL_READ_PLY_POINTS_H + +#include +#include +#include + +#include +#if BOOST_VERSION >= 104000 +#include +#else +#include +#endif + +#include +#include +#include + + +namespace CGAL { + +//=================================================================================== +/// \ingroup PkgPointSetProcessing +/// Reads points (positions + normals, if available) from a .ply stream. +/// 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. +/// @tparam PointPMap is a model of `WritablePropertyMap` with value type `Point_3`. +/// It can be omitted if the value type of `OutputIterator` is convertible to `Point_3`. +/// @tparam NormalPMap is a model of `WritablePropertyMap` with value type `Vector_3`. +/// @tparam Kernel Geometric traits class. +/// It can be omitted and deduced automatically from the value type of `PointPMap`. +/// +/// @return true on success. + +// This variant requires all parameters. +//----------------------------------------------------------------------------------- +template < typename OutputIteratorValueType, + typename OutputIterator, + typename PointPMap, + typename NormalPMap, + typename Kernel > +bool read_ply_points_and_normals(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + NormalPMap normal_pmap, ///< property map: value_type of OutputIterator -> Vector_3. + const Kernel& /*kernel*/) ///< geometric traits. +{ + + return true; +} + +/// @cond SKIP_IN_MANUAL +template < typename OutputIterator, + typename PointPMap, + typename NormalPMap, + typename Kernel > +bool read_ply_points_and_normals(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + NormalPMap normal_pmap, ///< property map: value_type of OutputIterator -> Vector_3. + const Kernel& kernel) ///< geometric traits. +{ + // just deduce value_type of OutputIterator + return read_ply_points_and_normals + ::type>(stream, + output, + point_pmap, + normal_pmap, + kernel); +} +//----------------------------------------------------------------------------------- +/// @endcond + +/// @cond SKIP_IN_MANUAL +// This variant deduces the kernel from the point property map. +//----------------------------------------------------------------------------------- +template < typename OutputIteratorValueType, + typename OutputIterator, + typename PointPMap, + typename NormalPMap > +bool read_ply_points_and_normals(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + NormalPMap normal_pmap) ///< property map: value_type of OutputIterator -> Vector_3. +{ + typedef typename boost::property_traits::value_type Point; + typedef typename Kernel_traits::Kernel Kernel; + return read_ply_points_and_normals + (stream, + output, + point_pmap, + normal_pmap, + Kernel()); +} + +template < typename OutputIterator, + typename PointPMap, + typename NormalPMap > +bool read_ply_points_and_normals(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + NormalPMap normal_pmap) ///< property map: value_type of OutputIterator -> Vector_3. +{ + // just deduce value_type of OutputIterator + return read_ply_points_and_normals + ::type>(stream, + output, + point_pmap, + normal_pmap); +} +//----------------------------------------------------------------------------------- +/// @endcond + +/// @cond SKIP_IN_MANUAL +// This variant creates a default point property map = Identity_property_map. +//----------------------------------------------------------------------------------- +template < typename OutputIteratorValueType, + typename OutputIterator, + typename NormalPMap > +bool read_ply_points_and_normals(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + NormalPMap normal_pmap) ///< property map: value_type of OutputIterator -> Vector_3. +{ + return read_ply_points_and_normals + (stream, + output, +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + make_dereference_property_map(output), +#else + make_identity_property_map(OutputIteratorValueType()), +#endif + normal_pmap); +} + +template < typename OutputIterator, + typename NormalPMap > +bool read_ply_points_and_normals(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + NormalPMap normal_pmap) ///< property map: value_type of OutputIterator -> Vector_3. +{ + // just deduce value_type of OutputIterator + return read_ply_points_and_normals + ::type>(stream, + output, + normal_pmap); +} +//----------------------------------------------------------------------------------- +/// @endcond + + +//=================================================================================== +/// \ingroup PkgPointSetProcessing +/// Reads points (position only) from a .ply stream. +/// If the position is followed by the nx ny nz normal, then the normal will be ignored. +/// 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. +/// @tparam PointPMap is a model of `WritablePropertyMap` with value_type `Point_3`. +/// It can be omitted if the value type of `OutputIterator` is convertible to `Point_3`. +/// @tparam Kernel Geometric traits class. +/// It can be omitted and deduced automatically from the value type of `PointPMap`. +/// +/// @return `true` on success. + +// This variant requires all parameters. +//----------------------------------------------------------------------------------- +template < typename OutputIteratorValueType, + typename OutputIterator, + typename PointPMap, + typename Kernel > +bool read_ply_points(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + const Kernel& kernel) ///< geometric traits. +{ + // Calls read_ply_points_and_normals() with a normal property map = boost::dummy_property_map + return read_ply_points_and_normals + (stream, + output, + point_pmap, + boost::dummy_property_map(), + kernel); +} + +/// @cond SKIP_IN_MANUAL +template < typename OutputIterator, + typename PointPMap, + typename Kernel > +bool read_ply_points(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + const Kernel& kernel) ///< geometric traits. +{ + // just deduce value_type of OutputIterator + return read_ply_points + ::type>(stream, + output, + point_pmap, + kernel); +} +//----------------------------------------------------------------------------------- +/// @endcond + +/// @cond SKIP_IN_MANUAL +// This variant deduces the kernel from the point property map. +//----------------------------------------------------------------------------------- +template < typename OutputIteratorValueType, + typename OutputIterator, + typename PointPMap > +bool read_ply_points(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap) ///< property map: value_type of OutputIterator -> Point_3. +{ + typedef typename boost::property_traits::value_type Point; + typedef typename Kernel_traits::Kernel Kernel; + return read_ply_points + (stream, + output, + point_pmap, + Kernel()); +} + +template < typename OutputIterator, + typename PointPMap > +bool read_ply_points(std::istream& stream, ///< input stream. + OutputIterator output, ///< output iterator over points. + PointPMap point_pmap) ///< property map: value_type of OutputIterator -> Point_3. +{ + // just deduce value_type of OutputIterator + return read_ply_points + ::type>(stream, + output, + point_pmap); +} +//----------------------------------------------------------------------------------- +/// @endcond + +/// @cond SKIP_IN_MANUAL +// This variant creates a default point property map = Identity_property_map. +//----------------------------------------------------------------------------------- +template < typename OutputIteratorValueType, + typename OutputIterator > +bool read_ply_points(std::istream& stream, ///< input stream. + OutputIterator output) ///< output iterator over points. +{ + return read_ply_points + (stream, + output, +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + make_dereference_property_map(output) +#else + make_identity_property_map(OutputIteratorValueType()) +#endif + ); +} + +template < typename OutputIterator> +bool read_ply_points(std::istream& stream, ///< input stream. + OutputIterator output) ///< output iterator over points. +{ + // just deduce value_type of OutputIterator + return read_ply_points + ::type>(stream, + output); +} +//----------------------------------------------------------------------------------- + +/// @endcond + + +} //namespace CGAL + +#endif // CGAL_READ_PLY_POINTS_H From 6b4da62cab26b51ba48370c67fb873fd71e19f69 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 6 Oct 2015 15:16:16 +0200 Subject: [PATCH 02/24] Update read_test with new ply function --- .../data/read_test/simple.ply | Bin 0 -> 320 bytes .../test/Point_set_processing_3/read_test.cpp | 13 +++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.ply diff --git a/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.ply b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.ply new file mode 100644 index 0000000000000000000000000000000000000000..8be39b1407359be4c5d2a2ffe0e567db0ca7b973 GIT binary patch literal 320 zcmZXP!3x4K42E~^Q{)L`;sZGJAcAMFrFNMsbm{0aS$Fc$4a(fu0zV{Q$e*P3NmU^> zhT-AJ#H77r_Nb9cX9)JYT-nexNDTM$<#s*66A7bXEERhEHeMJR2RNuUhF0 #include #include +#include #include #include @@ -47,6 +48,17 @@ bool read_off(std::string s, CGAL::Second_of_pair_property_map()); } +bool read_ply (std::string s, + std::vector& pv_pairs) +{ + std::ifstream fs(s.c_str()); + + return CGAL::read_ply_points_and_normals (fs, + back_inserter(pv_pairs), + CGAL::First_of_pair_property_map(), + CGAL::Second_of_pair_property_map()); +} + int main() { @@ -78,6 +90,7 @@ int main() assert(pv_pairs[2] == std::make_pair(Point_3(4,5,6), Vector_3(0,0,0))); assert(pv_pairs[3] == std::make_pair(Point_3(7,8,9), Vector_3(0,0,0))); + assert(read_ply("data/read_test/simple.ply", pv_pairs)); return 0; } From 867a731d484272561f5d4723d6371f20a6fefd39 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 6 Oct 2015 15:36:35 +0200 Subject: [PATCH 03/24] WIP: processing PLY header --- .../include/CGAL/IO/read_ply_points.h | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index e079ccd5731..05ff0f99bb1 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -48,7 +48,171 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. NormalPMap normal_pmap, ///< property map: value_type of OutputIterator -> Vector_3. const Kernel& /*kernel*/) ///< geometric traits. { + // value_type_traits is a workaround as back_insert_iterator's value_type is void + // typedef typename value_type_traits::type Enriched_point; + typedef OutputIteratorValueType Enriched_point; + typedef typename Kernel::Point_3 Point; + typedef typename Kernel::Vector_3 Vector; + + if(!stream) + { + std::cerr << "Error: cannot open file" << std::endl; + return false; + } + + // scan points + std::size_t pointsCount = 0, // number of items in file + pointsRead = 0, // current number of points read + lineNumber = 0; // current line number + enum Format { ASCII, BINARY_LITTLE_ENDIAN, BINARY_BIG_ENDIAN }; + Format format; + + std::string line; + std::istringstream iss; + + bool in_header = true; + + while (getline (stream,line)) + { + iss.clear(); + iss.str (line); + ++ lineNumber; + + if (in_header) + { + // Reads file signature on first line + if (lineNumber == 1) + { + std::string signature; + if (!(iss >> signature) || (signature != "ply")) + { + // if wrong file format + std::cerr << "Incorrect file format line " << lineNumber << " of file" << std::endl; + return false; + } + } + + // Reads format on 2nd line + else if (lineNumber == 2) + { + std::string tag, format_string, version; + if ( !(iss >> tag >> format_string >> version) ) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + if (format_string == "ascii") format = ASCII; + else if (format_string == "binary_little_endian") format = BINARY_LITTLE_ENDIAN; + else if (format_string == "binary_big_endian") format = BINARY_BIG_ENDIAN; + else + { + std::cerr << "Unknown file format \"" << format_string << "\" line " << lineNumber << std::endl; + return false; + } + } + + // Comments and vertex properties + else + { + std::string keyword; + if (!(iss >> keyword)) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + + // ignore comments and properties (if not in element + // vertex - cf below - properties are useless in our case) + if (keyword == "comment" || keyword == "property") + continue; + + if (keyword == "end_header") + { + in_header = false; + continue; + } + + if (keyword == "element") + { + std::string type; + std::size_t number; + if (!(iss >> type >> number)) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + + if (type == "face") + continue; + + if (type == "vertex") + pointsCount = number; + else + { + std::cerr << "Unknown element \"" << type << "\" line " << lineNumber << std::endl; + return false; + } + + while (getline (stream,line)) + { + iss.clear(); + iss.str (line); + ++ lineNumber; + std::string property, ftype, name; + if ( !(iss >> property >> ftype >> name) || property != "property") + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + + } + } + + } + } + + + // Reads 3D points on next lines + else if (pointsRead < pointsCount) + { + break; +// // Reads position + normal... +// double x,y,z; +// double nx,ny,nz; +// if (iss >> iformat(x) >> iformat(y) >> iformat(z)) +// { +// Point point(x,y,z); +// Vector normal = CGAL::NULL_VECTOR; +// // ... + normal... +// if (iss >> iformat(nx)) +// { +// // In case we could read one number, we expect that there are two more +// if(iss >> iformat(ny) >> iformat(nz)){ +// normal = Vector(nx,ny,nz); +// } else { +// std::cerr << "Error line " << lineNumber << " of file" << std::endl; +// return false; +// } +// } +// Enriched_point pwn; +// #ifdef CGAL_USE_PROPERTY_MAPS_API_V1 +// put(point_pmap, &pwn, point); // point_pmap[&pwn] = point +// put(normal_pmap, &pwn, normal); // normal_pmap[&pwn] = normal +// #else +// put(point_pmap, pwn, point); // point_pmap[&pwn] = point +// put(normal_pmap, pwn, normal); // normal_pmap[&pwn] = normal +// #endif +// *output++ = pwn; +// pointsRead++; +// } + // ...or skip comment line + } + // Skip remaining lines + } + + + return true; } From 442db8be132f2b931c3400184befeb0017e7d72e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 10:57:07 +0200 Subject: [PATCH 04/24] Fix OFF magic number --- .../test/Point_set_processing_3/data/read_test/simple.off | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.off b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.off index 71f3a1ccc32..462dc6fb8e6 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.off +++ b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.off @@ -1,4 +1,4 @@ -OFF +NOFF 3 0 0 1 1 1 2 2 2 3 3 3 4 4 4 From 850f28ed072ef6f19682adbe2dd504676306aa8d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 12:10:29 +0200 Subject: [PATCH 05/24] Ply reader for point sets --- .../include/CGAL/IO/read_ply_points.h | 381 ++++++++++++------ .../data/read_test/simple.ply | Bin 320 -> 320 bytes .../test/Point_set_processing_3/read_test.cpp | 3 + 3 files changed, 259 insertions(+), 125 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 05ff0f99bb1..fb50cec0c4b 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -19,6 +19,128 @@ namespace CGAL { + +// PLY types: +// name type number of bytes +// --------------------------------------- +// char character 1 +// uchar unsigned character 1 +// short short integer 2 +// ushort unsigned short integer 2 +// int integer 4 +// uint unsigned integer 4 +// float single-precision float 4 +// double double-precision float 8 + +namespace internal { + + class Ply_read_number + { + protected: + std::string m_name; + std::size_t m_format; + + public: + Ply_read_number (std::string name, std::size_t format) + : m_name (name), m_format (format) { } + virtual ~Ply_read_number() { } + + const std::string& name () const { return m_name; } + + virtual double operator() (std::istream& stream) const = 0; + + template + Type read (std::istream& stream) const + { + if (m_format == 0) // Ascii + { + Type t; + stream >> t; + return t; + } + else // Binary (2 = little endian) + { + std::size_t size = sizeof (Type); + unsigned int buffer[size]; + + stream.read(reinterpret_cast(buffer), size); + + if (m_format == 2) // Big endian + { + for (std::size_t i = 0; i < size / 2; ++ i) + { + unsigned char tmp = buffer[i]; + buffer[i] = buffer[size - i]; + buffer[size - i] = tmp; + } + } + return reinterpret_cast (buffer); + } + return Type(); + } + }; + + class Ply_read_char : public Ply_read_number + { + public: + Ply_read_char (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_uchar : public Ply_read_number + { + public: + Ply_read_uchar (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_short : public Ply_read_number + { + public: + Ply_read_short (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_ushort : public Ply_read_number + { + public: + Ply_read_ushort (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_int : public Ply_read_number + { + public: + Ply_read_int (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_uint : public Ply_read_number + { + public: + Ply_read_uint (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_float : public Ply_read_number + { + public: + Ply_read_float (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return static_cast (this->read (stream)); } + }; + class Ply_read_double : public Ply_read_number + { + public: + Ply_read_double (std::string name, std::size_t format) : Ply_read_number (name, format) { } + double operator() (std::istream& stream) const + { return this->read (stream); } + }; + + + +} //namespace CGAL + //=================================================================================== /// \ingroup PkgPointSetProcessing /// Reads points (positions + normals, if available) from a .ply stream. @@ -54,6 +176,7 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. typedef typename Kernel::Point_3 Point; typedef typename Kernel::Vector_3 Vector; + typedef typename Kernel::FT FT; if(!stream) { @@ -65,13 +188,15 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. std::size_t pointsCount = 0, // number of items in file pointsRead = 0, // current number of points read lineNumber = 0; // current line number - enum Format { ASCII, BINARY_LITTLE_ENDIAN, BINARY_BIG_ENDIAN }; + enum Format { ASCII = 0, BINARY_LITTLE_ENDIAN = 1, BINARY_BIG_ENDIAN = 2}; Format format; std::string line; std::istringstream iss; - bool in_header = true; + // Check the order of the properties of the point set + bool reading_properties = false; + std::vector readers; while (getline (stream,line)) { @@ -79,139 +204,145 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. iss.str (line); ++ lineNumber; - if (in_header) + // Reads file signature on first line + if (lineNumber == 1) { - // Reads file signature on first line - if (lineNumber == 1) + std::string signature; + if (!(iss >> signature) || (signature != "ply")) { - std::string signature; - if (!(iss >> signature) || (signature != "ply")) - { - // if wrong file format - std::cerr << "Incorrect file format line " << lineNumber << " of file" << std::endl; - return false; - } - } - - // Reads format on 2nd line - else if (lineNumber == 2) - { - std::string tag, format_string, version; - if ( !(iss >> tag >> format_string >> version) ) - { - std::cerr << "Error line " << lineNumber << " of file" << std::endl; - return false; - } - if (format_string == "ascii") format = ASCII; - else if (format_string == "binary_little_endian") format = BINARY_LITTLE_ENDIAN; - else if (format_string == "binary_big_endian") format = BINARY_BIG_ENDIAN; - else - { - std::cerr << "Unknown file format \"" << format_string << "\" line " << lineNumber << std::endl; - return false; - } - } - - // Comments and vertex properties - else - { - std::string keyword; - if (!(iss >> keyword)) - { - std::cerr << "Error line " << lineNumber << " of file" << std::endl; - return false; - } - - // ignore comments and properties (if not in element - // vertex - cf below - properties are useless in our case) - if (keyword == "comment" || keyword == "property") - continue; - - if (keyword == "end_header") - { - in_header = false; - continue; - } - - if (keyword == "element") - { - std::string type; - std::size_t number; - if (!(iss >> type >> number)) - { - std::cerr << "Error line " << lineNumber << " of file" << std::endl; - return false; - } - - if (type == "face") - continue; - - if (type == "vertex") - pointsCount = number; - else - { - std::cerr << "Unknown element \"" << type << "\" line " << lineNumber << std::endl; - return false; - } - - while (getline (stream,line)) - { - iss.clear(); - iss.str (line); - ++ lineNumber; - std::string property, ftype, name; - if ( !(iss >> property >> ftype >> name) || property != "property") - { - std::cerr << "Error line " << lineNumber << " of file" << std::endl; - return false; - } - - } - } - + // if wrong file format + std::cerr << "Incorrect file format line " << lineNumber << " of file" << std::endl; + return false; } } + // Reads format on 2nd line + else if (lineNumber == 2) + { + std::string tag, format_string, version; + if ( !(iss >> tag >> format_string >> version) ) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + if (format_string == "ascii") format = ASCII; + else if (format_string == "binary_little_endian") format = BINARY_LITTLE_ENDIAN; + else if (format_string == "binary_big_endian") format = BINARY_BIG_ENDIAN; + else + { + std::cerr << "Unknown file format \"" << format_string << "\" line " << lineNumber << std::endl; + return false; + } + } - // Reads 3D points on next lines - else if (pointsRead < pointsCount) + // Comments and vertex properties + else + { + std::string keyword; + if (!(iss >> keyword)) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + + if (keyword == "property") + { + if (!reading_properties) + continue; + + std::string type, name; + if (!(iss >> type >> name)) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + + if (type == "char") + readers.push_back (new internal::Ply_read_char (name, format)); + else if (type == "uchar") + readers.push_back (new internal::Ply_read_uchar (name, format)); + else if (type == "short") + readers.push_back (new internal::Ply_read_short (name, format)); + else if (type == "ushort") + readers.push_back (new internal::Ply_read_ushort (name, format)); + else if (type == "int") + readers.push_back (new internal::Ply_read_int (name, format)); + else if (type == "uint") + readers.push_back (new internal::Ply_read_uint (name, format)); + else if (type == "float") + readers.push_back (new internal::Ply_read_float (name, format)); + else if (type == "double") + readers.push_back (new internal::Ply_read_double (name, format)); + + continue; + } + else + reading_properties = false; + + // ignore comments and properties (if not in element + // vertex - cf below - properties are useless in our case) + if (keyword == "comment" || keyword == "property") + continue; + + if (keyword == "end_header") + break; + + if (keyword == "element") + { + std::string type; + std::size_t number; + if (!(iss >> type >> number)) + { + std::cerr << "Error line " << lineNumber << " of file" << std::endl; + return false; + } + + if (type == "vertex") + { + pointsCount = number; + reading_properties = true; + } + else + continue; + } + + } + } + + while (!(stream.eof()) && pointsRead < pointsCount) { - break; -// // Reads position + normal... -// double x,y,z; -// double nx,ny,nz; -// if (iss >> iformat(x) >> iformat(y) >> iformat(z)) -// { -// Point point(x,y,z); -// Vector normal = CGAL::NULL_VECTOR; -// // ... + normal... -// if (iss >> iformat(nx)) -// { -// // In case we could read one number, we expect that there are two more -// if(iss >> iformat(ny) >> iformat(nz)){ -// normal = Vector(nx,ny,nz); -// } else { -// std::cerr << "Error line " << lineNumber << " of file" << std::endl; -// return false; -// } -// } -// Enriched_point pwn; -// #ifdef CGAL_USE_PROPERTY_MAPS_API_V1 -// put(point_pmap, &pwn, point); // point_pmap[&pwn] = point -// put(normal_pmap, &pwn, normal); // normal_pmap[&pwn] = normal -// #else -// put(point_pmap, pwn, point); // point_pmap[&pwn] = point -// put(normal_pmap, pwn, normal); // normal_pmap[&pwn] = normal -// #endif -// *output++ = pwn; -// pointsRead++; -// } - // ...or skip comment line + + FT x, y, z, nx, ny, nz; + for (std::size_t i = 0; i < readers.size (); ++ i) + { + FT value = (*readers[i])(stream); + + if (readers[i]->name () == "x") x = value; + else if (readers[i]->name () == "y") y = value; + else if (readers[i]->name () == "z") z = value; + else if (readers[i]->name () == "nx") nx = value; + else if (readers[i]->name () == "ny") ny = value; + else if (readers[i]->name () == "nz") nz = value; + } + Point point(x,y,z); + Vector normal(nx,ny,nz); + + Enriched_point pwn; + +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + put(point_pmap, &pwn, point); // point_pmap[&pwn] = point + put(normal_pmap, &pwn, normal); // normal_pmap[&pwn] = normal +#else + put(point_pmap, pwn, point); // point_pmap[&pwn] = point + put(normal_pmap, pwn, normal); // normal_pmap[&pwn] = normal +#endif + *output++ = pwn; + pointsRead++; } // Skip remaining lines - } - + for (std::size_t i = 0; i < readers.size (); ++ i) + delete readers[i]; return true; } diff --git a/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.ply b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple.ply index 8be39b1407359be4c5d2a2ffe0e567db0ca7b973..1f55c3277c07229ef86c55d42ca19b926f4b2ad7 100644 GIT binary patch delta 65 mcmX@Wbbx6CJENro0|NsTI{;}IZUC}jcma?N!v}zD2nGOxg$$Me delta 65 ecmX@Wbbx6CJEJ875^w;rVHjB$DCPjg2w?!y_5`*7 diff --git a/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp index cd9df54f49c..0171510a402 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp @@ -90,7 +90,10 @@ int main() assert(pv_pairs[2] == std::make_pair(Point_3(4,5,6), Vector_3(0,0,0))); assert(pv_pairs[3] == std::make_pair(Point_3(7,8,9), Vector_3(0,0,0))); + pv_pairs.clear (); assert(read_ply("data/read_test/simple.ply", pv_pairs)); + pv_pairs.clear (); + assert(read_ply("data/read_test/simple_ascii.ply", pv_pairs)); return 0; } From 5c12ec1e4ee3f4f6fbc9779317dcdd3fa62bf161 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 12:40:46 +0200 Subject: [PATCH 06/24] Add new ply test (ascii format) --- .../data/read_test/simple_ascii.ply | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_ascii.ply diff --git a/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_ascii.ply b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_ascii.ply new file mode 100644 index 00000000000..5bc4a19d34f --- /dev/null +++ b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_ascii.ply @@ -0,0 +1,16 @@ +ply +format ascii 1.0 +comment VCGLIB generated +element vertex 3 +property float x +property float y +property float z +property float nx +property float ny +property float nz +element face 0 +property list uchar int vertex_indices +end_header +1 1 1 2 2 2 +3 3 3 4 4 4 +5 5 5 6 6 6 From 93c52c605c0267b455e4bcf0559f9de373c46197 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 13:49:24 +0200 Subject: [PATCH 07/24] New test for ply reader --- .../data/read_test/simple_with_flag.ply | Bin 0 -> 351 bytes .../test/Point_set_processing_3/read_test.cpp | 2 + .../Polyhedron_demo_ply_to_xyz_plugin.cpp | 58 ++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_with_flag.ply create mode 100644 Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp diff --git a/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_with_flag.ply b/Point_set_processing_3/test/Point_set_processing_3/data/read_test/simple_with_flag.ply new file mode 100644 index 0000000000000000000000000000000000000000..55661dd36bce5fb0138d040d4581965abe822efd GIT binary patch literal 351 zcmZXPK@Ng25JkK0Ddq$Q;{i0fFea|uHe(r}Nf}6~23&CzkK)lBG=RayOaA=npZwOo z(^(ZtjBs^~p)=ma=*bYL4jI;~MBAz?i6dMN$Mb0qIWYx{lxp(yS==c^YGI@6P}QP4 z$b2Oi+ojPhjmOg9zYPC{_$TG0SLQKqrZO2?f@HqyT@&GE3k)zk{&qD^zGq2NoSK3# erJ$ASw=-&|)WjfV9_dAo$VxqB9(jo#QR)p`O>V6K literal 0 HcmV?d00001 diff --git a/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp index 0171510a402..26c4760c2b5 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp @@ -94,6 +94,8 @@ int main() assert(read_ply("data/read_test/simple.ply", pv_pairs)); pv_pairs.clear (); assert(read_ply("data/read_test/simple_ascii.ply", pv_pairs)); + pv_pairs.clear (); + assert(read_ply("data/read_test/simple_with_flag.ply", pv_pairs)); return 0; } diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp new file mode 100644 index 00000000000..5d29e200529 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp @@ -0,0 +1,58 @@ +#include "Scene_points_with_normal_item.h" +#include "Polyhedron_demo_io_plugin_interface.h" + +#include + +class Polyhedron_demo_ply_to_xyz_plugin : + public QObject, + public Polyhedron_demo_io_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(Polyhedron_demo_io_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0") + +public: + QString name() const { return "ply_to_xyz_plugin"; } + QString nameFilters() const { return "PLY files as Point set (*.ply)"; } + bool canLoad() const; + Scene_item* load(QFileInfo fileinfo); + + bool canSave(const Scene_item*); + bool save(const Scene_item*, QFileInfo fileinfo); +}; + +bool Polyhedron_demo_ply_to_xyz_plugin::canLoad() const { + return true; +} + +Scene_item* +Polyhedron_demo_ply_to_xyz_plugin::load(QFileInfo fileinfo) { + std::ifstream in(fileinfo.filePath().toUtf8()); + + if(!in) + std::cerr << "Error!\n"; + + Scene_points_with_normal_item* item; + item = new Scene_points_with_normal_item(); + if(!item->read_ply_point_set(in)) + { + delete item; + return 0; + } + + item->setName(fileinfo.baseName()); + return item; +} + +bool Polyhedron_demo_ply_to_xyz_plugin::canSave(const Scene_item*) +{ + return false; +} + +bool Polyhedron_demo_ply_to_xyz_plugin::save(const Scene_item*, QFileInfo) +{ + return false; +} + + +#include "Polyhedron_demo_ply_to_xyz_plugin.moc" From fddcb241975c3352618a607671e2f4d88197721d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 13:50:57 +0200 Subject: [PATCH 08/24] Polyhedron demo ply_to_xyz reader --- .../include/CGAL/IO/read_ply_points.h | 2 +- Polyhedron/demo/Polyhedron/CMakeLists.txt | 3 +++ .../Polyhedron/Scene_points_with_normal_item.cpp | 16 ++++++++++++++++ .../Polyhedron/Scene_points_with_normal_item.h | 1 + Polyhedron/demo/Polyhedron/cgal_test_with_cmake | 1 + 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index fb50cec0c4b..08a4c0be32d 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -284,6 +284,7 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. if (keyword == "comment" || keyword == "property") continue; + // When end_header is reached, stop loop and begin reading points if (keyword == "end_header") break; @@ -316,7 +317,6 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. for (std::size_t i = 0; i < readers.size (); ++ i) { FT value = (*readers[i])(stream); - if (readers[i]->name () == "x") x = value; else if (readers[i]->name () == "y") y = value; else if (readers[i]->name () == "z") z = value; diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 2df990619b6..5b54bcc5c22 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -319,6 +319,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND) polyhedron_demo_plugin(off_to_xyz_plugin Polyhedron_demo_off_to_xyz_plugin) target_link_libraries(off_to_xyz_plugin scene_points_with_normal_item) + polyhedron_demo_plugin(ply_to_xyz_plugin Polyhedron_demo_ply_to_xyz_plugin) + target_link_libraries(ply_to_xyz_plugin scene_points_with_normal_item) + polyhedron_demo_plugin(convex_hull_plugin Polyhedron_demo_convex_hull_plugin) target_link_libraries(convex_hull_plugin scene_polyhedron_item scene_points_with_normal_item scene_polylines_item scene_polyhedron_selection_item) diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp index e583cbb6cf5..96ab82e8314 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp @@ -2,6 +2,7 @@ #include "Polyhedron_type.h" #include +#include #include #include #include @@ -317,6 +318,21 @@ void Scene_points_with_normal_item::selectDuplicates() Q_EMIT itemChanged(); } +// Loads point set from .PLY file +bool Scene_points_with_normal_item::read_ply_point_set(std::istream& stream) +{ + Q_ASSERT(m_points != NULL); + + m_points->clear(); + bool ok = stream && + CGAL::read_ply_points_and_normals(stream, + std::back_inserter(*m_points), + CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())) && + !isEmpty(); + invalidate_buffers(); + return ok; +} + // Loads point set from .OFF file bool Scene_points_with_normal_item::read_off_point_set(std::istream& stream) { diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h index 4e4f6b82e0e..be1dec4d03d 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h @@ -36,6 +36,7 @@ public: QMenu* contextMenu(); // IO + bool read_ply_point_set(std::istream& in); bool read_off_point_set(std::istream& in); bool write_off_point_set(std::ostream& out) const; bool read_xyz_point_set(std::istream& in); diff --git a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake index 2f49750a143..203a417cde9 100755 --- a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake +++ b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake @@ -126,6 +126,7 @@ else orient_soup_plugin \ parameterization_plugin \ pca_plugin \ + ply_to_xyz_plugin \ point_dialog \ point_inside_polyhedron_plugin \ point_set_average_spacing_plugin \ From f732c100c321414ab3c558ea3fd1c9ddcf14e56c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 14:08:03 +0200 Subject: [PATCH 09/24] Fix warnings and use union instead of reinterpret_cast --- .../include/CGAL/IO/read_ply_points.h | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 08a4c0be32d..7ce69c247f6 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -60,21 +60,26 @@ namespace internal { } else // Binary (2 = little endian) { + union + { + unsigned char uChar[sizeof (Type)]; + Type type; + } buffer; + std::size_t size = sizeof (Type); - unsigned int buffer[size]; - stream.read(reinterpret_cast(buffer), size); + stream.read(reinterpret_cast(buffer.uChar), size); if (m_format == 2) // Big endian { for (std::size_t i = 0; i < size / 2; ++ i) { - unsigned char tmp = buffer[i]; - buffer[i] = buffer[size - i]; - buffer[size - i] = tmp; + unsigned char tmp = buffer.uChar[i]; + buffer.uChar[i] = buffer.uChar[size - 1 - i]; + buffer.uChar[size - 1 - i] = tmp; } } - return reinterpret_cast (buffer); + return buffer.type; } return Type(); } @@ -189,7 +194,7 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. pointsRead = 0, // current number of points read lineNumber = 0; // current line number enum Format { ASCII = 0, BINARY_LITTLE_ENDIAN = 1, BINARY_BIG_ENDIAN = 2}; - Format format; + Format format = ASCII; std::string line; std::istringstream iss; @@ -313,7 +318,7 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. while (!(stream.eof()) && pointsRead < pointsCount) { - FT x, y, z, nx, ny, nz; + FT x = 0., y = 0., z = 0., nx = 0., ny = 0., nz = 0.; for (std::size_t i = 0; i < readers.size (); ++ i) { FT value = (*readers[i])(stream); From 674bcb5d917798fb34081a3d45fd01b666715265 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 14:13:55 +0200 Subject: [PATCH 10/24] Check if point set has normals when reading PLY --- .../Polyhedron/Scene_points_with_normal_item.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp index 96ab82e8314..4d7d50e49fb 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp @@ -329,6 +329,19 @@ bool Scene_points_with_normal_item::read_ply_point_set(std::istream& stream) std::back_inserter(*m_points), CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())) && !isEmpty(); + if (ok) + { + for (Point_set::iterator it=m_points->begin(), + end=m_points->end();it!=end; ++it) + { + if (it->normal() != CGAL::NULL_VECTOR) + { + m_has_normals=true; + setRenderingMode(PointsPlusNormals); + break; + } + } + } invalidate_buffers(); return ok; } From a8bea5e6d9826f58ced8b4f47a098f67ed81d099 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 14:19:26 +0200 Subject: [PATCH 11/24] Handle detailed types (e.g. int16 instead of short) --- .../include/CGAL/IO/read_ply_points.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 7ce69c247f6..27e082b2fae 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -262,21 +262,21 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. return false; } - if (type == "char") + if ( type == "char" || type == "int8") readers.push_back (new internal::Ply_read_char (name, format)); - else if (type == "uchar") + else if (type == "uchar" || type == "uint8") readers.push_back (new internal::Ply_read_uchar (name, format)); - else if (type == "short") + else if (type == "short" || type == "int16") readers.push_back (new internal::Ply_read_short (name, format)); - else if (type == "ushort") + else if (type == "ushort" || type == "uint16") readers.push_back (new internal::Ply_read_ushort (name, format)); - else if (type == "int") + else if (type == "int" || type == "int32") readers.push_back (new internal::Ply_read_int (name, format)); - else if (type == "uint") + else if (type == "uint" || type == "uint32") readers.push_back (new internal::Ply_read_uint (name, format)); - else if (type == "float") + else if (type == "float" || type == "float32") readers.push_back (new internal::Ply_read_float (name, format)); - else if (type == "double") + else if (type == "double" || type == "float64") readers.push_back (new internal::Ply_read_double (name, format)); continue; From 0004aed5bc95124c31ca268e4617aa664457a860 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 15:06:08 +0200 Subject: [PATCH 12/24] Bug fix: explicitly ask an integer when reading char/uchar from stream --- .../include/CGAL/IO/read_ply_points.h | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 27e082b2fae..67908f05fcc 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -49,26 +49,50 @@ namespace internal { virtual double operator() (std::istream& stream) const = 0; + + // The two following functions prevent the stream to only extract + // ONE character (= what the types char imply) by requiring + // explicitely an integer object when reading the stream + void read_ascii (std::istream& stream, char& c) const + { + short s; + stream >> s; + c = static_cast(s); + } + void read_ascii (std::istream& stream, unsigned char& c) const + { + unsigned short s; + stream >> s; + c = static_cast(s); + } + + // Default template when Type is not a char type + template + void read_ascii (std::istream& stream, Type& t) const + { + stream >> t; + } + template Type read (std::istream& stream) const { if (m_format == 0) // Ascii { Type t; - stream >> t; + read_ascii (stream, t); return t; } else // Binary (2 = little endian) { union { - unsigned char uChar[sizeof (Type)]; + char uChar[sizeof (Type)]; Type type; } buffer; std::size_t size = sizeof (Type); - stream.read(reinterpret_cast(buffer.uChar), size); + stream.read(buffer.uChar, size); if (m_format == 2) // Big endian { From 1e068b084404ef53c377207d17668615e2852245 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 15:12:19 +0200 Subject: [PATCH 13/24] Skeleton of write_ply_points.h file --- .../include/CGAL/IO/write_ply_points.h | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 Point_set_processing_3/include/CGAL/IO/write_ply_points.h diff --git a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h new file mode 100644 index 00000000000..c7bb74b20f9 --- /dev/null +++ b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h @@ -0,0 +1,250 @@ +// Copyright (c) 2007-09 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Pierre Alliez and Laurent Saboret + +#ifndef CGAL_WRITE_PLY_POINTS_H +#define CGAL_WRITE_PLY_POINTS_H + +#include +#include + +#include +#if BOOST_VERSION >= 104000 + #include +#else + #include +#endif + +#include +#include + +namespace CGAL { + + +//=================================================================================== +/// \ingroup PkgPointSetProcessing +/// Saves the [first, beyond) range of points (positions + normals) to a .ply stream. +/// +/// \pre normals must be unit vectors +/// +/// @tparam ForwardIterator iterator over input points. +/// @tparam PointPMap is a model of `ReadablePropertyMap` with value type `Point_3`. +/// It can be omitted if the value type of `ForwardIterator` is convertible to `Point_3`. +/// @tparam NormalPMap is a model of `ReadablePropertyMap` with a value type `Vector_3`. +/// @tparam Kernel Geometric traits class. +/// It can be omitted and deduced automatically from the value type of `PointPMap`. +/// +/// @return true on success. + +// This variant requires all parameters. +template +bool +write_ply_points_and_normals( + std::ostream& stream, ///< output stream. + ForwardIterator first, ///< iterator over the first input point. + ForwardIterator beyond, ///< past-the-end iterator over the input points. + PointPMap point_pmap, ///< property map: value_type of ForwardIterator -> Point_3. + NormalPMap normal_pmap, ///< property map: value_type of ForwardIterator -> Vector_3. + const Kernel& /*kernel*/) ///< geometric traits. +{ + // basic geometric types + typedef typename Kernel::Point_3 Point; + typedef typename Kernel::Vector_3 Vector; + + CGAL_point_set_processing_precondition(first != beyond); + + if(!stream) + { + std::cerr << "Error: cannot open file" << std::endl; + return false; + } + + // Write header + + // Write positions + normals + for(ForwardIterator it = first; it != beyond; it++) + { +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + Point p = get(point_pmap, it); + Vector n = get(normal_pmap, it); +#else + Point p = get(point_pmap, *it); + Vector n = get(normal_pmap, *it); +#endif + stream << p << " " << n << std::endl; + } + + return ! stream.fail(); +} + +/// @cond SKIP_IN_MANUAL +// This variant deduces the kernel from the point property map. +template +bool +write_ply_points_and_normals( + std::ostream& stream, ///< output stream. + ForwardIterator first, ///< first input point. + ForwardIterator beyond, ///< past-the-end input point. + PointPMap point_pmap, ///< property map: value_type of OutputIterator -> Point_3. + NormalPMap normal_pmap) ///< property map: value_type of OutputIterator -> Vector_3. +{ + typedef typename boost::property_traits::value_type Point; + typedef typename Kernel_traits::Kernel Kernel; + return write_ply_points_and_normals( + stream, + first, beyond, + point_pmap, + normal_pmap, + Kernel()); +} +/// @endcond + +/// @cond SKIP_IN_MANUAL +// This variant creates a default point property map = Identity_property_map. +template +bool +write_ply_points_and_normals( + std::ostream& stream, ///< output stream. + ForwardIterator first, ///< first input point. + ForwardIterator beyond, ///< past-the-end input point. + NormalPMap normal_pmap) ///< property map: value_type of OutputIterator -> Vector_3. +{ + return write_ply_points_and_normals( + stream, + first, beyond, +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + make_dereference_property_map(first), +#else + make_identity_property_map( + typename std::iterator_traits::value_type()), +#endif + normal_pmap); +} +/// @endcond + + +//=================================================================================== +/// \ingroup PkgPointSetProcessing +/// Saves the [first, beyond) range of points (positions only) to a .ply ASCII stream. +/// +/// @tparam ForwardIterator iterator over input points. +/// @tparam PointPMap is a model of `ReadablePropertyMap` with a value_type = `Point_3`. +/// It can be omitted if the value type of `ForwardIterator` is convertible to `Point_3`. +/// @tparam Kernel Geometric traits class. +/// It can be omitted and deduced automatically from the value type of `PointPMap`. +/// +/// @return true on success. + +// This variant requires all parameters. +template +bool +write_ply_points( + std::ostream& stream, ///< output stream. + ForwardIterator first, ///< iterator over the first input point. + ForwardIterator beyond, ///< past-the-end iterator over the input points. + PointPMap point_pmap, ///< property map: value_type of ForwardIterator -> Point_3. + const Kernel& ) ///< geometric traits. +{ + // basic geometric types + typedef typename Kernel::Point_3 Point; + + CGAL_point_set_processing_precondition(first != beyond); + + if(!stream) + { + std::cerr << "Error: cannot open file" << std::endl; + return false; + } + + // Write header + + // Write positions + for(ForwardIterator it = first; it != beyond; it++) + { +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + Point p = get(point_pmap, it); +#else + Point p = get(point_pmap, *it); +#endif + stream << p << std::endl; + } + + return ! stream.fail(); +} + +/// @cond SKIP_IN_MANUAL +// This variant deduces the kernel from the point property map. +template +bool +write_ply_points( + std::ostream& stream, ///< output stream. + ForwardIterator first, ///< first input point. + ForwardIterator beyond, ///< past-the-end input point. + PointPMap point_pmap) ///< property map: value_type of OutputIterator -> Point_3. +{ + typedef typename boost::property_traits::value_type Point; + typedef typename Kernel_traits::Kernel Kernel; + return write_ply_points( + stream, + first, beyond, + point_pmap, + Kernel()); +} +/// @endcond + +/// @cond SKIP_IN_MANUAL +// This variant creates a default point property map = Identity_property_map. +template +bool +write_ply_points( + std::ostream& stream, ///< output stream. + ForwardIterator first, ///< first input point. + ForwardIterator beyond) ///< past-the-end input point. +{ + return write_ply_points( + stream, + first, beyond, +#ifdef CGAL_USE_PROPERTY_MAPS_API_V1 + make_dereference_property_map(first) +#else + make_identity_property_map( + typename std::iterator_traits::value_type()) +#endif + ); +} +/// @endcond + + +} //namespace CGAL + +#endif // CGAL_WRITE_PLY_POINTS_H From 30323c816abbddefe7f652abe4a50517c1ae79ac Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 15:34:08 +0200 Subject: [PATCH 14/24] Write PLY headers --- .../include/CGAL/IO/write_ply_points.h | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h index c7bb74b20f9..004ac2f9db1 100644 --- a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h @@ -38,7 +38,7 @@ namespace CGAL { //=================================================================================== /// \ingroup PkgPointSetProcessing -/// Saves the [first, beyond) range of points (positions + normals) to a .ply stream. +/// Saves the [first, beyond) range of points (positions + normals) to a .ply ASCII stream. /// /// \pre normals must be unit vectors /// @@ -79,6 +79,18 @@ write_ply_points_and_normals( } // Write header + stream << "ply" << std::endl + << "format ascii 1.0" << std::endl + << "comment Generated by the CGAL library" << std::endl + << "element vertex " << std::distance (first, beyond) << std::endl + << "property double x" << std::endl + << "property double y" << std::endl + << "property double z" << std::endl + << "property double nx" << std::endl + << "property double ny" << std::endl + << "property double nz" << std::endl + << "end_header" << std::endl; + // Write positions + normals for(ForwardIterator it = first; it != beyond; it++) @@ -184,6 +196,14 @@ write_ply_points( } // Write header + stream << "ply" << std::endl + << "format ascii 1.0" << std::endl + << "comment Generated by the CGAL library" << std::endl + << "element vertex " << std::distance (first, beyond) << std::endl + << "property double x" << std::endl + << "property double y" << std::endl + << "property double z" << std::endl + << "end_header" << std::endl; // Write positions for(ForwardIterator it = first; it != beyond; it++) From 414f04068ed4058fee95872d9b19b01dcee96193 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 7 Oct 2015 15:34:23 +0200 Subject: [PATCH 15/24] Write PLY in polyhedron scene point set item --- .../Polyhedron/Scene_points_with_normal_item.cpp | 12 ++++++++++++ .../demo/Polyhedron/Scene_points_with_normal_item.h | 1 + 2 files changed, 13 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp index 4d7d50e49fb..8c9e3a33584 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -346,6 +347,17 @@ bool Scene_points_with_normal_item::read_ply_point_set(std::istream& stream) return ok; } +// Write point set to .PLY file +bool Scene_points_with_normal_item::write_ply_point_set(std::ostream& stream) const +{ + Q_ASSERT(m_points != NULL); + + return stream && + CGAL::write_ply_points_and_normals(stream, + m_points->begin(), m_points->end(), + CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type())); +} + // Loads point set from .OFF file bool Scene_points_with_normal_item::read_off_point_set(std::istream& stream) { diff --git a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h index be1dec4d03d..02c726b7c1b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_points_with_normal_item.h @@ -37,6 +37,7 @@ public: // IO bool read_ply_point_set(std::istream& in); + bool write_ply_point_set(std::ostream& out) const; bool read_off_point_set(std::istream& in); bool write_off_point_set(std::ostream& out) const; bool read_xyz_point_set(std::istream& in); From bf3fb02373246d86228eaf31bbc4c321a95c5302 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 07:15:00 +0200 Subject: [PATCH 16/24] Enable possibility to save point sets in ply format (polyhedron demo) --- .../Polyhedron_demo_ply_to_xyz_plugin.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp index 5d29e200529..91ddfec4c63 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_ply_to_xyz_plugin.cpp @@ -44,14 +44,28 @@ Polyhedron_demo_ply_to_xyz_plugin::load(QFileInfo fileinfo) { return item; } -bool Polyhedron_demo_ply_to_xyz_plugin::canSave(const Scene_item*) +bool Polyhedron_demo_ply_to_xyz_plugin::canSave(const Scene_item* item) { - return false; + // This plugin supports point sets + return qobject_cast(item); } -bool Polyhedron_demo_ply_to_xyz_plugin::save(const Scene_item*, QFileInfo) +bool Polyhedron_demo_ply_to_xyz_plugin::save(const Scene_item* item, QFileInfo fileinfo) { - return false; + // Check extension (quietly) + std::string extension = fileinfo.suffix().toUtf8().data(); + if (extension != "ply" && extension != "PLY") + return false; + + // This plugin supports point sets + const Scene_points_with_normal_item* point_set_item = + qobject_cast(item); + if(!point_set_item) + return false; + + // Save point set as .xyz + std::ofstream out(fileinfo.filePath().toUtf8().data()); + return point_set_item->write_ply_point_set(out); } From 9bee5207448cd8bae72caf40aac97e7c555c6e10 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 08:32:40 +0200 Subject: [PATCH 17/24] Enable possibility to save point sets in off format (polyhedron demo) --- .../Polyhedron_demo_off_to_xyz_plugin.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_xyz_plugin.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_xyz_plugin.cpp index cc32c58e245..375adf00f29 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_xyz_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_off_to_xyz_plugin.cpp @@ -56,14 +56,28 @@ Polyhedron_demo_off_to_xyz_plugin::load(QFileInfo fileinfo) { return item; } -bool Polyhedron_demo_off_to_xyz_plugin::canSave(const Scene_item*) +bool Polyhedron_demo_off_to_xyz_plugin::canSave(const Scene_item* item) { - return false; + // This plugin supports point sets + return qobject_cast(item); } -bool Polyhedron_demo_off_to_xyz_plugin::save(const Scene_item*, QFileInfo) +bool Polyhedron_demo_off_to_xyz_plugin::save(const Scene_item* item, QFileInfo fileinfo) { - return false; + // Check extension (quietly) + std::string extension = fileinfo.suffix().toUtf8().data(); + if (extension != "off" && extension != "OFF") + return false; + + // This plugin supports point sets + const Scene_points_with_normal_item* point_set_item = + qobject_cast(item); + if(!point_set_item) + return false; + + // Save point set as .xyz + std::ofstream out(fileinfo.filePath().toUtf8().data()); + return point_set_item->write_off_point_set(out); } From 512273ae5ff34fe96dd9fe063536cdd177a63d2f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 08:47:14 +0200 Subject: [PATCH 18/24] Update doc and tests --- .../Point_set_processing_3/PackageDescription.txt | 2 ++ .../Point_set_processing_3.txt | 14 ++++++++++---- .../include/CGAL/IO/read_ply_points.h | 10 +++++----- .../test/Point_set_processing_3/read_test.cpp | 11 +++++++++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt index d5314b0615b..ea4f4ab503a 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt @@ -25,6 +25,7 @@ ## Functions ## - `CGAL::read_off_points()` +- `CGAL::read_ply_points()` - `CGAL::read_xyz_points()` - `CGAL::compute_average_spacing()` - `CGAL::remove_outliers()` @@ -41,6 +42,7 @@ - `CGAL::vcm_estimate_normals()` - `CGAL::vcm_is_on_feature_edge()` - `CGAL::write_off_points()` +- `CGAL::write_ply_points()` - `CGAL::write_xyz_points()` */ diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 4011ef657d1..e01683a5bee 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -80,13 +80,19 @@ a property map. We provide functions to read and write sets of points or sets of points with normals from the following ASCII file formats: XYZ (three point coordinates `x y z` per line or three point coordinates and -three normal vector coordinates `x y z nx ny nz` per line), and OFF -(%Object File Format) \cgalCite{cgal:p-gmgv16-96}. +three normal vector coordinates `x y z nx ny nz` per line), OFF +(%Object File Format) \cgalCite{cgal:p-gmgv16-96} and PLY (Polygon +File Format). - `read_xyz_points()` -- `read_off_points()` +- `read_off_points()` +- `read_ply_points()` - `write_off_points()` -- `write_xyz_points()` +- `write_xyz_points()` +- `write_ply_points()` + +Note that `read_ply_points()` also accepts binary PLY format in +addition of ASCII. \subsection Point_set_processing_3Example Example diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 67908f05fcc..aa9f17054e4 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -172,8 +172,9 @@ namespace internal { //=================================================================================== /// \ingroup PkgPointSetProcessing -/// Reads points (positions + normals, if available) from a .ply stream. -/// Faces are ignored. +/// 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. @@ -477,9 +478,8 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. //=================================================================================== /// \ingroup PkgPointSetProcessing -/// Reads points (position only) from a .ply stream. -/// If the position is followed by the nx ny nz normal, then the normal will be ignored. -/// Faces are ignored. +/// Reads points (position only) from a .ply stream (ASCII or binary). +/// Potential additional point properties (including normals) 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. diff --git a/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp index 26c4760c2b5..5d32d7d3094 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/read_test.cpp @@ -92,10 +92,21 @@ int main() pv_pairs.clear (); assert(read_ply("data/read_test/simple.ply", pv_pairs)); + assert(pv_pairs[0] == std::make_pair(Point_3(1,1,1), Vector_3(2,2,2))); + assert(pv_pairs[1] == std::make_pair(Point_3(3,3,3), Vector_3(4,4,4))); + assert(pv_pairs[2] == std::make_pair(Point_3(5,5,5), Vector_3(6,6,6))); + pv_pairs.clear (); assert(read_ply("data/read_test/simple_ascii.ply", pv_pairs)); + assert(pv_pairs[0] == std::make_pair(Point_3(1,1,1), Vector_3(2,2,2))); + assert(pv_pairs[1] == std::make_pair(Point_3(3,3,3), Vector_3(4,4,4))); + assert(pv_pairs[2] == std::make_pair(Point_3(5,5,5), Vector_3(6,6,6))); + pv_pairs.clear (); assert(read_ply("data/read_test/simple_with_flag.ply", pv_pairs)); + assert(pv_pairs[0] == std::make_pair(Point_3(1,1,1), Vector_3(2,2,2))); + assert(pv_pairs[1] == std::make_pair(Point_3(3,3,3), Vector_3(4,4,4))); + assert(pv_pairs[2] == std::make_pair(Point_3(5,5,5), Vector_3(6,6,6))); return 0; } From 7a0134fc554bb351e3fef271c65bb7c88f36289b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 08:59:29 +0200 Subject: [PATCH 19/24] Update changes.html --- Installation/changes.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/changes.html b/Installation/changes.html index e2a4fca19e3..18327ca5839 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -154,6 +154,10 @@ and src/ directories). or CGAL::Parallel_tag when calling one of these functions.
  • CGAL::Parallel_tag can no longer be used in Point Set Processing algorithms if TBB is not available.
  • +
  • New IO functions for PLY format (Polygon File + Format): CGAL::read_ply_points(), + CGAL::read_ply_points_and_normals(), CGAL::write_ply_points() + and CGAL::write_ply_points_and_normals().
  • Surface Mesh Parameterization

      From eb430e2397a26f73bf6250d4d4b60864ce25190a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 09:24:35 +0200 Subject: [PATCH 20/24] Harmonize template indentation and remove outdated header --- .../include/CGAL/IO/write_ply_points.h | 50 +++++-------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h index 004ac2f9db1..e3d94183354 100644 --- a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h @@ -1,22 +1,3 @@ -// Copyright (c) 2007-09 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// -// Author(s) : Pierre Alliez and Laurent Saboret - #ifndef CGAL_WRITE_PLY_POINTS_H #define CGAL_WRITE_PLY_POINTS_H @@ -52,11 +33,10 @@ namespace CGAL { /// @return true on success. // This variant requires all parameters. -template +template < typename ForwardIterator, + typename PointPMap, + typename NormalPMap, + typename Kernel > bool write_ply_points_and_normals( std::ostream& stream, ///< output stream. @@ -110,10 +90,9 @@ write_ply_points_and_normals( /// @cond SKIP_IN_MANUAL // This variant deduces the kernel from the point property map. -template +template < typename ForwardIterator, + typename PointPMap, + typename NormalPMap > bool write_ply_points_and_normals( std::ostream& stream, ///< output stream. @@ -172,10 +151,9 @@ write_ply_points_and_normals( /// @return true on success. // This variant requires all parameters. -template +template < typename ForwardIterator, + typename PointPMap, + typename Kernel > bool write_ply_points( std::ostream& stream, ///< output stream. @@ -221,9 +199,8 @@ write_ply_points( /// @cond SKIP_IN_MANUAL // This variant deduces the kernel from the point property map. -template +template < typename ForwardIterator, + typename PointPMap > bool write_ply_points( std::ostream& stream, ///< output stream. @@ -243,8 +220,7 @@ write_ply_points( /// @cond SKIP_IN_MANUAL // This variant creates a default point property map = Identity_property_map. -template +template < typename ForwardIterator > bool write_ply_points( std::ostream& stream, ///< output stream. From 833982a32f2905a936d70703e82f878385780e9e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 09:52:45 +0200 Subject: [PATCH 21/24] Use boost fixed-width integer types for portability (and remove hack for reading ASCII 'char') --- .../include/CGAL/IO/read_ply_points.h | 39 ++++--------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index aa9f17054e4..f51ed296ee9 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -6,6 +6,7 @@ #include #include +#include #if BOOST_VERSION >= 104000 #include #else @@ -49,37 +50,13 @@ namespace internal { virtual double operator() (std::istream& stream) const = 0; - - // The two following functions prevent the stream to only extract - // ONE character (= what the types char imply) by requiring - // explicitely an integer object when reading the stream - void read_ascii (std::istream& stream, char& c) const - { - short s; - stream >> s; - c = static_cast(s); - } - void read_ascii (std::istream& stream, unsigned char& c) const - { - unsigned short s; - stream >> s; - c = static_cast(s); - } - - // Default template when Type is not a char type - template - void read_ascii (std::istream& stream, Type& t) const - { - stream >> t; - } - template Type read (std::istream& stream) const { if (m_format == 0) // Ascii { Type t; - read_ascii (stream, t); + stream >> t; return t; } else // Binary (2 = little endian) @@ -114,42 +91,42 @@ namespace internal { public: Ply_read_char (std::string name, std::size_t format) : Ply_read_number (name, format) { } double operator() (std::istream& stream) const - { return static_cast (this->read (stream)); } + { return static_cast (this->read (stream)); } }; class Ply_read_uchar : public Ply_read_number { public: Ply_read_uchar (std::string name, std::size_t format) : Ply_read_number (name, format) { } double operator() (std::istream& stream) const - { return static_cast (this->read (stream)); } + { return static_cast (this->read (stream)); } }; class Ply_read_short : public Ply_read_number { public: Ply_read_short (std::string name, std::size_t format) : Ply_read_number (name, format) { } double operator() (std::istream& stream) const - { return static_cast (this->read (stream)); } + { return static_cast (this->read (stream)); } }; class Ply_read_ushort : public Ply_read_number { public: Ply_read_ushort (std::string name, std::size_t format) : Ply_read_number (name, format) { } double operator() (std::istream& stream) const - { return static_cast (this->read (stream)); } + { return static_cast (this->read (stream)); } }; class Ply_read_int : public Ply_read_number { public: Ply_read_int (std::string name, std::size_t format) : Ply_read_number (name, format) { } double operator() (std::istream& stream) const - { return static_cast (this->read (stream)); } + { return static_cast (this->read (stream)); } }; class Ply_read_uint : public Ply_read_number { public: Ply_read_uint (std::string name, std::size_t format) : Ply_read_number (name, format) { } double operator() (std::istream& stream) const - { return static_cast (this->read (stream)); } + { return static_cast (this->read (stream)); } }; class Ply_read_float : public Ply_read_number { From f614ce4ea190a26ff3fe9810765daa3eab966182 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 10:00:39 +0200 Subject: [PATCH 22/24] Remove useless includes --- Point_set_processing_3/include/CGAL/IO/read_ply_points.h | 5 ----- Point_set_processing_3/include/CGAL/IO/write_ply_points.h | 5 ----- 2 files changed, 10 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index f51ed296ee9..7e34442ec27 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -7,11 +7,6 @@ #include #include -#if BOOST_VERSION >= 104000 -#include -#else -#include -#endif #include #include diff --git a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h index e3d94183354..cbe1236533e 100644 --- a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h @@ -5,11 +5,6 @@ #include #include -#if BOOST_VERSION >= 104000 - #include -#else - #include -#endif #include #include From 39eef6184780e053c15ae4f4f6ca462a7ad379b8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 10:08:39 +0200 Subject: [PATCH 23/24] Add headers --- .../include/CGAL/IO/read_ply_points.h | 19 +++++++++++++++++++ .../include/CGAL/IO/write_ply_points.h | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 7e34442ec27..863d91a5157 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -1,3 +1,22 @@ +// Copyright (c) 2015 Geometry Factory +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Simon Giraudot + #ifndef CGAL_READ_PLY_POINTS_H #define CGAL_READ_PLY_POINTS_H diff --git a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h index cbe1236533e..274713ec6a6 100644 --- a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h @@ -1,3 +1,22 @@ +// Copyright (c) 2015 Geometry Factory +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Simon Giraudot + #ifndef CGAL_WRITE_PLY_POINTS_H #define CGAL_WRITE_PLY_POINTS_H From 09d2c9e5a4d5626db4cfdac221681a4193a0fce8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 8 Oct 2015 10:18:16 +0200 Subject: [PATCH 24/24] Revert removal of hack to handle char properly (std::stream treats boost::int8_t as char) --- .../include/CGAL/IO/read_ply_points.h | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 863d91a5157..ad772f205c9 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -64,13 +64,36 @@ namespace internal { virtual double operator() (std::istream& stream) const = 0; + // The two following functions prevent the stream to only extract + // ONE character (= what the types char imply) by requiring + // explicitely an integer object when reading the stream + void read_ascii (std::istream& stream, boost::int8_t& c) const + { + short s; + stream >> s; + c = static_cast(s); + } + void read_ascii (std::istream& stream, boost::uint8_t& c) const + { + unsigned short s; + stream >> s; + c = static_cast(s); + } + + // Default template when Type is not a char type + template + void read_ascii (std::istream& stream, Type& t) const + { + stream >> t; + } + template Type read (std::istream& stream) const { if (m_format == 0) // Ascii { Type t; - stream >> t; + read_ascii (stream, t); return t; } else // Binary (2 = little endian) @@ -347,7 +370,6 @@ bool read_ply_points_and_normals(std::istream& stream, ///< input stream. } Point point(x,y,z); Vector normal(nx,ny,nz); - Enriched_point pwn; #ifdef CGAL_USE_PROPERTY_MAPS_API_V1