Add CGAL::IO::read_OM() (#8427)

## Summary of Changes

Add a function to read an OpenMesh file ( `*.om` ) in CGALlab. This file
format stores also edges and vertices marked as features.
For the moment the function itself is not documented.

## Release Management

* License and copyright ownership: GeometryFactory
This commit is contained in:
Sebastien Loriot 2024-11-14 14:12:26 +01:00 committed by GitHub
commit 74ea8b1f6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 585 additions and 6 deletions

View File

@ -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

View File

@ -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()

View File

@ -0,0 +1,85 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/IO/polygon_mesh_io.h>
#include <CGAL/property_map.h>
#include <CGAL/Surface_mesh.h>
#include <iostream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef OpenMesh::PolyMesh_ArrayKernelT</* MyTraits*/> OMesh;
typedef CGAL::Surface_mesh<Kernel::Point_3> SM;
typedef boost::graph_traits<OMesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<OMesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<SM>::vertex_descriptor sm_vertex_descriptor;
typedef boost::graph_traits<SM>::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_vertex_descriptor,bool> sm_selected_map;
auto sm_selected_pmap = boost::make_assoc_property_map(sm_selected_map);
std::map<sm_edge_descriptor,bool> 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;
}

View File

@ -1,17 +1,18 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <CGAL/boost/graph/graph_traits_TriMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/properties_TriMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/IO/polygon_mesh_io.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/mesh_segmentation.h>
#include <CGAL/property_map.h>
#include <iostream>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;

View File

@ -17,6 +17,7 @@
#include <CGAL/boost/graph/IO/INP.h>
#include <CGAL/boost/graph/IO/OBJ.h>
#include <CGAL/boost/graph/IO/OFF.h>
#include <CGAL/boost/graph/IO/OM.h>
#include <CGAL/boost/graph/IO/PLY.h>
#include <CGAL/boost/graph/IO/STL.h>
#include <CGAL/boost/graph/IO/VTK.h>
@ -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")

View File

