diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 883c1b3ad46..e058589c3bf 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/CMakeLists.txt b/BGL/examples/BGL_OpenMesh/CMakeLists.txt index f461d55efb1..a5091363a51 100644 --- a/BGL/examples/BGL_OpenMesh/CMakeLists.txt +++ b/BGL/examples/BGL_OpenMesh/CMakeLists.txt @@ -12,6 +12,9 @@ if(OpenMesh_FOUND) include(CGAL_OpenMesh_support) create_single_source_cgal_program("TriMesh.cpp") target_link_libraries(TriMesh PRIVATE CGAL::OpenMesh_support) + create_single_source_cgal_program("PolyMesh.cpp") + target_link_libraries(PolyMesh PRIVATE CGAL::OpenMesh_support) + else() message("NOTICE: This project requires OpenMesh and will not be compiled.") endif() diff --git a/BGL/examples/BGL_OpenMesh/PolyMesh.cpp b/BGL/examples/BGL_OpenMesh/PolyMesh.cpp new file mode 100644 index 00000000000..f5a644bba7b --- /dev/null +++ b/BGL/examples/BGL_OpenMesh/PolyMesh.cpp @@ -0,0 +1,85 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include + + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + +typedef OpenMesh::PolyMesh_ArrayKernelT OMesh; +typedef CGAL::Surface_mesh SM; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; + +typedef boost::graph_traits::vertex_descriptor sm_vertex_descriptor; +typedef boost::graph_traits::edge_descriptor sm_edge_descriptor; + +int main(int argc, char** argv ) +{ + OMesh 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_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) == 0); + ++i; + } + + const char* outname= (argc>2)?argv[2]:"out.om"; + OpenMesh::IO::write_mesh(omesh, outname, OpenMesh::IO::Options::Status); + + SM sm; + + std::map sm_selected_map; + auto sm_selected_pmap = boost::make_assoc_property_map(sm_selected_map); + + std::map sm_feature_map; + auto sm_feature_pmap = boost::make_assoc_property_map(sm_feature_map); + + CGAL::IO::read_OM(outname, sm, CGAL::parameters::vertex_is_constrained_map(sm_selected_pmap) + .edge_is_constrained_map(sm_feature_pmap)); + + + int nbv=0, nbfv=0; + for(auto v : vertices(sm)){ + ++nbv; + if (get(sm_selected_pmap, v)) ++nbfv; + } + std::cout << nbfv << " feature vertices out of " << nbv << "\n"; + + int nbe=0, nbfe=0; + for(auto e : edges(sm)){ + ++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/examples/BGL_OpenMesh/TriMesh.cpp b/BGL/examples/BGL_OpenMesh/TriMesh.cpp index e474020cc67..f84a19762a8 100644 --- a/BGL/examples/BGL_OpenMesh/TriMesh.cpp +++ b/BGL/examples/BGL_OpenMesh/TriMesh.cpp @@ -1,17 +1,18 @@ #include -#include #include #include +#include + #include -#include #include + +#include #include -#include #include -#include + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; diff --git a/BGL/include/CGAL/IO/polygon_mesh_io.h b/BGL/include/CGAL/IO/polygon_mesh_io.h index 21f61087ab6..60a1e5520c5 100644 --- a/BGL/include/CGAL/IO/polygon_mesh_io.h +++ b/BGL/include/CGAL/IO/polygon_mesh_io.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,7 @@ bool read_polygon_mesh(std::istream& is, * Supported file formats are the following: * - \ref IOStreamOFF (`.off`) * - \ref IOStreamOBJ (`.obj`) + * - \ref IOStreamOM (`.om`) * - \ref IOStreamSTL (`.stl`) * - \ref IOStreamPLY (`.ply`) * - \ref IOStreamGocad (`.ts`) @@ -138,6 +140,10 @@ bool read_polygon_mesh(const std::string& fname, return read_OBJ(fname, g, np); else if(ext == "off") return read_OFF(fname, g, np); +#ifdef CGAL_USE_OPENMESH + else if(ext == "om") + return read_OM(fname, g, np); +#endif else if(ext == "ply") return read_PLY(fname, g, np); else if(ext == "stl") diff --git a/BGL/include/CGAL/boost/graph/IO/OM.h b/BGL/include/CGAL/boost/graph/IO/OM.h new file mode 100644 index 00000000000..9d393022a03 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/IO/OM.h @@ -0,0 +1,239 @@ +// Copyright (c) 2024 GeometryFactory +// +// This file is part of CGAL (www.cgal.org); +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri + +#ifndef CGAL_BGL_IO_OM_H +#define CGAL_BGL_IO_OM_H + +#if defined(CGAL_USE_OPENMESH) || defined(DOXYGEN_RUNNING) + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace CGAL { +namespace IO { + +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; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor om_halfedge_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + OMesh omesh; + OpenMesh::IO::Options options = OpenMesh::IO::Options::Status; + bool ok = OpenMesh::IO::read_mesh(omesh, fname, options); + if(! ok){ + return false; + } + + std::map v2v; + auto v2vpmap = boost::make_assoc_property_map(v2v); + + std::map h2h; + auto h2hpmap = boost::make_assoc_property_map(h2h); + + CGAL::copy_face_graph(omesh, g, + CGAL::parameters::vertex_to_vertex_map(v2vpmap) + .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()); + } + } + + if(options.edge_has_status()){ + for(auto e : edges(omesh)){ + auto sme = edge(h2h[halfedge(e,omesh)], g); + put(efpm, sme , omesh.status(OpenMesh::EdgeHandle(e.idx())).feature()); + } + } + return true; +} + +template +bool write_OM(std::string fname, const Graph& g, VPM vpm, VFeaturePM vfpm, EFeaturePM efpm) +{ + typedef OpenMesh::PolyMesh_ArrayKernelT<> OMesh; + typedef typename boost::graph_traits::vertex_descriptor om_vertex_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor om_halfedge_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + std::map v2v; + auto v2vpmap = boost::make_assoc_property_map(v2v); + + std::map h2h; + auto h2hpmap = boost::make_assoc_property_map(h2h); + + OMesh omesh; + CGAL::copy_face_graph(g, omesh, + CGAL::parameters::vertex_point_map(vpm) + .vertex_to_vertex_map(v2vpmap) + .halfedge_to_halfedge_map(h2hpmap)); + omesh.request_edge_status(); + omesh.request_vertex_status(); + + for (auto h : halfedges(g)) + { + om_halfedge_descriptor omh = h2h.at(h); + const bool isfeature = get(efpm, edge(h, g)); + omesh.status(omesh.edge_handle(omh)).set_feature(isfeature); + } + for (auto v : vertices(g)) + { + auto omv = v2v.at(v); + const bool isfeature = get(vfpm, v); + omesh.status(omv).set_feature(isfeature); + } + + 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, + const 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)); + auto vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, g)); + return internal::write_OM(fname, g, vpm, vfpm, efpm); +} + + +} // namespace IO +} // namespace CGAL + +#endif // CGAL_USE_OPENMESH || DOXYGEN_RUNNING +#endif // CGAL_IO_OM diff --git a/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h b/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h index 79f1199e24d..36a872737b1 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h @@ -9,7 +9,6 @@ // // Author(s) : Andreas Fabri, Philipp Moeller -// include this to avoid a VC15 warning #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/BGL/include/CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h b/BGL/include/CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h index 5127f692a24..dc7098520a6 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h @@ -11,11 +11,16 @@ #ifndef CGAL_BOOST_GRAPH_GRAPH_TRAITS_POLYMESH_ARRAYKERNELT_H #define CGAL_BOOST_GRAPH_GRAPH_TRAITS_POLYMESH_ARRAYKERNELT_H +#ifdef OPEN_MESH_CLASS + #error OPEN_MESH_CLASS is already defined +#endif + // https://www.graphics.rwth-aachen.de/media/openmesh_static/Documentations/OpenMesh-Doc-Latest/a02182.html #include #include #include + #define OPEN_MESH_CLASS OpenMesh::PolyMesh_ArrayKernelT #include diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index ad6b83dd31a..c99b00c6e89 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/Lab/demo/Lab/Plugins/IO/CMakeLists.txt b/Lab/demo/Lab/Plugins/IO/CMakeLists.txt index e7593258017..595f1bd6e42 100644 --- a/Lab/demo/Lab/Plugins/IO/CMakeLists.txt +++ b/Lab/demo/Lab/Plugins/IO/CMakeLists.txt @@ -47,6 +47,16 @@ target_link_libraries(surf_io_plugin PRIVATE scene_surface_mesh_item) cgal_lab_plugin(lcc_io_plugin lcc_io_plugin KEYWORDS Viewer) target_link_libraries(lcc_io_plugin PRIVATE scene_lcc_item) +find_package(OpenMesh QUIET) +if(OpenMesh_FOUND) + include(CGAL_OpenMesh_support) + cgal_lab_plugin(om_plugin OM_io_plugin KEYWORDS Viewer PMP) + target_link_libraries(om_plugin PUBLIC scene_surface_mesh_item scene_polygon_soup_item scene_selection_item) + target_link_libraries(om_plugin PRIVATE CGAL::OpenMesh_support) +else() + message(STATUS "NOTICE: the OM IO plugin needs OpenMesh libraries and will not be compiled.") +endif() + find_package(VTK 9.0 QUIET COMPONENTS CommonCore IOCore IOLegacy IOXML FiltersCore FiltersSources) set_package_properties( VTK PROPERTIES diff --git a/Lab/demo/Lab/Plugins/IO/OM_io_plugin.cpp b/Lab/demo/Lab/Plugins/IO/OM_io_plugin.cpp new file mode 100644 index 00000000000..286fdd5bc01 --- /dev/null +++ b/Lab/demo/Lab/Plugins/IO/OM_io_plugin.cpp @@ -0,0 +1,200 @@ +#include "SMesh_type.h" +#include "Scene_surface_mesh_item.h" +#include "Scene_polygon_soup_item.h" +#include "Kernel_type.h" +#include "Scene.h" + +#include +#include +#include "Scene_polyhedron_selection_item.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace CGAL::Three; +class CGAL_Lab_om_plugin : + public QObject, + public CGAL_Lab_io_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::CGAL_Lab_io_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.IOPluginInterface/1.90" FILE "om_io_plugin.json") + +public: + QString nameFilters() const; + QString name() const { return "om_plugin"; } + bool canLoad(QFileInfo fileinfo) const; + QList load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true); + + bool canSave(const CGAL::Three::Scene_item*); + bool save(QFileInfo fileinfo,QList&); +}; + +QString CGAL_Lab_om_plugin::nameFilters() const { + return "om files (*.om)"; +} + +bool CGAL_Lab_om_plugin::canLoad(QFileInfo) const { + return true; +} + + + +QList +CGAL_Lab_om_plugin:: +load(QFileInfo fileinfo, bool& ok, bool add_to_scene){ + + // Open file + std::ifstream in(fileinfo.filePath().toUtf8(), std::ios::in | std::ios::binary); + if(!in) { + std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl; + ok = false; + return QList(); + } + in.close(); + if(fileinfo.size() == 0) + { + CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); + Scene_surface_mesh_item* item = new Scene_surface_mesh_item(); + item->setName(fileinfo.completeBaseName()); + ok = true; + if(add_to_scene) + CGAL::Three::Three::scene()->addItem(item); + return QList()<::vertex_descriptor vertex_descriptor; + typedef boost::graph_traits::edge_descriptor edge_descriptor; + std::map sm_vfeature_map; + auto sm_vfeature_pmap = boost::make_assoc_property_map(sm_vfeature_map); + + std::map sm_efeature_map; + auto sm_efeature_pmap = boost::make_assoc_property_map(sm_efeature_map); + + // Try building a surface_mesh + SMesh* sm = new SMesh(); + ok = CGAL::IO::read_OM((const char*)fileinfo.filePath().toUtf8(), + *sm, + CGAL::parameters::vertex_is_constrained_map(sm_vfeature_pmap) + .edge_is_constrained_map(sm_efeature_pmap)); + + if(!ok || !sm->is_valid() || sm->is_empty()){ + std::cerr << "Error: Invalid facegraph" << std::endl; + } + else{ + Scene_surface_mesh_item* item = new Scene_surface_mesh_item(sm); + + Scene_polyhedron_selection_item* selection_item = new Scene_polyhedron_selection_item(item, CGAL::Three::Three::mainWindow()); + for(auto v : vertices(*sm)){ + if(get(sm_vfeature_pmap, v)){ + selection_item->selected_vertices.insert(v); + } + } + for(auto e : edges(*sm)){ + if(get(sm_efeature_pmap, e)){ + selection_item->selected_edges.insert(e); + } + } + item->setName(fileinfo.completeBaseName()); + ok = true; + if(add_to_scene) + { + CGAL::Three::Three::scene()->addItem(item); + if(!selection_item->isEmpty()) + CGAL::Three::Three::scene()->addItem(selection_item); + } + + QList res; + res << item; + if(!selection_item->isEmpty()) + res << selection_item; + return res; + } + } + catch(...){} + + ok = false; + return QList(); +} + +bool CGAL_Lab_om_plugin::canSave(const CGAL::Three::Scene_item* item) +{ + return qobject_cast(item) + || qobject_cast(item); +} + +bool CGAL_Lab_om_plugin:: +save(QFileInfo fileinfo, QList& items) +{ + Scene_surface_mesh_item* sm_item = nullptr; + Scene_polyhedron_selection_item* selection_item = nullptr; + + for (Scene_item* item : items) + { + if (sm_item == nullptr) + { + sm_item = qobject_cast(item); + if (sm_item != nullptr) //surface_mesh_item found + continue; + } + if (selection_item == nullptr) + { + selection_item = qobject_cast(item); + } + } + + if (sm_item == nullptr && selection_item == nullptr) + return false; + + if (selection_item != nullptr) + { + if (sm_item == nullptr) + sm_item = selection_item->polyhedron_item(); + + if (sm_item != selection_item->polyhedron_item()) + { + std::cerr << "Warning! Selection is not associated to the surface_mesh. Ignoring selection." << std::endl; + selection_item = nullptr; + } + } + + bool res = false; + if (selection_item != nullptr) + { + res = CGAL::IO::write_OM((const char*)fileinfo.filePath().toUtf8() + , *sm_item->face_graph() + , CGAL::parameters::vertex_is_constrained_map(selection_item->constrained_vertices_pmap()) + .edge_is_constrained_map(selection_item->constrained_edges_pmap())); + } + else + { + res = CGAL::IO::write_OM((const char*)fileinfo.filePath().toUtf8() + , *sm_item->face_graph()); + } + + if (res) + { + items.removeAll(sm_item); + if (selection_item != nullptr) + items.removeAll(selection_item); + } + return res; +} + +#include "OM_io_plugin.moc" 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 5badcf76a9c..8f9a99e0877 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 diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index 89a5ba1f98a..dba097d69e6 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -421,6 +421,7 @@ The table above only lists the functions that work with any polygon mesh. \ref IOStreamOBJ "OBJ" \ref IOStreamGocad "GOCAD" \ref IOStreamWRL "WRL" + \ref IOStreamOM "OpenMesh (OM)" Input @@ -430,6 +431,7 @@ The table above only lists the functions that work with any polygon mesh. `CGAL::IO::read_VTP()` `CGAL::IO::read_OBJ()` `CGAL::IO::read_GOCAD()` + `CGAL::IO::read_OM()`
-
@@ -441,6 +443,7 @@ The table above only lists the functions that work with any polygon mesh. `CGAL::IO::write_OBJ()` `CGAL::IO::write_GOCAD()` `CGAL::IO::write_WRL()` + `CGAL::IO::write_OM()`