Improved existing SMP code

-Factorized the different tools to construct vertices and faces container in
a single class.
-Updated all examples accordingly and replaced the polylines output by an OFF
output across all files.
-Some other minor changes (missing includes, indentation, typos, etc.)
This commit is contained in:
Mael Rouxel-Labbé 2016-11-07 16:16:49 +01:00
parent eef01c2ac6
commit ae06b044ce
13 changed files with 256 additions and 352 deletions

View File

@ -1,10 +1,12 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/Polygon_mesh_processing/measure.h>
#include <CGAL/IO/Surface_mesh_parameterization/File_off.h>
#include <CGAL/parameterize.h>
#include <CGAL/Polygon_mesh_processing/measure.h>
#include <iostream>
#include <fstream>
@ -19,7 +21,11 @@ typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
int main(int argc, char * argv[])
{
std::ifstream in((argc>1)?argv[1]:"data/nefertiti.off");
std::ifstream in((argc>1)?argv[1]:"../data/mushroom_big_hole.off");
if(!in){
std::cerr << "Problem loading the input data" << std::endl;
return 1;
}
Mesh sm;
in >> sm;
@ -27,20 +33,12 @@ int main(int argc, char * argv[])
halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(sm).first;
CGAL::Unique_hash_map<vertex_descriptor,Point_2> uvhm;
boost::associative_property_map<CGAL::Unique_hash_map<vertex_descriptor,Point_2> > uvpm(uvhm);
boost::associative_property_map<CGAL::Unique_hash_map<vertex_descriptor,Point_2> > uvmap(uvhm);
CGAL::parameterize(sm, hd, uvpm);
CGAL::parameterize(sm, hd, uvmap);
// Write the result in the polyline format that can be loaded in the Polyhedron demo
std::ofstream out("result.off");
CGAL::Parameterization::output_uvmap_to_off(sm, hd, uvmap, out);
BOOST_FOREACH(face_descriptor fd, faces(sm)){
halfedge_descriptor hd = halfedge(fd,sm);
std::cout << "4 " << uvhm[target(hd,sm)] << " 0 ";
hd = next(hd,sm);
BOOST_FOREACH(vertex_descriptor vd, vertices_around_face(hd,sm)){
std::cout << uvhm[vd] << " 0 ";
}
std::cout << std::endl;
}
return 0;
}

View File

@ -1,7 +1,9 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/Seam_mesh.h>
#include <CGAL/IO/Surface_mesh_parameterization/File_off.h>
#include <CGAL/parameterize.h>
#include <CGAL/Two_vertices_parameterizer_3.h>
#include <CGAL/LSCM_parameterizer_3.h>
@ -21,9 +23,9 @@ typedef boost::graph_traits<SurfaceMesh>::edge_descriptor SM_edge_descriptor;
typedef boost::graph_traits<SurfaceMesh>::halfedge_descriptor SM_halfedge_descriptor;
typedef boost::graph_traits<SurfaceMesh>::vertex_descriptor SM_vertex_descriptor;
typedef SurfaceMesh::Property_map<SM_halfedge_descriptor,Point_2> UV_pmap;
typedef SurfaceMesh::Property_map<SM_edge_descriptor,bool> Seam_edge_pmap;
typedef SurfaceMesh::Property_map<SM_vertex_descriptor,bool> Seam_vertex_pmap;
typedef SurfaceMesh::Property_map<SM_halfedge_descriptor, Point_2> UV_pmap;
typedef SurfaceMesh::Property_map<SM_edge_descriptor, bool> Seam_edge_pmap;
typedef SurfaceMesh::Property_map<SM_vertex_descriptor, bool> Seam_vertex_pmap;
typedef CGAL::Seam_mesh<SurfaceMesh, Seam_edge_pmap, Seam_vertex_pmap> Mesh;
@ -31,35 +33,16 @@ typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
/// A helper class that writes a face as a polyline in the xy-plane
struct Face2Polyline
{
const Mesh& mesh;
const UV_pmap uvpm;
Face2Polyline(const Mesh& mesh, const UV_pmap& uvpm)
: mesh(mesh), uvpm(uvpm)
{ }
void operator()(face_descriptor fd) const
{
halfedge_descriptor hd = halfedge(fd,mesh);
std::cout << "4 " << uvpm[target(hd,mesh)].x() << " " << uvpm[target(hd,mesh)].y() << " 0 ";
hd = next(hd,mesh);
BOOST_FOREACH(vertex_descriptor vd, vertices_around_face(hd,mesh)){
std::cout << uvpm[vd].x() << " " << uvpm[vd].y() << " 0 ";
}
std::cout << std::endl;
}
};
int main(int argc, char * argv[])
{
SurfaceMesh sm;
std::ifstream in_mesh((argc>1)?argv[1]:"data/lion.off");
std::ifstream in_mesh((argc>1) ? argv[1] : "data/lion.off");
if(!in_mesh){
std::cerr << "Error: problem loading the input data" << std::endl;
return 1;
}
in_mesh >> sm;
// Two property maps to store the seam edges and vertices
@ -68,6 +51,7 @@ int main(int argc, char * argv[])
const char* filename = (argc>2) ? argv[2] : "data/lion.selection.txt";
// Read the constraints on the border
std::ifstream in(filename);
std::string vertices;
std::getline(in, vertices);
@ -90,14 +74,14 @@ int main(int argc, char * argv[])
halfedge_descriptor bhd(smhd);
bhd = opposite(bhd, mesh); // a halfedge on the virtual border
typedef CGAL::Two_vertices_parameterizer_3<Mesh> Border_parameterizer;
typedef CGAL::LSCM_parameterizer_3<Mesh, Border_parameterizer> Parameterizer;
typedef CGAL::Two_vertices_parameterizer_3<Mesh> Border_parameterizer;
typedef CGAL::LSCM_parameterizer_3<Mesh, Border_parameterizer> Parameterizer;
if(two_vertices_given){
SM_halfedge_descriptor smhp1 = halfedge(SM_vertex_descriptor(p1),sm);
SM_halfedge_descriptor smhp1 = halfedge(SM_vertex_descriptor(p1), sm);
vertex_descriptor vp1 = target(halfedge_descriptor(smhp1), mesh);
SM_halfedge_descriptor smhp2 = halfedge(SM_vertex_descriptor(p2),sm);
SM_halfedge_descriptor smhp2 = halfedge(SM_vertex_descriptor(p2), sm);
vertex_descriptor vp2 = target(halfedge_descriptor(smhp2), mesh);
CGAL::parameterize(mesh, Parameterizer(Border_parameterizer(vp1, vp2)), bhd, uv_pm);
@ -105,14 +89,7 @@ int main(int argc, char * argv[])
CGAL::parameterize(mesh, Parameterizer(), bhd, uv_pm);
}
std::ofstream out("/home/mrouxell/asd.polylines.txt");
Face2Polyline f2p(mesh, uv_pm, out);
// As the seam may define a patch we write
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(f2p));
CGAL::Parameterization::output_uvmap_to_off(mesh, bhd, uv_pm, std::cout);
return 0;
}

