Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
457ee55
Store selection in Status
afabri Aug 20, 2024
b2d5dc4
Fix options
afabri Aug 20, 2024
65b7c09
Add a conversion operator
afabri Aug 20, 2024
0c8e489
store/retrieve selection and features of an OM
afabri Aug 20, 2024
2c4fc75
Add CGAL::IO::read_OM()
afabri Aug 20, 2024
0e25e33
put code in header file
afabri Aug 20, 2024
5d4ba30
Avoid need for conversion operator
afabri Aug 20, 2024
4832f06
Add plugin to read OpenMesh .om files
afabri Aug 22, 2024
496019a
Add a selection item for edges marked in the om file
afabri Aug 22, 2024
302e2fe
We are only interested in features
afabri Aug 22, 2024
4324445
Merge remote-tracking branch 'mine/Installation-findOpenMesh-jtournoi…
janetournois Sep 5, 2024
07fac94
use CGAL::OpenMesh_support
janetournois Sep 5, 2024
2145d26
add write_OM() and use it in OM_io_plugin
janetournois Sep 5, 2024
dfecf51
trailing whitespaces
janetournois Sep 5, 2024
705729e
cleanup
afabri Sep 8, 2024
9f77e30
STL_extension: Add conversion operator
afabri Sep 8, 2024
4aae544
cleanup
afabri Sep 8, 2024
1066666
Merge remote-tracking branch 'cgal/master' into BGL-Openmesh_selectio…
janetournois Sep 9, 2024
2eb8033
create selection item only when OM file contains feature vertices or …
janetournois Sep 10, 2024
6696b2a
de X
afabri Sep 17, 2024
7d849ee
Merge remote-tracking branch 'cgal/master' into BGL-Openmesh_selectio…
afabri Sep 17, 2024
206eb3c
Only compile OM.h when using OpenMesh
afabri Sep 17, 2024
7faabe4
Add #include of copy_face_graph
afabri Sep 20, 2024
5f2afe2
fix typedefs (code review)
janetournois Sep 26, 2024
54db085
add EOL
janetournois Sep 26, 2024
5d77b6b
remove debug code
janetournois Sep 26, 2024
f30fffd
fix warnings and incorrect filename
sloriot Oct 8, 2024
b7b48b1
add QUIET
janetournois Oct 8, 2024
cddb3d5
move OM.h IO header to BGL package
janetournois Oct 23, 2024
9764dd1
remove extra include
sloriot Oct 23, 2024
69bf76e
remove obselete header
janetournois Oct 23, 2024
51b98e9
add doc
sloriot Oct 24, 2024
c893669
apply @MaelRL review
sloriot Nov 8, 2024
13fcef6
missing const
sloriot Nov 8, 2024
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
4 changes: 4 additions & 0 deletions BGL/doc/BGL/PackageDescription.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions BGL/examples/BGL_OpenMesh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
85 changes: 85 additions & 0 deletions BGL/examples/BGL_OpenMesh/PolyMesh.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
9 changes: 5 additions & 4 deletions BGL/examples/BGL_OpenMesh/TriMesh.cpp
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
6 changes: 6 additions & 0 deletions BGL/include/CGAL/IO/polygon_mesh_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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`)
Expand Down Expand Up @@ -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")
Expand Down
239 changes: 239 additions & 0 deletions BGL/include/CGAL/boost/graph/IO/OM.h
Original file line number Diff line number Diff line change
@@ -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, 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
Loading