@ -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 <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/property_map.h>
#include <CGAL/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <iostream>
#include <fstream>
#include <map>
namespace CGAL {
namespace IO {
namespace internal {
template <typename Graph, typename VPM, typename VFeaturePM, typename EFeaturePM>
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<OMesh>::vertex_descriptor om_vertex_descriptor;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<OMesh>::halfedge_descriptor om_halfedge_descriptor;
typedef typename boost::graph_traits<Graph>::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<om_vertex_descriptor, vertex_descriptor> v2v;
auto v2vpmap = boost::make_assoc_property_map(v2v);
std::map<om_halfedge_descriptor, halfedge_descriptor> h2h;
auto h2hpmap = boost::make_assoc_property_map(h2h);
CGAL::copy_face_graph<OMesh,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 <typename Graph, typename VPM, typename VFeaturePM, typename EFeaturePM>
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<OMesh>::vertex_descriptor om_vertex_descriptor;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<OMesh>::halfedge_descriptor om_halfedge_descriptor;
typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
std::map<vertex_descriptor, om_vertex_descriptor> v2v;
auto v2vpmap = boost::make_assoc_property_map(v2v);
std::map<halfedge_descriptor, om_halfedge_descriptor> h2h;
auto h2hpmap = boost::make_assoc_property_map(h2h);
OMesh omesh;
CGAL::copy_face_graph<Graph, OMesh>(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<Graph>::%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<Graph>::%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<Graph>::%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 <typename Graph, typename CGAL_NP_TEMPLATE_PARAMETERS>
bool read_OM(const std::string& fname,
Graph& g,
const CGAL_NP_CLASS& np = parameters::default_values())
{
using vertex_descriptor = typename boost::graph_traits<Graph>::vertex_descriptor;
using edge_descriptor = typename boost::graph_traits<Graph>::edge_descriptor;
using CGAL::parameters::get_parameter;
using CGAL::parameters::choose_parameter;
using Default_vfmap = Static_boolean_property_map<vertex_descriptor, false>;
using Default_efmap = Static_boolean_property_map<edge_descriptor, false>;
auto vfpm = choose_parameter<Default_vfmap>(get_parameter(np, internal_np::vertex_is_constrained));
auto efpm = choose_parameter<Default_efmap>(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<Graph>::%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<Graph>::%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<Graph>::%vertex_descriptor`
as key type and `bool` as value type.}
\cgalParamNEnd
\cgalNamedParamsEnd
\returns `true` if writing was successful, `false` otherwise.
*/
template <typename Graph, typename CGAL_NP_TEMPLATE_PARAMETERS>
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<Graph>::vertex_descriptor;
using edge_descriptor = typename boost::graph_traits<Graph>::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<vertex_descriptor, bool>(false));
auto efpm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained),
CGAL::Constant_property_map<edge_descriptor, bool>(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

View File

@ -9,7 +9,6 @@
//
// Author(s) : Andreas Fabri, Philipp Moeller
// include this to avoid a VC15 warning
#include <CGAL/Named_function_parameters.h>
#include <boost/graph/graph_traits.hpp>
@ -21,7 +20,6 @@
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Iterator_range.h>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/boost/graph/io.h>
#include <CGAL/assertions.h>
#include <CGAL/hash_openmesh.h>

View File

@ -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 <OpenMesh/Core/IO/MeshIO.hh>
#include <CGAL/boost/graph/properties_PolyMesh_ArrayKernelT.h>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#define OPEN_MESH_CLASS OpenMesh::PolyMesh_ArrayKernelT<K>
#include <CGAL/boost/graph/graph_traits_OpenMesh.h>

View File

@ -16,6 +16,7 @@
#include <CGAL/boost/graph/IO/INP.h>
#include <CGAL/boost/graph/IO/OBJ.h>
#include <CGAL/boost/graph/IO/OFF.h>
#include <CGAL/boost/graph/IO/OM.h>
#include <CGAL/boost/graph/IO/PLY.h>
#include <CGAL/boost/graph/IO/STL.h>
#include <CGAL/boost/graph/IO/VTK.h>

View File

@ -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

View File

@ -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 <CGAL/Three/CGAL_Lab_io_plugin_interface.h>
#include <CGAL/Three/Three.h>
#include "Scene_polyhedron_selection_item.h"
#include <CGAL/boost/graph/IO/OM.h>
#include <CGAL/boost/graph/io.h>
#include <QColor>
#include <QString>
#include <QStringList>
#include <QMainWindow>
#include <QInputDialog>
#include <boost/property_map/function_property_map.hpp>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <limits>
#include <vector>
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<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>&);
};
QString CGAL_Lab_om_plugin::nameFilters() const {
return "om files (*.om)";
}
bool CGAL_Lab_om_plugin::canLoad(QFileInfo) const {
return true;
}
QList<Scene_item*>
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<Scene_item*>();
}
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<Scene_item*>()<<item;
}
try
{
typedef boost::graph_traits<SMesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<SMesh>::edge_descriptor edge_descriptor;
std::map<vertex_descriptor,bool> sm_vfeature_map;
auto sm_vfeature_pmap = boost::make_assoc_property_map(sm_vfeature_map);
std::map<edge_descriptor,bool> 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<Scene_item*> res;
res << item;
if(!selection_item->isEmpty())
res << selection_item;
return res;
}
}
catch(...){}
ok = false;
return QList<Scene_item*>();
}
bool CGAL_Lab_om_plugin::canSave(const CGAL::Three::Scene_item* item)
{
return qobject_cast<const Scene_surface_mesh_item*>(item)
|| qobject_cast<const Scene_polyhedron_selection_item*>(item);
}
bool CGAL_Lab_om_plugin::
save(QFileInfo fileinfo, QList<CGAL::Three::Scene_item*>& 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<Scene_surface_mesh_item*>(item);
if (sm_item != nullptr) //surface_mesh_item found
continue;
}
if (selection_item == nullptr)
{
selection_item = qobject_cast<Scene_polyhedron_selection_item*>(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"

View File

@ -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 <a href="https://www.graphics.rwth-aachen.de/media/openmesh_static/Documentations/OpenMesh-Doc-Latest/a06338.html">here</a>.
<table class="iotable">
<tr>
<th colspan="4">OpenMesh Format (OM)</th>
</tr>
<tr>
<td width="75">Input</td>
<td width="175">Polygon Mesh</td>
<td width="250">Any model of `MutableFaceGraph`</td>
<td width="500">\link PkgBGLIoFuncsOM CGAL::IO::read_OM(const std::string&, Graph&)\endlink</td>
</tr>
<tr>
<td>Output</td>
<td>Polygon Mesh</td>
<td>Any model of `FaceGraph`</td>
<td>\link PkgBGLIoFuncsOM CGAL::IO::write_OM(const std::string&, const Graph&)\endlink</td>
</tr>
</table>
\section IOStreamSTL STereoLithography (STL) File Format

View File

@ -421,6 +421,7 @@ The table above only lists the functions that work with any polygon mesh.
<th colspan="1">\ref IOStreamOBJ "OBJ"</th>
<th colspan="1">\ref IOStreamGocad "GOCAD"</th>
<th colspan="1">\ref IOStreamWRL "WRL"</th>
<th colspan="1">\ref IOStreamOM "OpenMesh (OM)"</th>
</tr>
<tr>
<td>Input</td>
@ -430,6 +431,7 @@ The table above only lists the functions that work with any polygon mesh.
<td>`CGAL::IO::read_VTP()`</td>
<td>`CGAL::IO::read_OBJ()`</td>
<td>`CGAL::IO::read_GOCAD()`</td>
<td>`CGAL::IO::read_OM()`</td>
<td><center> - </center></td>
</tr>
<tr>
@ -441,6 +443,7 @@ The table above only lists the functions that work with any polygon mesh.
<td>`CGAL::IO::write_OBJ()`</td>
<td>`CGAL::IO::write_GOCAD()`</td>
<td>`CGAL::IO::write_WRL()`</td>
<td>`CGAL::IO::write_OM()`</td>
</tr>
</table>