View File

@ -139,6 +139,8 @@ int main(int argc, char * argv[])
#ifdef MVC_POLY_MESH
{
std::cout << "MVC POLY MESH" << std::endl;
PMesh pm;
in >> pm;
@ -162,10 +164,15 @@ int main(int argc, char * argv[])
#ifdef BARY_POLY_MESH
{
std::cout << "BARY POLY MESH" << std::endl;
PMesh pm;
in.clear();
in.seekg(0, std::ios::beg);
in >> pm;
PM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(pm).first;
assert(hd != PM_halfedge_descriptor());
// UV map
CGAL::Unique_hash_map<PM_vertex_descriptor, Point_2,
@ -176,10 +183,12 @@ int main(int argc, char * argv[])
// Indices map
typedef boost::unordered_map<PM_vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(face(opposite(hd, pm), pm),
pm,
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(hd, pm), pm),
pm,
boost::make_function_output_iterator(
CGAL::Parameterization::Vertices<PMesh, Indices>(pm, indices)));
CGAL::internal::Parameterization::Index_map_filler<PMesh,
Indices>(pm, indices)));
// Vertex parameterized map
boost::unordered_set<PM_vertex_descriptor> vs;
@ -198,7 +207,11 @@ int main(int argc, char * argv[])
#ifdef ARAP_POLY_MESH
{
std::cout << "ARAP POLY MESH" << std::endl;
PMesh pm;
in.clear();
in.seekg(0, std::ios::beg);
in >> pm;
PM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(pm).first;
@ -217,8 +230,9 @@ int main(int argc, char * argv[])
face(opposite(hd, pm), pm),
pm,
boost::make_function_output_iterator(
CGAL::Parameterization::Vertices<PMesh,
Indices>(pm, indices)));
CGAL::internal::Parameterization::Index_map_filler<PMesh,
Indices>(pm, indices)));
boost::associative_property_map<Indices> vipm(indices);
// Vertex parameterized map
@ -247,6 +261,8 @@ int main(int argc, char * argv[])
#ifdef ARAP_SURF_MESH
{
std::cout << "ARAP SURF MESH" << std::endl;
SMesh sm;
in.clear();
in.seekg(0, std::ios::beg);
@ -263,14 +279,15 @@ int main(int argc, char * argv[])
boost::hash<SM_vertex_descriptor> > > uv_pm(uvhm);
// Indices map
typedef boost::unordered_map<SM_vertex_descriptor, int> Vertex_index_map;
Vertex_index_map indices;
typedef boost::unordered_map<SM_vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, sm), sm),
sm,
boost::make_function_output_iterator(
CGAL::Parameterization::Vertices<SMesh, Vertex_index_map>(sm, indices)));
boost::associative_property_map<Vertex_index_map> vipm(indices);
CGAL::internal::Parameterization::Index_map_filler<SMesh,
Indices>(sm, indices)));
boost::associative_property_map<Indices> vipm(indices);
boost::unordered_set<SM_vertex_descriptor> vs;
CGAL::internal::Bool_property_map< boost::unordered_set<SM_vertex_descriptor> > vpm(vs);
@ -286,6 +303,8 @@ int main(int argc, char * argv[])
#ifdef ARAP_SM_SEAM_MESH
{
std::cout << "ARAP SURF SEAM MESH" << std::endl;
SMesh sm;
in.clear();
in.seekg(0, std::ios::beg);
@ -294,7 +313,7 @@ int main(int argc, char * argv[])
SM_seam_edge_pmap seam_edge_pm =
sm.add_property_map<SM_edge_descriptor,bool>("e:on_seam", false).first;
SM_seam_vertex_pmap seam_vertex_pm =
sm.add_property_map<SM_vertex_descriptor,bool>("v:on_seam",false).first;
sm.add_property_map<SM_vertex_descriptor,bool>("v:on_seam", false).first;
SM_Seam_mesh mesh(sm, seam_edge_pm, seam_vertex_pm);
SM_halfedge_descriptor smhd = mesh.add_seams("../data/lion.selection.txt");
@ -312,10 +331,11 @@ int main(int argc, char * argv[])
typedef boost::unordered_map<SM_SE_vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
CGAL::Parameterization::Vertices<SM_Seam_mesh, Indices>(mesh, indices)));
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
CGAL::internal::Parameterization::Index_map_filler<SM_Seam_mesh,
Indices>(mesh, indices)));
boost::associative_property_map<Indices> vipm(indices);
// Parameterized
@ -334,6 +354,8 @@ int main(int argc, char * argv[])
#ifdef ARAP_PM_SEAM_MESH
{
std::cout << "ARAP POLY SEAM MESH" << std::endl;
PMesh pm;
in.clear();
in.seekg(0, std::ios::beg);
@ -360,10 +382,11 @@ int main(int argc, char * argv[])
typedef boost::unordered_map<PM_SE_vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
CGAL::Parameterization::Vertices<PM_Seam_mesh, Indices>(mesh, indices)));
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
CGAL::internal::Parameterization::Index_map_filler<PM_Seam_mesh,
Indices>(mesh, indices)));
boost::associative_property_map<Indices> vipm(indices);
// Parameterized

