Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
2d72f21
IO: read_PLY() for Epeck
afabri Nov 20, 2023
40dee7d
whitespace
afabri Nov 20, 2023
5eb9344
Fix ascii output
afabri Nov 22, 2023
d876fba
add missing include
sloriot Nov 22, 2023
7a98410
Add code that shows the issue
afabri Jun 7, 2024
fe86a79
Fix the test
afabri Jun 7, 2024
6cba601
WIP just to get it working
afabri Jun 7, 2024
c58286d
Add #include
afabri Jun 7, 2024
710666a
Use the normal computation function that uses approximate_sqrt
MaelRL Jun 10, 2024
c5a6885
Test the write output
MaelRL Jun 10, 2024
cfcc90d
Add extra lines to clarify that the blocks aren't related
MaelRL Jun 10, 2024
969062e
Add the possibility to pass a vertex normal map
afabri Jun 11, 2024
a08388c
Also write normals in the generic code
afabri Jun 11, 2024
ba87b5c
typename
afabri Jun 11, 2024
a316b67
Merge remote-tracking branch 'cgal/master' into IO-read_PLY_Epeck-GF
afabri Jun 11, 2024
7ab9468
typename
afabri Jun 11, 2024
0e27e76
cleanup
afabri Jun 11, 2024
0501437
Add doxygen
afabri Jun 11, 2024
5171477
Fix tests
afabri Jun 17, 2024
5103fb4
merge
afabri Sep 26, 2025
b97c4b7
Convert on the fly to double
afabri Sep 29, 2025
3567ba1
Fix plugin
afabri Sep 29, 2025
3be4ffc
Fix plugin
afabri Sep 29, 2025
e652a79
fix doxygen warning
afabri Sep 29, 2025
33bd58b
fix doxygen warning
afabri Sep 30, 2025
89ba13f
fix doxygen warning
afabri Sep 30, 2025
36b6694
after Mael's review
afabri Sep 30, 2025
0a743e6
Document named parameter verbose
afabri Sep 30, 2025
737079e
Fix warning
afabri Oct 1, 2025
9a99df4
Comment static_assert
afabri Oct 1, 2025
39531ba
Use has_vnormal
afabri Oct 2, 2025
2402442
use constexpr
sloriot Oct 2, 2025
865c1d2
Fix error in test case
afabri Oct 6, 2025
878ba3f
suggestions from Mael
sloriot Oct 17, 2025
3706528
Update Stream_support/include/CGAL/IO/PLY/PLY_writer.h
afabri Oct 17, 2025
da011b2
No longer #if 0
afabri Oct 17, 2025
98a3051
copy style
afabri Oct 17, 2025
d9ba43a
Make it constexpr to avoid error in CI
afabri Oct 17, 2025
00f5ae0
Use Simple_cartesian<Exact_rational>
afabri Oct 30, 2025
35613b9
Deal with generic version
afabri Oct 30, 2025
622b652
Add to BGL dependencies
afabri Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 131 additions & 9 deletions BGL/include/CGAL/boost/graph/IO/PLY.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <CGAL/boost/graph/IO/Generic_facegraph_builder.h>
#include <CGAL/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

#include <fstream>
#include <string>
Expand All @@ -44,27 +45,30 @@ class PLY_builder
typedef typename Base::Face_container Face_container;

public:
PLY_builder(std::istream& is) : Base(is) { }
PLY_builder(std::istream& is, std::string& comments) : Base(is), comments(comments) { }

template <typename NamedParameters>
bool read(std::istream& is,
Point_container& points,
Face_container& faces,
const NamedParameters& np)
{
return read_PLY(is, points, faces, np);
return read_PLY(is, points, faces, comments, np);
}

std::string& comments;
};

template <typename Graph, typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY_BGL(std::istream& is,
Graph& g,
std::string& comments,
const CGAL_NP_CLASS& np = parameters::default_values())
{
typedef typename CGAL::GetVertexPointMap<Graph, CGAL_NP_CLASS>::type VPM;
typedef typename boost::property_traits<VPM>::value_type Point;

internal::PLY_builder<Graph, Point> builder(is);
internal::PLY_builder<Graph, Point> builder(is, comments);
return builder(g, np);
}

