diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt
index e8fc0239428..4a8ad74af10 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt
+++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt
@@ -1,6 +1,6 @@
include( polyhedron_demo_macros )
if(EIGEN3_FOUND)
- qt5_wrap_ui( parameterizationUI_FILES Parameterization_widget.ui ARAP_dialog.ui)
+ qt5_wrap_ui( parameterizationUI_FILES Parameterization_widget.ui ARAP_dialog.ui OTE_dialog.ui)
polyhedron_demo_plugin(parameterization_plugin Parameterization_plugin ${parameterizationUI_FILES})
target_link_libraries(parameterization_plugin scene_polyhedron_item scene_textured_polyhedron_item scene_polyhedron_selection_item)
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/OTE_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/OTE_dialog.ui
new file mode 100644
index 00000000000..f5ae423667a
--- /dev/null
+++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/OTE_dialog.ui
@@ -0,0 +1,137 @@
+
+
+ OTE_dialog
+
+
+
+ 0
+ 0
+ 355
+ 100
+
+
+
+ ArrowCursor
+
+
+ Meshing criteria
+
+
+ -
+
+
-
+
+
+ Orbifold type
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
-
+
+ I (Square)
+
+
+ -
+
+ II (Diamond)
+
+
+ -
+
+ III (Triangle)
+
+
+ -
+
+ IV (Parallelogram)
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ OTE_dialog
+ accept()
+
+
+ 384
+ 191
+
+
+ 157
+ 195
+
+
+
+
+ buttonBox
+ rejected()
+ OTE_dialog
+ reject()
+
+
+ 384
+ 191
+
+
+ 286
+ 195
+
+
+
+
+
diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp
index c0820f7c688..0a0254ba25d 100644
--- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp
+++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp
@@ -20,18 +20,33 @@
#include
#include
#include
+
+#include
+#include
+
#include
+#include
+
#include
#include
#include
#include
#include
#include
+#include
+#include
#include
#include
+#include
+#include
+#include
+
+#include
#include
+#include
+#include
#include
#include
@@ -41,6 +56,7 @@
#include "ui_Parameterization_widget.h"
#include "ui_ARAP_dialog.h"
+#include "ui_OTE_dialog.h"
namespace SMP = CGAL::Surface_mesh_parameterization;
@@ -143,32 +159,44 @@ private:
QPointF prev_pos;
};
-typedef Kernel::FT FT;
-typedef boost::graph_traits::vertex_descriptor vertex_descriptor;
-typedef Kernel::Point_2 Point_2;
-typedef boost::graph_traits::edge_descriptor P_edge_descriptor;
-typedef boost::graph_traits::halfedge_descriptor P_halfedge_descriptor;
+namespace SMP = CGAL::Surface_mesh_parameterization;
+typedef Kernel::FT FT;
+typedef boost::graph_traits::vertex_descriptor P_vertex_descriptor;
+typedef Kernel::Point_2 Point_2;
+typedef boost::graph_traits::edge_descriptor P_edge_descriptor;
+typedef boost::graph_traits::halfedge_descriptor P_halfedge_descriptor;
+// Textured polyhedron
typedef boost::graph_traits::
- edge_descriptor T_edge_descriptor;
+ edge_descriptor T_edge_descriptor;
typedef boost::graph_traits::
- halfedge_descriptor T_halfedge_descriptor;
+ halfedge_descriptor T_halfedge_descriptor;
typedef boost::graph_traits::
- vertex_descriptor T_vertex_descriptor;
+ vertex_descriptor T_vertex_descriptor;
+// Seam
+typedef CGAL::Unique_hash_map UV_uhm;
+typedef CGAL::Unique_hash_map Seam_edge_uhm;
+typedef CGAL::Unique_hash_map Seam_vertex_uhm;
-typedef CGAL::Unique_hash_map UV_uhm;
-typedef CGAL::Unique_hash_map Seam_edge_uhm;
-typedef CGAL::Unique_hash_map Seam_vertex_uhm;
-
-typedef boost::associative_property_map UV_pmap;
-typedef boost::associative_property_map Seam_edge_pmap;
-typedef boost::associative_property_map Seam_vertex_pmap;
-
+typedef boost::associative_property_map UV_pmap;
+typedef boost::associative_property_map Seam_edge_pmap;
+typedef boost::associative_property_map Seam_vertex_pmap;
typedef CGAL::Seam_mesh Seam_mesh;
-typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor;
+
+typedef boost::graph_traits::vertex_descriptor vertex_descriptor;
+typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor;
+typedef boost::graph_traits::face_descriptor face_descriptor;
+
+typedef boost::graph_traits::face_iterator face_iterator;
+
+typedef boost::unordered_set Component;
+typedef std::vector Components;
+
+typedef boost::unordered_set SComponent;
+typedef std::vector SComponents;
class UVItem : public QGraphicsItem
{
@@ -263,17 +291,19 @@ public:
QAction* actionLSC = new QAction("Least Square Conformal Map", mw);
QAction* actionDAP = new QAction("Discrete Authalic", mw);
QAction* actionARAP = new QAction("As Rigid As Possible", mw);
+ QAction* actionOTE = new QAction("Orbifold Tutte Embedding", mw);
actionMVC->setObjectName("actionMVC");
actionDCP->setObjectName("actionDCP");
actionLSC->setObjectName("actionLSC");
actionDAP->setObjectName("actionDAP");
actionARAP->setObjectName("actionARAP");
+ actionOTE->setObjectName("actionOTE");
_actions << actionMVC
<< actionDCP
<< actionLSC
<< actionDAP
- << actionARAP;
+ << actionOTE;
autoConnectActions();
Q_FOREACH(QAction *action, _actions)
action->setProperty("subMenuName",
@@ -309,6 +339,7 @@ public Q_SLOTS:
void on_actionLSC_triggered();
void on_actionDAP_triggered();
void on_actionARAP_triggered();
+ void on_actionOTE_triggered();
void on_prevButton_pressed();
void on_nextButton_pressed();
void replacePolyline()
@@ -318,8 +349,7 @@ public Q_SLOTS:
int id = scene->mainSelectionIndex();
Q_FOREACH(UVItem* pl, projections)
{
- if(pl==NULL
- || pl != projections[scene->item(id)])
+ if(pl==NULL || pl != projections[scene->item(id)])
continue;
current_uv_item = pl;
break;
@@ -363,8 +393,10 @@ public Q_SLOTS:
}
protected:
- enum Parameterization_method { PARAM_MVC, PARAM_DCP, PARAM_LSC, PARAM_DAP, PARAM_ARAP};
+ enum Parameterization_method { PARAM_MVC, PARAM_DCP, PARAM_LSC,
+ PARAM_DAP, PARAM_ARAP, PARAM_OTE};
void parameterize(Parameterization_method method);
+
private:
Messages_interface *messages;
QList _actions;
@@ -439,10 +471,10 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
sel_item = qobject_cast(scene->item(id));
if(!sel_item)
continue;
- if(sel_item->selected_edges.empty()
- || !sel_item->selected_facets.empty()
- || !sel_item->selected_vertices.empty())
+ if(sel_item->selected_edges.empty())
continue;
+ if(method == PARAM_OTE && sel_item->selected_vertices.empty())
+ continue;
is_seamed = true;
}
// Two property maps to store the seam edges and vertices
@@ -514,9 +546,26 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
}
}
+ // map the cones from the selection plugin to the textured polyhedron
+ boost::unordered_set unordered_cones;
+ if(method == PARAM_OTE) {
+ BOOST_FOREACH(P_vertex_descriptor vd, sel_item->selected_vertices) {
+ Polyhedron::Vertex_handle pvd(vd);
+ Textured_polyhedron::Vertex_iterator it = tMesh.vertices_begin(),
+ end = tMesh.vertices_end();
+ for(; it!=end; ++it) {
+ Textured_polyhedron::Vertex_handle tvd(it);
+ if(it->id() == pvd->id()) {
+ unordered_cones.insert(tvd);
+ }
+ }
+ }
+ }
+
Seam_mesh sMesh(tMesh, seam_edge_pm, seam_vertex_pm);
sMesh.set_seam_edges_number(seam_edges.size());
+ // The parameterized values
UV_uhm uv_uhm;
UV_pmap uv_pm(uv_uhm);
@@ -537,24 +586,45 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
CGAL::Polygon_mesh_processing::parameters::edge_is_constrained_map(
edge_pmap));
- Components t_components(number_of_components);
+
+ // Next is the gathering of the border halfedges of the connected component.
+ // It is wrong to pass the underlying mesh tMesh: a sphere split in half does
+ // not have any border according if border_halfedges() is run with tMesh.
+ //
+ // The proper way would be to completely redesign the plugin to use Seam meshes
+ // everywhere. But that's not worth it. Instead, we abuse the fact that faces
+ // are the same in tMesh and sMesh.
+
+ // the SEAM MESH faces of each connected component
+ SComponents s_components(number_of_components);
+
Textured_polyhedron::Base::Facet_iterator fit;
- for(fit = tMesh.facets_begin(); fit != tMesh.facets_end(); ++fit)
- {
- t_components.at(fccmap[fit]).insert(fit);
+ for(fit = tMesh.facets_begin(); fit != tMesh.facets_end(); ++fit) {
+ s_components.at(fccmap[fit]).insert(face_descriptor(fit));
}
//once per component
std::vector >uv_borders;
uv_borders.resize(number_of_components);
+
for(int current_component=0; current_component border;
- PMP::border_halfedges(t_components.at(current_component),
- tMesh,
- std::back_inserter(border));
+ std::vector border;
- BOOST_FOREACH(T_halfedge_descriptor hd, border)
+ // using `impl` to avoid face_index_t property maps
+// PMP::internal::border_halfedges_impl(s_components.at(current_component),
+// std::back_inserter(border),
+// sMesh);
+
+ PMP::internal::border_halfedges_impl(s_components.at(current_component),
+ std::back_inserter(border),
+ sMesh);
+
+ std::cout << sMesh.number_of_seam_edges() << " seams" << std::endl;
+ std::cout << (s_components.at(current_component)).size() << " faces" << std::endl;
+ std::cout << border.size() << " border halfedges" << std::endl;
+
+ BOOST_FOREACH(halfedge_descriptor hd, border)
{
uv_borders[current_component].push_back(source(hd, tMesh)->point().x());
uv_borders[current_component].push_back(source(hd, tMesh)->point().y());
@@ -569,12 +639,8 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
halfedge_descriptor bhd; // a halfedge on the (possibly virtual) border
boost::unordered_set visited;
FT result_len = 0;
- BOOST_FOREACH(T_halfedge_descriptor thd, border)
+ BOOST_FOREACH(halfedge_descriptor hd, border)
{
- halfedge_descriptor hd(thd);
- if(sMesh.has_on_seam(thd))
- hd.seam = true; // virtual border halfedge
-
assert(is_border(hd, sMesh));
if(visited.find(hd) == visited.end())
@@ -593,7 +659,8 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
}
}
}
- assert(bhd != halfedge_descriptor() && is_border(bhd, sMesh));
+ CGAL_postcondition(bhd != halfedge_descriptor());
+ CGAL_postcondition(is_border(bhd, sMesh));
bool success = false;
switch(method)
@@ -660,6 +727,64 @@ void Polyhedron_demo_parameterization_plugin::parameterize(const Parameterizatio
success = (err == SMP::OK);
break;
}
+ case PARAM_OTE:
+ {
+ new_item_name = tr("%1 (parameterized (OTE))").arg(poly_item->name());
+ std::cout << "Parameterize (OTE)...";
+
+ // does not handle multiple connected components right now
+ // @todo (need to remove the assertions such as cones.size() == 4
+ // and check where and when cones are used (passed by ID, for ex.?))
+ CGAL_assertion(number_of_components == 1);
+
+ CGAL_precondition(!unordered_cones.empty());
+
+ typedef SMP::Orbital_Tutte_parameterizer_3 Parameterizer;
+
+ QDialog dialog(mw);
+ Ui::OTE_dialog ui;
+ ui.setupUi(&dialog);
+ connect(ui.buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
+ connect(ui.buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
+
+ // Get values
+ QApplication::restoreOverrideCursor();
+
+ int i = dialog.exec();
+ if (i == QDialog::Rejected)
+ return;
+
+ SMP::Orbifold_type orb = static_cast(ui.OrbComboBox->currentIndex());
+ std::cout << "selected orbifold type: " << ui.OrbComboBox->currentText().toStdString() << std::endl;
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+
+ // Now, parameterize
+ Parameterizer parameterizer(orb);
+
+ // mark cones in the seam mesh
+ typedef boost::unordered_map Cones;
+ Cones cmap;
+ SMP::internal::locate_unordered_cones,
+ Cones>(sMesh, unordered_cones, cmap);
+
+ // vimap and uvmap
+ typedef boost::unordered_map Indices;
+ Indices indices;
+ CGAL::Polygon_mesh_processing::connected_component(
+ face(opposite(bhd, sMesh), sMesh),
+ sMesh,
+ boost::make_function_output_iterator(
+ SMP::internal::Index_map_filler(sMesh, indices)));
+ boost::associative_property_map vimap(indices);
+
+ // Call to parameterizer
+ SMP::Error_code err = parameterizer.parameterize(sMesh, bhd, cmap, uv_pm, vimap);
+ success = (err == SMP::OK);
+ break;
+ }
}//end switch
QApplication::restoreOverrideCursor();
@@ -770,4 +895,10 @@ void Polyhedron_demo_parameterization_plugin::on_actionARAP_triggered()
parameterize(PARAM_ARAP);
}
+void Polyhedron_demo_parameterization_plugin::on_actionOTE_triggered()
+{
+ std::cerr << "OTE...";
+ parameterize(PARAM_OTE);
+}
+
#include "Parameterization_plugin.moc"
diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbital.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbital.cpp
index 183fd7ca618..fb2dd59a430 100644
--- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbital.cpp
+++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbital.cpp
@@ -46,87 +46,16 @@ typedef SurfaceMesh::Property_map UV_pmap;
namespace SMP = CGAL::Surface_mesh_parameterization;
-/// Read the cones from the input file.
-SMP::Error_code read_cones(const SurfaceMesh& sm, const char* filename,
- std::vector& cone_vds_in_sm)
-{
- std::ifstream in(filename);
- std::string vertices_line;
- std::getline(in, vertices_line); // read the first line of the file
- std::istringstream iss(vertices_line);
- std::vector cones;
- cones.reserve(4);
- int cone_index;
- while(iss >> cone_index) {
- cones.push_back(cone_index);
- }
-
- if(cones.size() < 3 || cones.size() > 4) {
- std::cerr << "Error: problem loading the input cones" << std::endl;
- return SMP::ERROR_WRONG_PARAMETER;
- }
-
- std::cout << "Cones: ";
- for(std::size_t i=0; i
-void locate_cones(const Mesh& mesh,
- const std::vector& cone_vds_in_sm,
- ConeMap& cones)
-{
- // property map to go from SM_vertex_descriptor to Point_3
- typedef SMP::internal::Kernel_traits::PPM SM_PPM;
- const SM_PPM sm_ppmap = get(boost::vertex_point, mesh.mesh());
-
- // property map to go from vertex_descriptor to Point_3
- typedef SMP::internal::Kernel_traits::PPM PPM;
- const PPM ppmap = get(boost::vertex_point, mesh);
-
- // the cones in the underlying mesh
- std::size_t cvdss = cone_vds_in_sm.size();
- for(std::size_t i=0; i2) ? argv[2] : "../data/bear.selection.txt";
// Read the cones and find the corresponding vertex_descriptor in the underlying mesh 'sm'
- std::vector cone_vds_in_sm;
- read_cones(sm, cone_filename, cone_vds_in_sm);
+ typedef std::vector Cones_in_smesh_container;
+ Cones_in_smesh_container cone_vds_in_sm;
+ SMP::internal::read_cones(sm, cone_filename, cone_vds_in_sm);
// Two property maps to store the seam edges and vertices
Seam_edge_pmap seam_edge_pm = sm.add_property_map("e:on_seam", false).first;
@@ -185,7 +115,9 @@ int main(int argc, char * argv[])
// Mark the cones in the seam mesh
typedef boost::unordered_map Cones;
Cones cmap;
- locate_cones(mesh, cone_vds_in_sm, cmap);
+ SMP::internal::locate_cones(mesh, cone_vds_in_sm, cmap);
// The 2D points of the uv parametrisation will be written into this map
// Note that this is a halfedge property map, and that uv values
diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/parameterization_tests.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/parameterization_tests.cpp
index 9aca13e54d2..01b67c1abac 100644
--- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/parameterization_tests.cpp
+++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/parameterization_tests.cpp
@@ -5,16 +5,17 @@
#include
#include
+#include
+#include
+
#include
#include
-#include
-#include
-#include
-
#include
#include
+#include
+
#include
#include
diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbital_Tutte_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbital_Tutte_parameterizer_3.h
index a09cbbb66f9..cb726db4b62 100644
--- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbital_Tutte_parameterizer_3.h
+++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbital_Tutte_parameterizer_3.h
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include
@@ -58,20 +59,16 @@
// @todo checks that cones are different, are on seams, seam is one connected
// component
+// @todo Should the order of cones provided in entry matter ? Map the first cone
+// to [-1, -1] for example ?
namespace CGAL {
namespace Surface_mesh_parameterization {
-enum Cone_type
-{
- Unique_cone,
- Duplicated_cone
-};
-
enum Orbifold_type
{
- Square,
+ Square = 0,
Diamond,
Triangle,
Parallelogram
@@ -246,10 +243,12 @@ public:
++id_r; // current line index in A is increased
}
- void parameterize_seam_segment(const std::vector >& seam_segment,
- NT ang, int& current_line_id_in_A,
- Matrix& A, Vector& B) const
+ void constrain_seam_segment(const std::vector >& seam_segment,
+ NT ang, int& current_line_id_in_A,
+ Matrix& A, Vector& B) const
{
+ std::cout << "constraining segment of length " << seam_segment.size() << std::endl;
+
// check that if there is a common vertex, it is at the beginning
bool is_reversed = (seam_segment.back().first == seam_segment.back().second);
@@ -323,7 +322,7 @@ public:
// points between two cones, and the corresponding points on the opposite side of the seam
std::vector > seam_segment;
- int segment_index = 0; // counting the segments (3 max)
+ std::size_t segment_index = 0; // counting the segments (3 max)
// Go through the seam, marking rotation and cone constraints
while(true) { // breaking at the last cone
@@ -366,7 +365,7 @@ public:
CGAL_assertion(segment_index < angs.size());
NT ang = angs[segment_index];
- parameterize_seam_segment(seam_segment, ang, current_line_id_in_A, A, B);
+ constrain_seam_segment(seam_segment, ang, current_line_id_in_A, A, B);
// the last cone of the seam is constrained
if(is_in_map->second == Unique_cone) { // reached the end of the seam
@@ -378,7 +377,7 @@ public:
std::cout << "-------------------------" << std::endl;
seam_segment.clear();
- segment_index++;
+ ++segment_index;
}
// move to the next halfedge couple (walking on the border of the seam)
@@ -482,7 +481,7 @@ public:
const VertexIndexMap vimap) const
{
std::cout << "size of X: " << X.size() << std::endl;
- CGAL_assertion(X.size() == 2 * num_vertices(mesh) );
+ CGAL_assertion(X.size() == static_cast(2 * num_vertices(mesh)));
BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)) {
int index = get(vimap, vd);
diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/orbital_cone_helper.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/orbital_cone_helper.h
new file mode 100644
index 00000000000..ea0e6103f04
--- /dev/null
+++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/orbital_cone_helper.h
@@ -0,0 +1,236 @@
+// Copyright (c) 2016 GeometryFactory (France).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// You can redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL$
+// $Id$
+//
+//
+// Author(s) :
+
+#ifndef CGAL_SURFACE_MESH_PARAMETERIZATION_INTERNAL_CONE_HELPER_H
+#define CGAL_SURFACE_MESH_PARAMETERIZATION_INTERNAL_CONE_HELPER_H
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace CGAL {
+
+namespace Surface_mesh_parameterization {
+
+enum Cone_type
+{
+ Unique_cone,
+ Duplicated_cone
+};
+
+namespace internal {
+
+/// Read the cones from the input file.
+template
+Error_code read_cones(const Polygon_mesh& pm, const char* filename,
+ std::vector::vertex_descriptor>& cone_vds_in_pm)
+{
+ typedef typename boost::graph_traits::vertex_descriptor PM_vertex_descriptor;
+
+ std::ifstream in(filename);
+ std::string vertices_line;
+ std::getline(in, vertices_line); // read the first line of the file
+ std::istringstream iss(vertices_line);
+ std::vector cones;
+ cones.reserve(4);
+ int cone_index;
+ while(iss >> cone_index) {
+ cones.push_back(cone_index);
+ }
+
+ if(cones.size() < 3 || cones.size() > 4) {
+ std::cerr << "Error: Not enough or too many input cones" << std::endl;
+ return ERROR_WRONG_PARAMETER;
+ }
+
+ std::cout << "Cones: ";
+ for(std::size_t i=0; i Cone_type
+template
+void locate_cones(const Mesh& mesh,
+ const Cones_in_pmesh_vector& cone_vds_in_sm,
+ ConeMap& cones)
+{
+ CGAL_precondition(cones.empty());
+
+ typedef typename boost::graph_traits::vertex_descriptor BM_vertex_descriptor;
+ typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor;
+
+ // property map to go from BM_vertex_descriptor to Point_3
+ typedef typename Kernel_traits::PPM PM_PPM;
+ const PM_PPM pm_ppmap = get(boost::vertex_point, mesh.mesh());
+
+ // property map to go from vertex_descriptor to Point_3
+ typedef typename Kernel_traits::PPM PPM;
+ const PPM ppmap = get(boost::vertex_point, mesh);
+
+ // the cones in the underlying mesh
+ std::size_t cvdss = cone_vds_in_sm.size();
+ for(std::size_t i=0; i Cone_type
+template
+void locate_unordered_cones(const Mesh& mesh,
+ const Cones_in_pmesh_set& cone_vds_in_sm,
+ ConeMap& cones)
+{
+ CGAL_precondition(cones.empty());
+
+ typedef typename boost::graph_traits::vertex_descriptor BM_vertex_descriptor;
+ typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor;
+ typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor;
+
+ // find a vertex on the seam
+ vertex_descriptor vertex_on_seam;
+ BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)) {
+ if(mesh.has_on_seam(vd)) {
+ vertex_on_seam = vd;
+ break;
+ }
+ }
+
+ CGAL_assertion(vertex_on_seam != vertex_descriptor());
+
+ // property map to go from BM_vertex_descriptor to Point_3
+ typedef typename Kernel_traits::PPM PM_PPM;
+ const PM_PPM pm_ppmap = get(boost::vertex_point, mesh.mesh());
+
+ // property map to go from vertex_descriptor to Point_3
+ typedef typename Kernel_traits::PPM PPM;
+ const PPM ppmap = get(boost::vertex_point, mesh);
+
+ // walk on the seam and mark if we encounter a cone
+ vertex_descriptor end = vertex_on_seam;
+ do {
+ BOOST_FOREACH(BM_vertex_descriptor smvd, cone_vds_in_sm) {
+ if(get(ppmap, vertex_on_seam) == get(pm_ppmap, smvd)) { // the seam mesh vertex is a cone
+
+ // we have encountered a cone. Must check if the cone is a Unique_cone
+ // or a Duplicated_cone.
+
+ // a check is to look at the sources of two halfedges with the same direction
+ // on either side of the seam. If the sources are the same, it's a Unique_cone;
+ // if they differ, it's a duplicated_cone.
+
+ halfedge_descriptor hd = halfedge(vertex_on_seam, mesh);
+ halfedge_descriptor other_hd = opposite(hd, mesh);
+
+ // little trick to go from border halfedge on one side of the seam to
+ // interior halfedge on the other side of the seam
+ CGAL_assertion(other_hd.seam);
+ other_hd.seam = false;
+
+ Cone_type ct = (target(hd, mesh) == source(other_hd, mesh)) ? Unique_cone
+ : Duplicated_cone;
+
+ std::cout << "new cone with type: " << ct << std::endl;
+
+ cones.insert(std::make_pair(vertex_on_seam, ct));
+ }
+ }
+
+ // move to the next vertex_descriptor on the seam
+ vertex_on_seam = source(halfedge(vertex_on_seam, mesh), mesh);
+ CGAL_assertion(mesh.has_on_seam(vertex_on_seam));
+
+ } while(vertex_on_seam != end);
+
+ CGAL_postcondition((cone_vds_in_sm.size() == 3 && cones.size() == 4) ||
+ (cone_vds_in_sm.size() == 4 && cones.size() == 6));
+
+ std::cout << cone_vds_in_sm.size() << " cones in sm" << std::endl;
+ std::cout << cones.size() << " cones in mesh" << std::endl;
+}
+
+} // namespace internal
+
+} // namespace Surface_mesh_parameterization
+
+} // namespace CGAL
+
+#endif // CGAL_SURFACE_MESH_PARAMETERIZATION_INTERNAL_CONE_HELPER_H