View File

@ -1,24 +1,28 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <CGAL/boost/graph/Seam_mesh.h>
#include <CGAL/boost/graph/graph_traits_Seam_mesh.h>
#include <CGAL/IO/Surface_mesh_parameterization/File_off.h>
#include <CGAL/parameterize.h>
#include <boost/foreach.hpp>
#include <iostream>
#include <fstream>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Kernel::Point_3> SurfaceMesh;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Kernel::Point_3> SurfaceMesh;
typedef boost::graph_traits<SurfaceMesh>::edge_descriptor SM_edge_descriptor;
typedef boost::graph_traits<SurfaceMesh>::halfedge_descriptor SM_halfedge_descriptor;
typedef boost::graph_traits<SurfaceMesh>::vertex_descriptor SM_vertex_descriptor;
typedef SurfaceMesh::Property_map<SM_halfedge_descriptor,Point_2> UV_pmap;
typedef SurfaceMesh::Property_map<SM_edge_descriptor,bool> Seam_edge_pmap;
typedef SurfaceMesh::Property_map<SM_vertex_descriptor,bool> Seam_vertex_pmap;
typedef SurfaceMesh::Property_map<SM_halfedge_descriptor, Point_2> UV_pmap;
typedef SurfaceMesh::Property_map<SM_edge_descriptor, bool> Seam_edge_pmap;
typedef SurfaceMesh::Property_map<SM_vertex_descriptor, bool> Seam_vertex_pmap;
typedef CGAL::Seam_mesh<SurfaceMesh, Seam_edge_pmap, Seam_vertex_pmap> Mesh;
@ -26,61 +30,30 @@ typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
/// A helper class that writes a face as a polyline in the xy-plane
struct Face2Polyline
{
const Mesh& mesh;
const UV_pmap uvpm;
Face2Polyline(const Mesh& mesh, const UV_pmap& uvpm)
: mesh(mesh), uvpm(uvpm)
{ }
void operator()(face_descriptor fd) const
{
halfedge_descriptor hd = halfedge(fd,mesh);
std::cout << "4 " << uvpm[target(hd,mesh)].x() << " "
<< uvpm[target(hd,mesh)].y() << " 0 ";
hd = next(hd,mesh);
BOOST_FOREACH(vertex_descriptor vd, vertices_around_face(hd,mesh)){
std::cout << uvpm[vd].x() << " " << uvpm[vd].y() << " 0 ";
}
std::cout << std::endl;
}
};
int main(int argc, char * argv[])
{
SurfaceMesh sm;
std::vector<SM_edge_descriptor> seam;
std::ifstream in_mesh((argc>1)?argv[1]:"data/lion.off");
if(!in_mesh){
std::cerr << "Error: problem loading the input data" << std::endl;
return 1;
}
in_mesh >> sm;
// Two property maps to store the seam edges and vertices
Seam_edge_pmap seam_edge_pm = sm.add_property_map<SM_edge_descriptor,bool>("e:on_seam", false).first;
Seam_vertex_pmap seam_vertex_pm = sm.add_property_map<SM_vertex_descriptor,bool>("v:on_seam",false).first;
std::ifstream in((argc>2)?argv[2]:"data/lion.selection.txt");
int s, t;
SM_halfedge_descriptor smhd;
while(in >> s >> t){
SM_vertex_descriptor svd(s), tvd(t);
SM_edge_descriptor ed = edge(svd, tvd,sm).first;
if(! is_border(ed,sm)){
put(seam_edge_pm, ed, true);
put(seam_vertex_pm, svd, true);
put(seam_vertex_pm, tvd, true);
if(smhd == boost::graph_traits<SurfaceMesh>::null_halfedge()){
smhd = halfedge(edge(svd,tvd,sm).first,sm);
}
}
}
Seam_edge_pmap seam_edge_pm =
sm.add_property_map<SM_edge_descriptor,bool>("e:on_seam", false).first;
Seam_vertex_pmap seam_vertex_pm =
sm.add_property_map<SM_vertex_descriptor,bool>("v:on_seam",false).first;
Mesh mesh(sm, seam_edge_pm, seam_vertex_pm);
const char* filename = (argc>2) ? argv[2] : "/data/lion.selection.txt";
SM_halfedge_descriptor smhd = mesh.add_seams(filename);
assert(smhd != SM_halfedge_descriptor());
// The 2D points of the uv parametrisation will be written into this map
// Note that this is a halfedge property map, and that the uv
// is only stored for the canonical halfedges representing a vertex
@ -91,12 +64,7 @@ int main(int argc, char * argv[])
CGAL::parameterize(mesh, bhd, uv_pm);
Face2Polyline f2p(mesh,uv_pm);
// As the seam may define a patch we write
CGAL::Polygon_mesh_processing::connected_component(face(opposite(bhd,mesh),mesh),
mesh,
boost::make_function_output_iterator(f2p));
CGAL::Parameterization::output_uvmap_to_off(mesh, bhd, uv_pm, std::cout);
return 0;
}