Expand All @@ -84,6 +88,7 @@ bool read_PLY_BGL(std::istream& is,

\param is the input stream
\param g the graph to be built from the input data
\param comments a string included line by line in the header of the PLY stream (each line will be precedeed by "comment ")
\param np optional \ref bgl_namedparameters "Named Parameters" described below

\cgalNamedParamsBegin
Expand Down Expand Up @@ -128,6 +133,20 @@ bool read_PLY_BGL(std::istream& is,

\sa Overloads of this function for specific models of the concept `FaceGraph`.
*/
template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(std::istream& is,
Graph& g,
std::string& comments,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
#endif
)
{
return internal::read_PLY_BGL(is, g, comments, np);
}

template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(std::istream& is,
Expand All @@ -138,9 +157,11 @@ bool read_PLY(std::istream& is,
#endif
)
{
return internal::read_PLY_BGL(is, g, np);
std::string unused_comments;
return internal::read_PLY_BGL(is, g, unused_comments, np);
}


/*!
\ingroup PkgBGLIoFuncsPLY

Expand All @@ -153,6 +174,7 @@ bool read_PLY(std::istream& is,

\param fname the name of the input file
\param g the graph to be built from the input data
\param comments a string included line by line in the header of the PLY stream (each line will be precedeed by "comment" )
\param np optional \ref bgl_namedparameters "Named Parameters" described below

\cgalNamedParamsBegin
Expand Down Expand Up @@ -207,6 +229,7 @@ template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(const std::string& fname,
Graph& g,
std::string& comments,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
Expand All @@ -218,16 +241,29 @@ bool read_PLY(const std::string& fname,
{
std::ifstream is(fname, std::ios::binary);
CGAL::IO::set_mode(is, CGAL::IO::BINARY);
return internal::read_PLY_BGL(is, g, np);
return read_PLY(is, g, comments, np);
}
else
{
std::ifstream is(fname);
CGAL::IO::set_mode(is, CGAL::IO::ASCII);
return internal::read_PLY_BGL(is, g, np);
return read_PLY(is, g, comments, np);
}
}

template <typename Graph,
typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_PLY(const std::string& fname,
Graph& g,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, std::enable_if_t<!internal::is_Point_set_or_Range_or_Iterator<Graph>::value>* = nullptr
#endif
)
{
std::string unused_comment;
return read_PLY(fname, g, unused_comment, np);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Write
Expand Down Expand Up @@ -259,6 +295,15 @@ bool read_PLY(const std::string& fname,
must be available in `Graph`.}
\cgalParamNEnd

\cgalParamNBegin{vertex_normal_map}
\cgalParamDescription{a property map associating normals to the vertices of `g`}
\cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
as key type and `%Vector_3` as value type}
\cgalParamDefault{`boost::get(CGAL::vertex_point, g)`}
\cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
must be available in `Graph`.}
\cgalParamNEnd

\cgalParamNBegin{vertex_index_map}
\cgalParamDescription{a property map associating to each vertex of `graph` a unique index}
\cgalParamType{a class model of `WritablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
Expand Down Expand Up @@ -326,6 +371,8 @@ bool write_PLY(std::ostream& os,

bool has_vcolor = !is_default_parameter<CGAL_NP_CLASS, internal_np::vertex_color_map_t>::value;
bool has_fcolor = !is_default_parameter<CGAL_NP_CLASS, internal_np::face_color_map_t>::value;
constexpr bool has_vnormal = !is_default_parameter<CGAL_NP_CLASS, internal_np::vertex_normal_map_t>::value;

VIMap vim = CGAL::get_initialized_vertex_index_map(g, np);
Vpm vpm = choose_parameter(get_parameter(np, internal_np::vertex_point),
get_const_property_map(boost::vertex_point, g));
Expand All @@ -351,8 +398,20 @@ bool write_PLY(std::ostream& os,
}
}


os << "element vertex " << vertices(g).size() << std::endl;
internal::output_property_header(os, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
if constexpr (std::is_same<typename Kernel_traits<Point_3>::Kernel::FT, float>::value)
{
internal::output_property_header(os, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
}
else
{
typedef typename Kernel_traits<Point_3>::Kernel K;
typedef decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Point_3>())) Target_point;
auto fvpm = CGAL::make_cartesian_converter_property_map<Target_point>(vpm);
internal::output_property_header(os, make_ply_point_writer (fvpm));
}

//if vcm is not default add v:color property
if(has_vcolor)
{
Expand All @@ -362,10 +421,30 @@ bool write_PLY(std::ostream& os,
<< "property uchar alpha" << std::endl;
}

if constexpr (has_vnormal)
{
auto vnm = get_parameter(np, internal_np::vertex_normal_map);
typedef decltype(vnm) Normal_map;
typedef typename Normal_map::value_type Vector_3;
typedef typename Kernel_traits<Vector_3>::Kernel K;
typedef typename K::FT FT;
if constexpr (std::is_same<FT, float>::value)
{
internal::output_property_header(os, make_ply_normal_writer (CGAL::Identity_property_map<Vector_3>()));
}
else
{
typedef decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Vector_3>())) Target_vector;
auto fvnm = CGAL::make_cartesian_converter_property_map<Target_vector>(vnm);
internal::output_property_header(os, make_ply_normal_writer (fvnm));
}
}

os << "element face " << faces(g).size() << std::endl;
internal::output_property_header(
os, std::make_pair(CGAL::Identity_property_map<std::vector<std::size_t> >(),
PLY_property<std::vector<int> >("vertex_indices")));

//if fcm is not default add f:color property
if(has_fcolor)
{
Expand All @@ -378,8 +457,42 @@ bool write_PLY(std::ostream& os,

for(vertex_descriptor vd : vertices(g))
{
const Point_3& p = get(vpm, vd);
internal::output_properties(os, &p, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
if constexpr (std::is_same<typename Kernel_traits<Point_3>::Kernel::FT, float>::value)
{
decltype(auto) p = get(vpm, vd);
internal::output_properties(os, &p, make_ply_point_writer (CGAL::Identity_property_map<Point_3>()));
}
else
{
typedef typename Kernel_traits<Point_3>::Kernel K;
typedef CGAL::cpp20::remove_cvref_t<decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Point_3>()))> Target_point;
CGAL::Cartesian_converter_property_map<Target_point, Vpm> fvpm = CGAL::make_cartesian_converter_property_map<Target_point>(vpm);
decltype(auto) fp = get(fvpm, vd);
internal::output_properties(os, &fp, make_ply_point_writer (CGAL::Identity_property_map<Target_point>()));
}

std::cout << "using generic writer" << std::endl;

if constexpr (!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::vertex_normal_map_t>::value)
{
auto vnm = get_parameter(np, internal_np::vertex_normal_map);
typedef decltype(vnm) Normal_map;
typedef typename Normal_map::value_type Vector_3;

if constexpr (std::is_same<typename Kernel_traits<Vector_3>::Kernel::FT, float>::value)
{
decltype(auto) vec = get(vnm,vd);
internal::output_properties(os, &vec, make_ply_normal_writer (CGAL::Identity_property_map<Vector_3>()));
}
else
{
typedef typename Kernel_traits<Vector_3>::Kernel K;
typedef CGAL::cpp20::remove_cvref_t<decltype(std::declval<CGAL::Cartesian_converter<K, Epick> >().operator()(std::declval<Vector_3>()))> Target_vector;
auto fvnm = CGAL::make_cartesian_converter_property_map<Target_vector>(vnm);
decltype(auto) fvec = get(fvnm, vd);
internal::output_properties(os, &fvec, make_ply_normal_writer (CGAL::Identity_property_map<Target_vector>()));
}
}
if(has_vcolor)
{
const CGAL::IO::Color& c = get(vcm, vd);
Expand Down Expand Up @@ -455,6 +568,15 @@ bool write_PLY(std::ostream& os, const Graph& g, const CGAL_NP_CLASS& np = param
must be available in `Graph`.}
\cgalParamNEnd

\cgalParamNBegin{vertex_normal_map}
\cgalParamDescription{a property map associating normals to the vertices of `g`}
\cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
as key type and `%Vector_3` as value type}
\cgalParamDefault{`boost::get(CGAL::vertex_point, g)`}
\cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t`
must be available in `Graph`.}
\cgalParamNEnd

\cgalParamNBegin{vertex_index_map}
\cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`}
\cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits<Graph>::%vertex_descriptor`
Expand Down
7 changes: 7 additions & 0 deletions BGL/package_info/BGL/dependencies
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
Algebraic_foundations
Arithmetic_kernel
BGL
Cartesian_kernel
Circulator
Distance_2
Distance_3
Filtered_kernel
Homogeneous_kernel
Hash_map
Installation
Intersections_2
Intersections_3
Interval_support
Kernel_23
Kernel_d
Modular_arithmetic
Number_types
Profiling_tools
Property_map
Random_numbers
STL_Extension
Stream_support
CGAL_Core
4 changes: 3 additions & 1 deletion Lab/demo/Lab/Plugins/IO/PLY_io_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <CGAL/Three/CGAL_Lab_io_plugin_interface.h>
#include <CGAL/Surface_mesh/IO/PLY.h>
#include <CGAL/Three/Three.h>
#include <CGAL/use.h>

#include <QInputDialog>
#include <QApplication>
Expand Down Expand Up @@ -132,8 +133,9 @@ load(QFileInfo fileinfo, bool& ok, bool add_to_scene) {
std::vector<CGAL::IO::Color> fcolors;
std::vector<CGAL::IO::Color> vcolors;

if (!(CGAL::IO::read_PLY (in, points, polygons, fcolors, vcolors)))
if (!(CGAL::IO::read_PLY (in, points, polygons, comments, fcolors, vcolors)))
{
CGAL_USE(comments);
QApplication::restoreOverrideCursor();
ok = false;
return QList<Scene_item*>();
Expand Down
1 change: 0 additions & 1 deletion Property_map/include/CGAL/property_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,6 @@ struct Cartesian_converter_property_map
{
return CGAL::Cartesian_converter<K1, K2>()(get(pm.vpm, k));
}

friend void put(Cartesian_converter_property_map<GeomObject, Vpm>& pm, const key_type& k, const value_type& v)
{
put(pm.vpm, k, CGAL::Cartesian_converter<K2, K1>()(v));
Expand Down
18 changes: 9 additions & 9 deletions Stream_support/doc/Stream_support/IOstream.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,25 @@ bool is_pretty(std::ios& s);
\subsection IOstreamInput Input Operator

\cgal defines input operators for classes that are derived
from the class `istream`. This allows to read from istreams
from the class `std::istream`. This allows to read from istreams
as `std::cin`, as well as from `std::istringstream` and `std::ifstream`.
The input operator is defined for all classes in the \cgal `Kernel`.
Let `is` be an input stream.

\code{.cpp}
// Extracts object `c` from the stream `is`. Returns `is`.
istream& operator>>(istream& is, Class c);
istream& operator>>(istream& is, Class& c);
\endcode

\code{.cpp}
#include <iostream>
#include <fstream>

#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Segment_2.h>

typedef CGAL::Point_2< CGAL::Cartesian<double> > Point;
typedef CGAL::Segment_2< CGAL::Cartesian<double> > Segment;
typedef CGAL::Point_2< CGAL::Simple_cartesian<double> > Point;
typedef CGAL::Segment_2< CGAL::Simple_cartesian<double> > Segment;

int
main()
Expand All @@ -123,7 +123,7 @@ main()
CGAL::IO::set_ascii_mode(std::cin);
std::cin >> p >> q;

std::ifstream f("data.txt");
std::ifstream f("data.txt", std::ios::binary);
CGAL::IO::set_binary_mode(f);
f >> s >> p;

Expand All @@ -150,11 +150,11 @@ ostream& operator<<(ostream& os, Class c);
#include <iostream>
#include <fstream>

#include <CGAL/Cartesian.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Segment_2.h>

typedef CGAL::Point_2< CGAL::Cartesian<double> > Point;
typedef CGAL::Segment_2< CGAL::Cartesian<double> > Segment;
typedef CGAL::Point_2< CGAL::Simple_cartesian<double> > Point;
typedef CGAL::Segment_2< CGAL::Simple_cartesian<double> > Segment;

int main()
{
Expand Down
Loading