mirror of https://github.com/CGAL/cgal
Merge branch 'Point_set_processing_3-IO_ply-GF-old' into Point_set_processing_3-IO_ply-GF
This commit is contained in:
commit
99d4fc84bd
|
|
@ -161,6 +161,10 @@ and <code>src/</code> directories).
|
||||||
automatically adapt the local density of points to the local
|
automatically adapt the local density of points to the local
|
||||||
variation of the input computed by principal component analysis.
|
variation of the input computed by principal component analysis.
|
||||||
</li>
|
</li>
|
||||||
|
<li> New IO functions for PLY format (Polygon File
|
||||||
|
Format): <code>CGAL::read_ply_points()</code>,
|
||||||
|
<code>CGAL::read_ply_points_and_normals()</code>, <code>CGAL::write_ply_points()</code>
|
||||||
|
and <code>CGAL::write_ply_points_and_normals()</code>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>Surface Mesh Parameterization</h3>
|
<h3>Surface Mesh Parameterization</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
## Functions ##
|
## Functions ##
|
||||||
|
|
||||||
- `CGAL::read_off_points()`
|
- `CGAL::read_off_points()`
|
||||||
|
- `CGAL::read_ply_points()`
|
||||||
- `CGAL::read_xyz_points()`
|
- `CGAL::read_xyz_points()`
|
||||||
- `CGAL::compute_average_spacing()`
|
- `CGAL::compute_average_spacing()`
|
||||||
- `CGAL::remove_outliers()`
|
- `CGAL::remove_outliers()`
|
||||||
|
|
@ -42,6 +43,7 @@
|
||||||
- `CGAL::vcm_estimate_normals()`
|
- `CGAL::vcm_estimate_normals()`
|
||||||
- `CGAL::vcm_is_on_feature_edge()`
|
- `CGAL::vcm_is_on_feature_edge()`
|
||||||
- `CGAL::write_off_points()`
|
- `CGAL::write_off_points()`
|
||||||
|
- `CGAL::write_ply_points()`
|
||||||
- `CGAL::write_xyz_points()`
|
- `CGAL::write_xyz_points()`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,19 @@ a property map.
|
||||||
We provide functions to read and write sets of points or sets of
|
We provide functions to read and write sets of points or sets of
|
||||||
points with normals from the following ASCII file formats: XYZ (three
|
points with normals from the following ASCII file formats: XYZ (three
|
||||||
point coordinates `x y z` per line or three point coordinates and
|
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
|
three normal vector coordinates `x y z nx ny nz` per line), OFF
|
||||||
(%Object File Format) \cgalCite{cgal:p-gmgv16-96}.
|
(%Object File Format) \cgalCite{cgal:p-gmgv16-96} and PLY (Polygon
|
||||||
|
File Format).
|
||||||
|
|
||||||
- `read_xyz_points()`
|
- `read_xyz_points()`
|
||||||
- `read_off_points()`
|
- `read_off_points()`
|
||||||
|
- `read_ply_points()`
|
||||||
- `write_off_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
|
\subsection Point_set_processing_3Example Example
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,615 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
#include <CGAL/property_map.h>
|
||||||
|
#include <CGAL/value_type_traits.h>
|
||||||
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
|
|
||||||
|
#include <boost/version.hpp>
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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<char>(s);
|
||||||
|
}
|
||||||
|
void read_ascii (std::istream& stream, boost::uint8_t& c) const
|
||||||
|
{
|
||||||
|
unsigned short s;
|
||||||
|
stream >> s;
|
||||||
|
c = static_cast<unsigned char>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default template when Type is not a char type
|
||||||
|
template <typename Type>
|
||||||
|
void read_ascii (std::istream& stream, Type& t) const
|
||||||
|
{
|
||||||
|
stream >> t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
Type read (std::istream& stream) const
|
||||||
|
{
|
||||||
|
if (m_format == 0) // Ascii
|
||||||
|
{
|
||||||
|
Type t;
|
||||||
|
read_ascii (stream, t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
else // Binary (2 = little endian)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char uChar[sizeof (Type)];
|
||||||
|
Type type;
|
||||||
|
} buffer;
|
||||||
|
|
||||||
|
std::size_t size = sizeof (Type);
|
||||||
|
|
||||||
|
stream.read(buffer.uChar, size);
|
||||||
|
|
||||||
|
if (m_format == 2) // Big endian
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < size / 2; ++ i)
|
||||||
|
{
|
||||||
|
unsigned char tmp = buffer.uChar[i];
|
||||||
|
buffer.uChar[i] = buffer.uChar[size - 1 - i];
|
||||||
|
buffer.uChar[size - 1 - i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.type;
|
||||||
|
}
|
||||||
|
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<double> (this->read<boost::int8_t> (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<double> (this->read<boost::uint8_t> (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<double> (this->read<boost::int16_t> (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<double> (this->read<boost::uint16_t> (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<double> (this->read<boost::int32_t> (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<double> (this->read<boost::uint32_t> (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<double> (this->read<float> (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<float> (stream); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
//===================================================================================
|
||||||
|
/// \ingroup PkgPointSetProcessing
|
||||||
|
/// 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<OutputIterator>::%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<Kernel>`.
|
||||||
|
/// It can be omitted if the value type of `OutputIterator` is convertible to `Point_3<Kernel>`.
|
||||||
|
/// @tparam NormalPMap is a model of `WritablePropertyMap` with value type `Vector_3<Kernel>`.
|
||||||
|
/// @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.
|
||||||
|
{
|
||||||
|
// value_type_traits is a workaround as back_insert_iterator's value_type is void
|
||||||
|
// typedef typename value_type_traits<OutputIterator>::type Enriched_point;
|
||||||
|
typedef OutputIteratorValueType Enriched_point;
|
||||||
|
|
||||||
|
typedef typename Kernel::Point_3 Point;
|
||||||
|
typedef typename Kernel::Vector_3 Vector;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
|
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 = 0, BINARY_LITTLE_ENDIAN = 1, BINARY_BIG_ENDIAN = 2};
|
||||||
|
Format format = ASCII;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::istringstream iss;
|
||||||
|
|
||||||
|
// Check the order of the properties of the point set
|
||||||
|
bool reading_properties = false;
|
||||||
|
std::vector<internal::Ply_read_number*> readers;
|
||||||
|
|
||||||
|
while (getline (stream,line))
|
||||||
|
{
|
||||||
|
iss.clear();
|
||||||
|
iss.str (line);
|
||||||
|
++ lineNumber;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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" || type == "int8")
|
||||||
|
readers.push_back (new internal::Ply_read_char (name, format));
|
||||||
|
else if (type == "uchar" || type == "uint8")
|
||||||
|
readers.push_back (new internal::Ply_read_uchar (name, format));
|
||||||
|
else if (type == "short" || type == "int16")
|
||||||
|
readers.push_back (new internal::Ply_read_short (name, format));
|
||||||
|
else if (type == "ushort" || type == "uint16")
|
||||||
|
readers.push_back (new internal::Ply_read_ushort (name, format));
|
||||||
|
else if (type == "int" || type == "int32")
|
||||||
|
readers.push_back (new internal::Ply_read_int (name, format));
|
||||||
|
else if (type == "uint" || type == "uint32")
|
||||||
|
readers.push_back (new internal::Ply_read_uint (name, format));
|
||||||
|
else if (type == "float" || type == "float32")
|
||||||
|
readers.push_back (new internal::Ply_read_float (name, format));
|
||||||
|
else if (type == "double" || type == "float64")
|
||||||
|
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;
|
||||||
|
|
||||||
|
// When end_header is reached, stop loop and begin reading points
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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
|
||||||
|
<typename value_type_traits<OutputIterator>::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<PointPMap>::value_type Point;
|
||||||
|
typedef typename Kernel_traits<Point>::Kernel Kernel;
|
||||||
|
return read_ply_points_and_normals
|
||||||
|
<OutputIteratorValueType>(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
|
||||||
|
<typename value_type_traits<OutputIterator>::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
|
||||||
|
<OutputIteratorValueType>(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
|
||||||
|
<typename value_type_traits<OutputIterator>::type>(stream,
|
||||||
|
output,
|
||||||
|
normal_pmap);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================================
|
||||||
|
/// \ingroup PkgPointSetProcessing
|
||||||
|
/// 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<OutputIterator>::%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<Kernel>`.
|
||||||
|
/// It can be omitted if the value type of `OutputIterator` is convertible to `Point_3<Kernel>`.
|
||||||
|
/// @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
|
||||||
|
<OutputIteratorValueType>(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
|
||||||
|
<typename value_type_traits<OutputIterator>::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<PointPMap>::value_type Point;
|
||||||
|
typedef typename Kernel_traits<Point>::Kernel Kernel;
|
||||||
|
return read_ply_points
|
||||||
|
<OutputIteratorValueType>(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
|
||||||
|
<typename value_type_traits<OutputIterator>::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
|
||||||
|
<OutputIteratorValueType>(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
|
||||||
|
<typename value_type_traits<OutputIterator>::type>(stream,
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_READ_PLY_POINTS_H
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
#include <CGAL/property_map.h>
|
||||||
|
#include <CGAL/point_set_processing_assertions.h>
|
||||||
|
|
||||||
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================================
|
||||||
|
/// \ingroup PkgPointSetProcessing
|
||||||
|
/// Saves the [first, beyond) range of points (positions + normals) to a .ply ASCII 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<Kernel>`.
|
||||||
|
/// It can be omitted if the value type of `ForwardIterator` is convertible to `Point_3<Kernel>`.
|
||||||
|
/// @tparam NormalPMap is a model of `ReadablePropertyMap` with a value type `Vector_3<Kernel>`.
|
||||||
|
/// @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 ForwardIterator,
|
||||||
|
typename PointPMap,
|
||||||
|
typename NormalPMap,
|
||||||
|
typename Kernel >
|
||||||
|
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
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
#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 < typename ForwardIterator,
|
||||||
|
typename PointPMap,
|
||||||
|
typename NormalPMap >
|
||||||
|
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<PointPMap>::value_type Point;
|
||||||
|
typedef typename Kernel_traits<Point>::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 <typename ForwardIterator,
|
||||||
|
typename NormalPMap
|
||||||
|
>
|
||||||
|
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<ForwardIterator>::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<Kernel>`.
|
||||||
|
/// It can be omitted if the value type of `ForwardIterator` is convertible to `Point_3<Kernel>`.
|
||||||
|
/// @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 ForwardIterator,
|
||||||
|
typename PointPMap,
|
||||||
|
typename Kernel >
|
||||||
|
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
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
#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 < typename ForwardIterator,
|
||||||
|
typename PointPMap >
|
||||||
|
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<PointPMap>::value_type Point;
|
||||||
|
typedef typename Kernel_traits<Point>::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 < typename ForwardIterator >
|
||||||
|
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<ForwardIterator>::value_type())
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/// @endcond
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_WRITE_PLY_POINTS_H
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
OFF
|
NOFF
|
||||||
3 0 0
|
3 0 0
|
||||||
1 1 1 2 2 2
|
1 1 1 2 2 2
|
||||||
3 3 3 4 4 4
|
3 3 3 4 4 4
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -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
|
||||||
Binary file not shown.
|
|
@ -2,6 +2,7 @@
|
||||||
#include <CGAL/Simple_cartesian.h>
|
#include <CGAL/Simple_cartesian.h>
|
||||||
#include <CGAL/property_map.h>
|
#include <CGAL/property_map.h>
|
||||||
#include <CGAL/IO/read_off_points.h>
|
#include <CGAL/IO/read_off_points.h>
|
||||||
|
#include <CGAL/IO/read_ply_points.h>
|
||||||
#include <CGAL/IO/read_xyz_points.h>
|
#include <CGAL/IO/read_xyz_points.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -47,6 +48,17 @@ bool read_off(std::string s,
|
||||||
CGAL::Second_of_pair_property_map<PointVectorPair>());
|
CGAL::Second_of_pair_property_map<PointVectorPair>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool read_ply (std::string s,
|
||||||
|
std::vector<PointVectorPair>& 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<PointVectorPair>(),
|
||||||
|
CGAL::Second_of_pair_property_map<PointVectorPair>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|
@ -78,6 +90,23 @@ int main()
|
||||||
assert(pv_pairs[2] == std::make_pair(Point_3(4,5,6), Vector_3(0,0,0)));
|
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(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));
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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)
|
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)
|
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)
|
target_link_libraries(convex_hull_plugin scene_polyhedron_item scene_points_with_normal_item scene_polylines_item scene_polyhedron_selection_item)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,14 +56,28 @@ Polyhedron_demo_off_to_xyz_plugin::load(QFileInfo fileinfo) {
|
||||||
return item;
|
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<const Scene_points_with_normal_item*>(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<const Scene_points_with_normal_item*>(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include "Scene_points_with_normal_item.h"
|
||||||
|
#include "Polyhedron_demo_io_plugin_interface.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
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* item)
|
||||||
|
{
|
||||||
|
// This plugin supports point sets
|
||||||
|
return qobject_cast<const Scene_points_with_normal_item*>(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Polyhedron_demo_ply_to_xyz_plugin::save(const Scene_item* item, QFileInfo fileinfo)
|
||||||
|
{
|
||||||
|
// 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<const Scene_points_with_normal_item*>(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "Polyhedron_demo_ply_to_xyz_plugin.moc"
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include "Polyhedron_type.h"
|
#include "Polyhedron_type.h"
|
||||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||||
|
|
||||||
|
#include <CGAL/IO/read_ply_points.h>
|
||||||
|
#include <CGAL/IO/write_ply_points.h>
|
||||||
#include <CGAL/IO/read_off_points.h>
|
#include <CGAL/IO/read_off_points.h>
|
||||||
#include <CGAL/IO/write_off_points.h>
|
#include <CGAL/IO/write_off_points.h>
|
||||||
#include <CGAL/IO/read_xyz_points.h>
|
#include <CGAL/IO/read_xyz_points.h>
|
||||||
|
|
@ -317,6 +319,45 @@ void Scene_points_with_normal_item::selectDuplicates()
|
||||||
Q_EMIT itemChanged();
|
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();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
// Loads point set from .OFF file
|
||||||
bool Scene_points_with_normal_item::read_off_point_set(std::istream& stream)
|
bool Scene_points_with_normal_item::read_off_point_set(std::istream& stream)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ public:
|
||||||
QMenu* contextMenu();
|
QMenu* contextMenu();
|
||||||
|
|
||||||
// IO
|
// 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 read_off_point_set(std::istream& in);
|
||||||
bool write_off_point_set(std::ostream& out) const;
|
bool write_off_point_set(std::ostream& out) const;
|
||||||
bool read_xyz_point_set(std::istream& in);
|
bool read_xyz_point_set(std::istream& in);
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ else
|
||||||
orient_soup_plugin \
|
orient_soup_plugin \
|
||||||
parameterization_plugin \
|
parameterization_plugin \
|
||||||
pca_plugin \
|
pca_plugin \
|
||||||
|
ply_to_xyz_plugin \
|
||||||
point_dialog \
|
point_dialog \
|
||||||
point_inside_polyhedron_plugin \
|
point_inside_polyhedron_plugin \
|
||||||
point_set_average_spacing_plugin \
|
point_set_average_spacing_plugin \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue