diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 883c1b3ad465..e058589c3bf4 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -482,6 +482,10 @@ the requirement for traversal of all faces in a graph. /// I/O Functions for the \ref IOStreamOBJ /// \ingroup PkgBGLIOFct +/// \defgroup PkgBGLIoFuncsOM OM I/O Functions +/// I/O Functions for the \ref IOStreamOM +/// \ingroup PkgBGLIOFct + /// \defgroup PkgBGLIoFuncsOFF OFF I/O Functions /// I/O Functions for the \ref IOStreamOFF /// \ingroup PkgBGLIOFct diff --git a/BGL/examples/BGL_OpenMesh/PolyMesh.cpp b/BGL/examples/BGL_OpenMesh/PolyMesh.cpp index 96d6feb252bb..f5a644bba7bd 100644 --- a/BGL/examples/BGL_OpenMesh/PolyMesh.cpp +++ b/BGL/examples/BGL_OpenMesh/PolyMesh.cpp @@ -24,25 +24,32 @@ int main(int argc, char** argv ) { OMesh omesh; - const std::string filename = (argc>1)?argv[1]:CGAL::data_file_path("meshes/in.off"); - const char* outname= (argc>2)?argv[2]:"out.om"; - CGAL::IO::read_polygon_mesh(filename, omesh); + const std::string filename = (argc>1)?argv[1]:CGAL::data_file_path("meshes/cube-meshed.off"); + + if (!CGAL::IO::read_polygon_mesh(filename, omesh)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } omesh.request_vertex_status(); omesh.request_edge_status(); int i = 0; - for(auto v : vertices(omesh)){ - omesh.status(v).set_selected((i%2) == 0); - ++i; + for(auto v : vertices(omesh)) + { + omesh.status(v).set_feature((i%2) == 0); + ++i; } i = 0; - for(auto eit = omesh.edges_begin(); eit != omesh.edges_end(); ++eit){ - omesh.status(*eit).set_feature(i > 2); - ++i; + for(auto eit = omesh.edges_begin(); eit != omesh.edges_end(); ++eit) + { + omesh.status(*eit).set_feature((i%2) == 0); + ++i; } + const char* outname= (argc>2)?argv[2]:"out.om"; OpenMesh::IO::write_mesh(omesh, outname, OpenMesh::IO::Options::Status); SM sm; @@ -53,16 +60,26 @@ int main(int argc, char** argv ) std::map sm_feature_map; auto sm_feature_pmap = boost::make_assoc_property_map(sm_feature_map); - CGAL::IO::read_OM(outname, sm, sm_selected_pmap, sm_feature_pmap); + CGAL::IO::read_OM(outname, sm, CGAL::parameters::vertex_is_constrained_map(sm_selected_pmap) + .edge_is_constrained_map(sm_feature_pmap)); - std::cout << "vertex selection values:\n"; + + int nbv=0, nbfv=0; for(auto v : vertices(sm)){ - std::cout << std::boolalpha << get(sm_selected_pmap, v) << std::endl; + ++nbv; + if (get(sm_selected_pmap, v)) ++nbfv; } + std::cout << nbfv << " feature vertices out of " << nbv << "\n"; - std::cout << "edge feature values:\n"; + int nbe=0, nbfe=0; for(auto e : edges(sm)){ - std::cout << std::boolalpha << get(sm_feature_pmap, e) << std::endl; + ++nbe; + if (get(sm_feature_pmap, e)) ++nbfe; } + std::cout << nbfe << " feature edges out of " << nbe << "\n"; + + assert(nbv>1 || nbfv!=0); + assert(nbe>1 || nbfe!=0); + return 0; } diff --git a/BGL/include/CGAL/boost/graph/IO/OM.h b/BGL/include/CGAL/boost/graph/IO/OM.h index c9a9f1f3ef32..aae313b34421 100644 --- a/BGL/include/CGAL/boost/graph/IO/OM.h +++ b/BGL/include/CGAL/boost/graph/IO/OM.h @@ -30,8 +30,9 @@ namespace CGAL { namespace IO { -template -bool read_OM(const std::string& fname, Graph& g, VFeaturePM vfpm, EFeaturePM efpm) +namespace internal { +template +bool read_OM(const std::string& fname, Graph& g, VPM vpm, VFeaturePM vfpm, EFeaturePM efpm) { typedef OpenMesh::PolyMesh_ArrayKernelT<> OMesh; typedef typename boost::graph_traits::vertex_descriptor om_vertex_descriptor; @@ -54,7 +55,8 @@ bool read_OM(const std::string& fname, Graph& g, VFeaturePM vfpm, EFeaturePM efp CGAL::copy_face_graph(omesh, g, CGAL::parameters::vertex_to_vertex_map(v2vpmap) - .halfedge_to_halfedge_map(h2hpmap)); + .halfedge_to_halfedge_map(h2hpmap), + CGAL::parameters::vertex_point_map(vpm)); if(options.vertex_has_status()){ for(auto v : vertices(omesh)){ put(vfpm, v2v[v], omesh.status(v).feature()); @@ -70,25 +72,8 @@ bool read_OM(const std::string& fname, Graph& g, VFeaturePM vfpm, EFeaturePM efp return true; } -template -bool read_OM(const std::string& fname, - Graph& g, - const CGAL_NP_CLASS& np = parameters::default_values()) -{ - using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; - using edge_descriptor = typename boost::graph_traits::edge_descriptor; - - using CGAL::parameters::get_parameter; - using CGAL::parameters::choose_parameter; - auto vfpm = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), - CGAL::Constant_property_map(false)); - auto efpm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - CGAL::Constant_property_map(false)); - return read_OM(fname, g, vfpm, efpm); -} - -template -bool write_OM(std::string fname, Graph& g, VFeaturePM vfpm, EFeaturePM efpm) +template +bool write_OM(std::string fname, Graph& g, VPM vpm, VFeaturePM vfpm, EFeaturePM efpm) { typedef OpenMesh::PolyMesh_ArrayKernelT<> OMesh; typedef typename boost::graph_traits::vertex_descriptor om_vertex_descriptor; @@ -104,8 +89,9 @@ bool write_OM(std::string fname, Graph& g, VFeaturePM vfpm, EFeaturePM efpm) OMesh omesh; CGAL::copy_face_graph(g, omesh, - CGAL::parameters::vertex_to_vertex_map(v2vpmap) - .halfedge_to_halfedge_map(h2hpmap)); + CGAL::parameters::vertex_point_map(vpm) + .vertex_to_vertex_map(v2vpmap) + .halfedge_to_halfedge_map(h2hpmap)); omesh.request_edge_status(); omesh.request_vertex_status(); @@ -124,7 +110,108 @@ bool write_OM(std::string fname, Graph& g, VFeaturePM vfpm, EFeaturePM efpm) return OpenMesh::IO::write_mesh(omesh, fname, OpenMesh::IO::Options::Status); } +} // end of internal namespace + +/*! + \ingroup PkgBGLIoFuncsOM + + \brief reads the graph `g` from the file `fname`, using the \ref IOStreamOM. + + The data is expected to represent a 2-manifold (possibly with borders). + + \attention The graph `g` is not cleared, and the data from the file are appended. + + \note This function is only available if OpenMesh is available (`CGAL_USE_OPENMESH` is defined or CMake target is linked with `CGAL::OpenMesh_support`). + + \tparam Graph a model of `MutableFaceGraph` + \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + + \param fname the name of the input file + \param g the graph to be built from the input data + \param np optional \ref bgl_namedparameters "Named Parameters" described below + + \cgalNamedParamsBegin + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{a property map associating points to the vertices of `g`} + \cgalParamType{a class model of `WritablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + as key type and `%Point_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{edge_is_constrained_map} + \cgalParamDescription{a property map containing the feature-or-not status of each edge of `g` to be filled by the reader} + \cgalParamType{a class model of `WritablePropertyMap` with `boost::graph_traits::%edge_descriptor` + as key type and `bool` as value type.} + \cgalParamDefault{a default property map where no edge is marked as feature} + \cgalParamNEnd + \cgalParamNBegin{vertex_is_constrained_map} + \cgalParamDescription{a property map containing the feature-or-not status of each vertex of `g` to be filled by the reader} + \cgalParamType{a class model of `WritablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + as key type and `bool` as value type.} + \cgalParamDefault{a default property map where no vertex is marked as feature} + \cgalParamNEnd + \cgalNamedParamsEnd + + \returns `true` if reading was successful and the resulting mesh is valid, `false` otherwise. +*/ +template +bool read_OM(const std::string& fname, + Graph& g, + const CGAL_NP_CLASS& np = parameters::default_values()) +{ + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + using edge_descriptor = typename boost::graph_traits::edge_descriptor; + + using CGAL::parameters::get_parameter; + using CGAL::parameters::choose_parameter; + using Default_vfmap = Static_boolean_property_map; + using Default_efmap = Static_boolean_property_map; + auto vfpm = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained)); + auto efpm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained)); + auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_property_map(vertex_point, g)); + return internal::read_OM(fname, g, vpm, vfpm, efpm); +} + +/*! +\ingroup PkgBGLIoFuncsOM + + \brief writes the graph `g` into a file named `fname`, using the \ref IOStreamOM. + + \note This function is only available if OpenMesh is available (`CGAL_USE_OPENMESH` is defined or CMake target is linked with `CGAL::OpenMesh_support`). + + \tparam Graph a model of `FaceListGraph` and `HalfedgeListGraph` + \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + + \param fname the output file + \param g the graph to be written + \param np optional \ref bgl_namedparameters "Named Parameters" described below + + \cgalNamedParamsBegin + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{a property map associating points to the vertices of `g`} + \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + as key type and `%Point_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{edge_is_constrained_map} + \cgalParamDescription{a property map containing the feature-or-not status of each edge of `g`} + \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%edge_descriptor` + as key type and `bool` as value type.} + \cgalParamNEnd + \cgalParamNBegin{vertex_is_constrained_map} + \cgalParamDescription{a property map containing the feature-or-not status of each vertex of `g`} + \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + as key type and `bool` as value type.} + \cgalParamNEnd + \cgalNamedParamsEnd + + \returns `true` if writing was successful, `false` otherwise. +*/ template bool write_OM(const std::string& fname, Graph& g, @@ -139,7 +226,9 @@ bool write_OM(const std::string& fname, CGAL::Constant_property_map(false)); auto efpm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), CGAL::Constant_property_map(false)); - return write_OM(fname, g, vfpm, efpm); + auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_property_map(vertex_point, g)); + return internal::write_OM(fname, g, vpm, vfpm, efpm); } diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index ad6b83dd31a1..c99b00c6e895 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 5badcf76a9c8..8f9a99e0877c 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -9,6 +9,7 @@ each specific format. - \ref IOStreamOFF - \ref IOStreamOBJ +- \ref IOStreamOM - \ref IOStreamSTL - \ref IOStreamPLY - \ref IOStreamXYZ @@ -141,6 +142,29 @@ If the data of a polygon mesh cannot be read in a `FaceGraph` due to bad orienta manifoldness issues, consider using \link PMP_IO_grp `CGAL::Polygon_mesh_processing::IO::read_polygon_mesh()` \endlink, which offers combinatorial repairing while reading bad inputs. +\section IOStreamOM OpenMesh (OM) File format +The OpenMesh proprietary format, using the file extension `.om`, can be used to represent collections of planar polygons with possibly shared vertices. +Additionally, it allows to store and restore custom properties along with the standard properties. + +More information are provided here. + + + + + + + + + + + + + + + + + +
OpenMesh Format (OM)
InputPolygon MeshAny model of `MutableFaceGraph`\link PkgBGLIoFuncsOM CGAL::IO::read_OM(const std::string&, Graph&)\endlink
OutputPolygon MeshAny model of `FaceGraph`\link PkgBGLIoFuncsOM CGAL::IO::write_OM(const std::string&, const Graph&)\endlink
\section IOStreamSTL STereoLithography (STL) File Format