View File

@ -1,76 +1,53 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/boost/graph/Seam_mesh.h>
#include <CGAL/boost/graph/graph_traits_Seam_mesh.h>
#include <CGAL/IO/Surface_mesh_parameterization/File_off.h>
#include <CGAL/parameterize.h>
#include <CGAL/Unique_hash_map.h>
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
#include <fstream>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Polyhedron_3<Kernel> SurfaceMesh;
typedef CGAL::Polyhedron_3<Kernel> PolyMesh;
typedef boost::graph_traits<SurfaceMesh>::edge_descriptor SM_edge_descriptor;
typedef boost::graph_traits<SurfaceMesh>::halfedge_descriptor SM_halfedge_descriptor;
typedef boost::graph_traits<SurfaceMesh>::vertex_descriptor SM_vertex_descriptor;
typedef boost::graph_traits<PolyMesh>::edge_descriptor SM_edge_descriptor;
typedef boost::graph_traits<PolyMesh>::halfedge_descriptor SM_halfedge_descriptor;
typedef boost::graph_traits<PolyMesh>::vertex_descriptor SM_vertex_descriptor;
typedef CGAL::Unique_hash_map<SM_halfedge_descriptor,Point_2> UV_uhm;
typedef CGAL::Unique_hash_map<SM_edge_descriptor,bool> Seam_edge_uhm;
typedef CGAL::Unique_hash_map<SM_vertex_descriptor,bool> Seam_vertex_uhm;
typedef CGAL::Unique_hash_map<SM_halfedge_descriptor, Point_2> UV_uhm;
typedef CGAL::Unique_hash_map<SM_edge_descriptor, bool> Seam_edge_uhm;
typedef CGAL::Unique_hash_map<SM_vertex_descriptor, bool> Seam_vertex_uhm;
typedef boost::associative_property_map<UV_uhm> UV_pmap;
typedef boost::associative_property_map<Seam_edge_uhm> Seam_edge_pmap;
typedef boost::associative_property_map<Seam_vertex_uhm> Seam_vertex_pmap;
typedef CGAL::Seam_mesh<SurfaceMesh, Seam_edge_pmap, Seam_vertex_pmap> Mesh;
typedef CGAL::Seam_mesh<PolyMesh, Seam_edge_pmap, Seam_vertex_pmap> Mesh;
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
/// A helper class that writes a face as a polyline in the xy-plane
struct Face2Polyline
{
const Mesh& mesh;
const UV_pmap uvpm;
Face2Polyline(const Mesh& mesh, const UV_pmap& uvpm)
: mesh(mesh), uvpm(uvpm)
{ }
void operator()(face_descriptor fd) const
{
halfedge_descriptor hd = halfedge(fd,mesh);
std::cout << "4 " << uvpm[target(hd,mesh)].x()
<< " " << uvpm[target(hd,mesh)].y() << " 0 ";
hd = next(hd,mesh);
BOOST_FOREACH(vertex_descriptor vd, vertices_around_face(hd,mesh)){
std::cout << uvpm[vd].x() << " " << uvpm[vd].y() << " 0 ";
}
std::cout << std::endl;
}
};
int main(int argc, char * argv[])
{
SurfaceMesh sm;
PolyMesh sm;
std::ifstream in_mesh((argc>1)?argv[1]:"data/lion.off");
in_mesh >> sm;
std::vector<SM_vertex_descriptor> id2v;
BOOST_FOREACH(SM_vertex_descriptor vd, vertices(sm)){
id2v.push_back(vd);
if(!in_mesh){
std::cerr << "Error: problem loading the input data" << std::endl;
return 1;
}
in_mesh >> sm;
// Two property maps to store the seam edges and vertices
Seam_edge_uhm seam_edge_uhm(false);
Seam_edge_pmap seam_edge_pm(seam_edge_uhm);
@ -78,28 +55,15 @@ int main(int argc, char * argv[])
Seam_vertex_uhm seam_vertex_uhm(false);
Seam_vertex_pmap seam_vertex_pm(seam_vertex_uhm);
std::ifstream in((argc>2)?argv[2]:"data/lion.selection.txt");
int s, t;
SM_halfedge_descriptor smhd;
while(in >> s >> t){
SM_vertex_descriptor svd = id2v[s], tvd = id2v[t];
SM_edge_descriptor ed = edge(svd, tvd,sm).first;
if(!is_border(ed,sm)){
put(seam_edge_pm, ed, true);
put(seam_vertex_pm, svd, true);
put(seam_vertex_pm, tvd, true);
if(smhd == boost::graph_traits<SurfaceMesh>::null_halfedge()){
smhd = halfedge(edge(svd,tvd,sm).first,sm);
}
}
}
Mesh mesh(sm, seam_edge_pm, seam_vertex_pm);
const char* filename = (argc>2) ? argv[2] : "data/lion.selection.txt";
SM_halfedge_descriptor smhd = mesh.add_seams(filename);
assert(smhd != SM_halfedge_descriptor());
// The 2D points of the uv parametrisation will be written into this map
// Note that this is a halfedge property map, and that the uv
// is only stored for the canonical halfedges representing a vertex
UV_uhm uv_uhm;
UV_pmap uv_pm(uv_uhm);
@ -108,12 +72,7 @@ int main(int argc, char * argv[])
CGAL::parameterize(mesh, bhd, uv_pm);
Face2Polyline f2p(mesh,uv_pm);
// The seam may define a patch, that is we take the connected component of the border halfedge
CGAL::Polygon_mesh_processing::connected_component(face(opposite(bhd,mesh),mesh),
mesh,
boost::make_function_output_iterator(f2p));
CGAL::Parameterization::output_uvmap_to_off(mesh, bhd, uv_pm, std::cout);
return 0;
}

View File

@ -63,10 +63,8 @@
// (this produces C2=0 which is problematic to compute a & b)
// @todo Add to the polyhedron demo
// @todo Add distortion measures
// @todo remove the requirements on the vimap from all parameterizers
// @todo is_one_to_one mapping functions in all parameterizers
// @todo Use a boost array for the roots?
// @todo The two systems A Xu = Bu and A Xv = BV could be merged in one system
// using complex numbers?
// @todo Parallelize the local phase?
@ -237,8 +235,8 @@ private:
const VertexIndexMap vimap) const
{
std::ofstream out(filename.c_str());
CGAL::Surface_mesh_parameterization::output_uvmap_to_off(mesh, vertices, faces,
uvmap, vimap, out);
CGAL::Parameterization::output_uvmap_to_off(mesh, vertices, faces,
uvmap, vimap, out);
}
/// Print the parameterized mesh.
@ -255,8 +253,8 @@ private:
std::ostringstream out_ss;
out_ss << filename << iter << ".off" << std::ends;
std::ofstream out(out_ss.str().c_str());
CGAL::Surface_mesh_parameterization::output_uvmap_to_off(mesh, vertices, faces,
uvmap, vimap, out);
CGAL::Parameterization::output_uvmap_to_off(mesh, vertices, faces,
uvmap, vimap, out);
}
/// Copy the data from two vectors to the UVmap.
@ -284,8 +282,8 @@ private:
Vertex_set& vertices,
Faces_vector& faces) const
{
CGAL::internal::Surface_mesh_parameterization::Containers_filler<TriangleMesh>
fc(mesh, faces, vertices);
CGAL::internal::Parameterization::Containers_filler<TriangleMesh>
fc(mesh, vertices, &faces);
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
@ -1366,7 +1364,7 @@ public:
output_uvmap("ARAP_final_pre_processing.off", mesh, vertices, faces, uvmap, vimap);
if(!internal::Surface_mesh_parameterization::is_one_to_one_mapping(mesh, uvmap)){
if(!internal::Parameterization::is_one_to_one_mapping(mesh, uvmap)){
// Use post processing to handle flipped elements
std::cout << "Parameterization is not valid; calling post processor" << std::endl;
status = post_process(mesh, vertices, faces, bhd, uvmap, vimap);

View File

@ -24,17 +24,20 @@
#include <CGAL/license/Surface_mesh_parameterization.h>
#include <CGAL/circulator.h>
#include <CGAL/Eigen_solver_traits.h>
#include <CGAL/internal/Surface_mesh_parameterization/Containers_filler.h>
#include <CGAL/Parameterizer_traits_3.h>
#include <CGAL/Circular_border_parameterizer_3.h>
#include <CGAL/circulator.h>
#include <CGAL/Eigen_solver_traits.h>
#include <CGAL/Polygon_mesh_processing/connected_components.h>
#include <boost/foreach.hpp>
#include <iostream>
#include <boost/function_output_iterator.hpp>
#include <boost/unordered_set.hpp>
#include <CGAL/Polygon_mesh_processing/connected_components.h>
#include <boost/function_output_iterator.hpp>
#include <iostream>
/// \file Fixed_border_parameterizer_3.h
@ -287,29 +290,6 @@ private:
Sparse_LA m_linearAlgebra;
};
namespace Parameterization {
template <typename Mesh, typename Set>
struct Vertices_set {
Vertices_set(const Mesh& mesh, Set& set)
: mesh(mesh), set(&set)
{}
void operator()(const typename boost::graph_traits<Mesh>::face_descriptor& fd)
{
BOOST_FOREACH(typename boost::graph_traits<Mesh>::vertex_descriptor vd, vertices_around_face(halfedge(fd,mesh),mesh)){
set->insert(vd);
}
}
const Mesh& mesh;
mutable Set* set;
};
} // namespace Parameterization
// ------------------------------------------------------------------------------------
// Implementation
// ------------------------------------------------------------------------------------
@ -351,11 +331,12 @@ parameterize(TriangleMesh& mesh,
typedef boost::unordered_set<vertex_descriptor> Vertex_set;
Vertex_set vertices;
CGAL::internal::Parameterization::Containers_filler<TriangleMesh> fc(mesh, vertices);
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
Parameterization::Vertices_set<TriangleMesh, Vertex_set>(mesh, vertices)));
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(fc));
// Count vertices
int nbVertices = static_cast<int>(num_vertices(mesh));

