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 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
23 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
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
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(UseOpenMesh)
create_single_source_cgal_program("TriMesh.cpp")
target_link_libraries(TriMesh PRIVATE ${OPENMESH_LIBRARIES})

create_single_source_cgal_program("PolyMesh.cpp")
target_link_libraries(PolyMesh PRIVATE ${OPENMESH_LIBRARIES})
else()
message("NOTICE: This project requires OpenMesh and will not be compiled.")
endif()
71 changes: 71 additions & 0 deletions BGL/examples/BGL_OpenMesh/PolyMesh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

#include <OpenMesh/Core/IO/MeshIO.hh>
#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 <CXGAL/IO/OM.h>
#include <CGAL/property_map.h>
#include <CGAL/Surface_mesh.h>
#include <iostream>
#include <fstream>


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/in.off");
const char* outname= (argc>2)?argv[2]:"out.om";
CGAL::IO::read_polygon_mesh(filename, omesh);

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;
}

i = 0;
for(auto eit = omesh.edges_begin(); eit != omesh.edges_end(); ++eit){
omesh.status(*eit).set_feature(i > 2);
++i;
}

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, sm_selected_pmap, sm_feature_pmap);

std::cout << "vertex selection values:\n";
for(auto v : vertices(sm)){
std::cout << std::boolalpha << get(sm_selected_pmap, v) << std::endl;
}

std::cout << "edge feature values:\n";
for(auto e : edges(sm)){
std::cout << std::boolalpha << get(sm_feature_pmap, e) << std::endl;
}
return 0;
}
62 changes: 62 additions & 0 deletions BGL/examples/BGL_OpenMesh/read_OM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#pragma once

#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>

#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/property_map.h>
#include <iostream>
#include <fstream>
#include <map>

namespace CGAL {
namespace IO {

template <typename SM, typename VSelectionPM, typename EFeaturePM>
bool read_OM(std::string fname, SM& sm, VSelectionPM vspm, EFeaturePM efpm)
{
typedef OpenMesh::PolyMesh_ArrayKernelT<> OMesh;
typedef boost::graph_traits<OMesh>::vertex_descriptor om_vertex_descriptor;
typedef boost::graph_traits<SM>::vertex_descriptor sm_vertex_descriptor;
typedef boost::graph_traits<OMesh>::halfedge_descriptor om_halfedge_descriptor;
typedef boost::graph_traits<SM>::halfedge_descriptor sm_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,sm_vertex_descriptor> v2v;
auto v2vpmap = boost::make_assoc_property_map(v2v);

std::map<om_halfedge_descriptor,sm_halfedge_descriptor> h2h;
auto h2hpmap = boost::make_assoc_property_map(h2h);

CGAL::copy_face_graph<OMesh,SM>(omesh, sm, CGAL::parameters::vertex_to_vertex_map(v2vpmap).halfedge_to_halfedge_map(h2hpmap));

if(options.vertex_has_status()){
for(auto v : vertices(omesh)){
put(vspm, v2v[v], omesh.status(v).selected());
}
}else{
std::cout << "no vertex status" << std::endl;
}

if(options.edge_has_status()){
for(auto e : edges(omesh)){
auto sme = edge(h2h[halfedge(e,omesh)], sm);
put(efpm, sme , omesh.status(OpenMesh::EdgeHandle(e.idx())).feature());
}
}else{
std::cout << "no edge status" << std::endl;
}
return true;
}

} // namespace IO
} // namespace CGAL


10 changes: 10 additions & 0 deletions Lab/demo/Lab/Plugins/IO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ target_link_libraries(surf_io_plugin PUBLIC scene_surface_mesh_item)
cgal_lab_plugin(lcc_io_plugin lcc_io_plugin KEYWORDS Viewer)
target_link_libraries(lcc_io_plugin PUBLIC scene_lcc_item)

find_package(OpenMesh)
if(OpenMesh_FOUND)
include(UseOpenMesh)
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 ${OPENMESH_LIBRARIES})
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
Expand Down
175 changes: 175 additions & 0 deletions Lab/demo/Lab/Plugins/IO/OM_io_plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#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/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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SMesh* SM = new SMesh();
SMesh* sm = new SMesh();

the name should be lower case

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started from the STL plugin.

ok = CGAL::IO::read_OM((const char*)fileinfo.filePath().toUtf8(), *SM, sm_vfeature_pmap, 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());
janetournois marked this conversation as resolved.
Show resolved Hide resolved
bool eselected = false;
bool vselected = false;
for(auto v : vertices(*SM)){
if(get(sm_vfeature_pmap, v)){
selection_item->selected_vertices.insert(v);
vselected = true;
}
}
for(auto e : edges(*SM)){
if(get(sm_efeature_pmap, e)){
selection_item->selected_edges.insert(e);
eselected = true;
}
}
item->setName(fileinfo.completeBaseName());
ok = true;
if(add_to_scene){
CGAL::Three::Three::scene()->addItem(item);
CGAL::Three::Three::scene()->addItem(selection_item);
}
return QList<Scene_item*>()<<item << selection_item;
}
}
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);
}

bool CGAL_Lab_om_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
#if 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#if 0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving a mesh in *.om format is not yet done. It would be cleaner to reply false in a can_save() method.

Scene_item* item = items.front();
const Scene_surface_mesh_item* sm_item =
qobject_cast<const Scene_surface_mesh_item*>(item);

if(!sm_item)
return false;

QStringList list;
list << tr("Binary");
list << tr("Ascii");
bool ok = false;
QString choice
= QInputDialog::getItem(nullptr, tr("Save om file"), tr("Format"), list, 0, false, &ok);

if (!ok)
return false;

std::ofstream out(fileinfo.filePath().toUtf8(), std::ios::out | std::ios::binary);
if ( choice == tr("Binary") )
CGAL::IO::set_mode(out, CGAL::IO::BINARY);
else
{
CGAL::IO::set_mode(out, CGAL::IO::ASCII);
out.precision (std::numeric_limits<double>::digits10 + 2);
}

if (sm_item)
{
CGAL::IO::write_om(out, *sm_item->face_graph());
items.pop_front();
return true;
}
#endif
return false;
}

#include "om_io_plugin.moc"
5 changes: 5 additions & 0 deletions STL_Extension/include/CGAL/hash_openmesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class OMesh_edge {
}
}

/*
operator OpenMesh::EdgeHandle () const {
return OpenMesh::EdgeHandle(idx());
}
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should go to another pull request. The thing is that the edge_descriptor we wrote cannot be passed to methods like status(e).

bool operator<(const OMesh_edge& other) const
{
return this->idx() < other.idx();
Expand Down
Loading