View File

@ -18,11 +18,18 @@
//
// Author(s) :
#include <CGAL/internal/Surface_mesh_parameterization/Containers_filler.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Polygon_mesh_processing/connected_components.h>
#include <CGAL/circulator.h>
#include <boost/foreach.hpp>
#include <boost/function_output_iterator.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/unordered/unordered_map.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <cstddef>
#include <fstream>
@ -34,7 +41,7 @@
namespace CGAL {
namespace Surface_mesh_parameterization {
namespace Parameterization {
template <typename TriangleMesh,
typename VertexContainer,
@ -83,8 +90,10 @@ void output_uvmap_to_off(const TriangleMesh& mesh,
}
template <typename TriangleMesh,
typename HD,
typename VertexUVMap>
void output_uvmap_to_off(const TriangleMesh& mesh,
HD bhd,
const VertexUVMap uvmap,
std::ostream& os)
{
@ -96,15 +105,24 @@ void output_uvmap_to_off(const TriangleMesh& mesh,
Vertex_index_map vium;
boost::associative_property_map<Vertex_index_map> vimap(vium);
boost::unordered_set<vertex_descriptor> vertices;
std::vector<face_descriptor> faces;
CGAL::internal::Parameterization::Containers_filler<TriangleMesh> fc(mesh, vertices, &faces);
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(fc));
std::ostringstream out_vertices, out_faces;
std::size_t vertices_counter = 0, faces_counter = 0;
BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)){
BOOST_FOREACH(vertex_descriptor vd, vertices){
put(vimap, vd, vertices_counter++);
out_vertices << get(uvmap, vd) << " 0" << '\n';
}
BOOST_FOREACH(face_descriptor fd, faces(mesh)){
BOOST_FOREACH(face_descriptor fd, faces){
halfedge_descriptor hd = halfedge(fd, mesh);
out_faces << "3";
@ -121,7 +139,7 @@ void output_uvmap_to_off(const TriangleMesh& mesh,
os << out_vertices.str() << out_faces.str();
}
} // namespace Surface_mesh_parameterization
} // namespace Parameterization
} // namespace CGAL

View File

@ -180,9 +180,6 @@ public:
// Count vertices
int nbVertices = num_vertices(mesh);
// Index vertices from 0 to nbVertices-1
// TODO mesh.index_mesh_vertices();
// Compute (u,v) for (at least two) border vertices
// and mark them as "parameterized"
Error_code status = get_border_parameterizer().parameterize_border(mesh,bhd,uvmap,vpmap);
@ -201,14 +198,17 @@ public:
// Fill the matrix for the other vertices
solver.begin_system();
std::vector<face_descriptor> ccfaces;
boost::unordered_set<vertex_descriptor> ccvertices;
CGAL::internal::Surface_mesh_parameterization::Containers_filler<TriangleMesh>
fc(mesh, ccfaces, ccvertices);
std::vector<face_descriptor> ccfaces;
CGAL::internal::Parameterization::Containers_filler<TriangleMesh>
fc(mesh, ccvertices, &ccfaces);
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd,mesh), mesh),
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(fc));
BOOST_FOREACH(face_descriptor fd, ccfaces){
// Create two lines in the linear system per triangle (one for u, one for v)
status = setup_triangle_relations(solver, mesh, fd, vimap);

View File

@ -190,8 +190,8 @@ private:
Vertex_set& vertices,
Faces_vector& faces) const
{
CGAL::internal::Surface_mesh_parameterization::Containers_filler<TriangleMesh>
fc(mesh, faces, vertices);
internal::Parameterization::Containers_filler<TriangleMesh>
fc(mesh, vertices, &faces);
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,

View File

@ -22,6 +22,7 @@
#define CGAL_INTERNAL_SURFACE_MESH_PARAMETERIZATION_CONTAINERS_FILLER_H
#include <boost/foreach.hpp>
#include "boost/tuple/tuple.hpp"
#include <boost/unordered_set.hpp>
#include <vector>
@ -30,40 +31,78 @@ namespace CGAL {
namespace internal {
namespace Surface_mesh_parameterization {
namespace Parameterization {
// Custom output iterator that fills 'faces' and 'vertices' containers from a mesh
template<typename TriangleMesh>
template<typename TriangleMesh,
typename Vertex_set =
boost::unordered_set<typename boost::graph_traits<TriangleMesh>::vertex_descriptor>,
typename Face_vector =
std::vector<typename boost::graph_traits<TriangleMesh>::face_descriptor> >
class Containers_filler
{
typedef typename boost::graph_traits<TriangleMesh>::face_descriptor
face_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor
vertex_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::face_descriptor face_descriptor;
const TriangleMesh& mesh;
std::vector<face_descriptor>& faces;
boost::unordered_set<vertex_descriptor>& vertices;
Vertex_set& vertices;
Face_vector* faces;
public:
Containers_filler(const TriangleMesh& mesh,
std::vector<face_descriptor>& faces,
boost::unordered_set<vertex_descriptor>& vertices)
: mesh(mesh), faces(faces), vertices(vertices)
Containers_filler(const TriangleMesh& mesh_,
Vertex_set& vertices_,
Face_vector* faces_)
: mesh(mesh_), vertices(vertices_), faces(faces_)
{ }
Containers_filler(const TriangleMesh& mesh_,
Vertex_set& vertices_)
: mesh(mesh_), vertices(vertices_), faces(NULL)
{ }
void operator()(face_descriptor fd)
{
typename boost::graph_traits<TriangleMesh>::halfedge_descriptor hd =
halfedge(fd,mesh);
halfedge_descriptor hd = halfedge(fd, mesh);
BOOST_FOREACH(vertex_descriptor vd, vertices_around_face(hd, mesh)){
vertices.insert(vd);
}
faces.push_back(fd);
if(faces != NULL)
faces->push_back(fd);
}
};
} // namespace Surface_mesh_parameterization
template <typename Mesh, typename Map>
struct Index_map_filler
{
typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor;
Index_map_filler(const Mesh& mesh, Map& map)
: mesh(mesh), map(&map), index(0)
{ }
void operator()(const face_descriptor& fd)
{
BOOST_FOREACH(vertex_descriptor vd,
vertices_around_face(halfedge(fd, mesh), mesh)){
typename Map::iterator it;
bool new_element;
boost::tie(it,new_element) = map->insert(std::make_pair(vd,1));
if(new_element){
it->second = index++;
}
}
}
const Mesh& mesh;
mutable Map* map;
int index;
};
} // namespace Parameterization
} // namespace internal

View File

@ -36,7 +36,7 @@ namespace CGAL {
namespace internal {
namespace Surface_mesh_parameterization {
namespace Parameterization {
template<typename TriangleMesh, typename VertexUVMap>
bool has_flips(const TriangleMesh& mesh,
@ -293,7 +293,7 @@ bool is_one_to_one_mapping(const TriangleMesh& mesh,
return (counter == 0);
}
} // namespace Surface_mesh_parameterization
} // namespace Parameterization
} // namespace internal

View File

@ -72,37 +72,6 @@ private:
} // namespace internal
namespace Parameterization {
template <typename Mesh, typename Map>
struct Vertices {
Vertices(const Mesh& mesh, Map& map)
: mesh(mesh), map(&map), index(0)
{ }
void operator()(const typename boost::graph_traits<Mesh>::face_descriptor& fd)
{
BOOST_FOREACH(typename boost::graph_traits<Mesh>::vertex_descriptor vd,
vertices_around_face(halfedge(fd,mesh),mesh)){
typename Map::iterator it;
bool new_element;
boost::tie(it,new_element) = map->insert(std::make_pair(vd,1));
if(new_element){
it->second = index++;
}
}
}
const Mesh& mesh;
mutable Map* map;
int index;
};
} // namespace Parameterization
/// \ingroup PkgSurfaceParameterizationMainFunction
///
/// Compute a one-to-one mapping from a 3D triangle surface `mesh` to a
@ -138,20 +107,23 @@ parameterize(TriangleMesh& mesh,
VertexUVmap uvm)
{
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
typedef boost::unordered_map<vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
internal::Parameterization::Index_map_filler<TriangleMesh,
Indices>(mesh, indices)));
boost::associative_property_map<Indices> vipm(indices);
boost::unordered_set<vertex_descriptor> vs;
internal::Bool_property_map<boost::unordered_set<vertex_descriptor> > vpm(vs);
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd,mesh),mesh),
mesh,
boost::make_function_output_iterator(
Parameterization::Vertices<TriangleMesh,Indices>(mesh,indices)));
return parameterizer.parameterize(mesh, bhd, uvm, boost::make_assoc_property_map(indices), vpm);
return parameterizer.parameterize(mesh, bhd, uvm, vipm, vpm);
}
/// \ingroup PkgSurfaceParameterizationMainFunction
///
/// Compute a one-to-one mapping from a 3D triangle surface `mesh` to a
@ -180,53 +152,13 @@ parameterize(TriangleMesh& mesh,
HD bhd,
VertexUVmap uvm)
{
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
boost::unordered_set<vertex_descriptor> vs;
internal::Bool_property_map<boost::unordered_set<vertex_descriptor> > vpm(vs);
typedef boost::unordered_map<vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
Parameterization::Vertices<TriangleMesh,Indices>(mesh, indices)));
Mean_value_coordinates_parameterizer_3<TriangleMesh> parameterizer;
return parameterizer.parameterize(mesh, bhd, uvm, boost::make_assoc_property_map(indices), vpm);
return Parameterizer_traits_3<TriangleMesh>::OK;
return CGAL::parameterize(mesh, parameterizer, bhd, uvm);
}
template <class TM, class SEM, class SVM>
class Seam_mesh;
template <class TM, class SEM, class SVM, class HD, class VertexUVmap>
typename Parameterizer_traits_3<Seam_mesh<TM, SEM, SVM> >::Error_code
parameterize(Seam_mesh<TM, SEM, SVM>& mesh,
HD bhd,
VertexUVmap uvm)
{
typedef typename boost::graph_traits<Seam_mesh<TM, SEM, SVM> >::vertex_descriptor vertex_descriptor;
boost::unordered_set<vertex_descriptor> vs;
internal::Bool_property_map<boost::unordered_set<vertex_descriptor> > vpm(vs);
typedef boost::unordered_map<vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
Parameterization::Vertices<Seam_mesh<TM, SEM, SVM>, Indices>(mesh, indices)));
boost::associative_property_map<Indices> vipm(indices);
Mean_value_coordinates_parameterizer_3<Seam_mesh<TM, SEM, SVM> > parameterizer;
return parameterizer.parameterize(mesh, bhd, uvm, vipm, vpm);
}
template <class TM, class SEM, class SVM, class Parameterizer, class HD, class VertexUVmap>
typename Parameterizer_traits_3<Seam_mesh<TM, SEM, SVM> >::Error_code
parameterize(Seam_mesh<TM, SEM, SVM>& mesh,
@ -241,15 +173,26 @@ parameterize(Seam_mesh<TM, SEM, SVM>& mesh,
typedef boost::unordered_map<vertex_descriptor, int> Indices;
Indices indices;
CGAL::Polygon_mesh_processing::connected_component(
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
Parameterization::Vertices<Seam_mesh<TM, SEM, SVM>, Indices>(mesh, indices)));
face(opposite(bhd, mesh), mesh),
mesh,
boost::make_function_output_iterator(
internal::Parameterization::Index_map_filler<Seam_mesh<TM, SEM, SVM>,
Indices>(mesh, indices)));
boost::associative_property_map<Indices> vipm(indices);
return parameterizer.parameterize(mesh, bhd, uvm, vipm, vpm);
}
template <class TM, class SEM, class SVM, class HD, class VertexUVmap>
typename Parameterizer_traits_3<Seam_mesh<TM, SEM, SVM> >::Error_code
parameterize(Seam_mesh<TM, SEM, SVM>& mesh,
HD bhd,
VertexUVmap uvm)
{
Mean_value_coordinates_parameterizer_3<Seam_mesh<TM, SEM, SVM> > parameterizer;
return CGAL::parameterize(mesh, parameterizer, bhd, uvm);
}
} // namespace CGAL
#endif // CGAL_PARAMETERIZE_H