#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Surface_mesh_parameterization/IO/File_off.h>
#include <CGAL/Surface_mesh_parameterization/Square_border_parameterizer_3.h>
#include <CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h>
#include <CGAL/Surface_mesh_parameterization/parameterize.h>
#include <CGAL/Polygon_mesh_processing/measure.h>
#include <CGAL/Unique_hash_map.h>
#include <boost/array.hpp>
#include <boost/foreach.hpp>
#include <boost/unordered_set.hpp>
#include <cstdlib>
#include <iostream>
#include <fstream>
typedef boost::graph_traits<PolyMesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<PolyMesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<PolyMesh>::face_descriptor face_descriptor;
typedef boost::graph_traits<PolyMesh>::vertex_iterator vertex_iterator;
typedef boost::array<vertex_descriptor, 4> Vd_array;
typedef boost::associative_property_map<UV_uhm> UV_pmap;
namespace SMP = CGAL::Surface_mesh_parameterization;
bool read_vertices(const PolyMesh& mesh,
const char* filename,
Vd_array& fixed_vertices)
{
std::string str = filename;
if(str.substr(str.length() - 14) != ".selection.txt") {
std::cerr << "Error: vertices must be given by a *.selection.txt file" << std::endl;
return false;
}
std::ifstream in(filename);
std::string line;
if(!std::getline(in, line)) {
std::cerr << "Error: could not read input file: " << filename << std::endl;
return false;
}
std::vector<vertex_descriptor> vds;
vds.reserve(num_vertices(mesh));
vertex_iterator vi = vertices(mesh).begin(), vi_end = vertices(mesh).end();
vds.push_back(*vi);
}
std::size_t counter = 0;
std::istringstream point_line(line);
std::size_t s;
boost::unordered_set<std::size_t> indices;
while(point_line >> s) {
if(s >= vds.size())
{
std::cerr << "Error: Vertex index too large" << std::endl;
return false;
}
vertex_descriptor vd = vds[s];
std::cerr << "Error: vertex is not on the border of the mesh" << std::endl;
return false;
}
if(counter >= 4) {
std::cerr << "Error: Too many vertices are fixed" << std::endl;
return false;
}
fixed_vertices[counter++] = vd;
indices.insert(s);
}
if(indices.size() < 4) {
std::cerr << "Error: at least four unique vertices must be provided" << std::endl;
return false;
}
return true;
}
int main(int argc, char * argv[])
{
std::ifstream in((argc>1) ? argv[1] : "data/nefertiti.off");
if(!in){
std::cerr << "Error: problem loading the input data" << std::endl;
return 1;
}
PolyMesh sm;
in >> sm;
halfedge_descriptor bhd = CGAL::Polygon_mesh_processing::longest_border(sm).first;
UV_uhm uv_uhm;
UV_pmap uv_map(uv_uhm);
const char* filename = (argc > 2) ? argv[2] : "data/square_corners.selection.txt";
Vd_array vda;
if(!read_vertices(sm, filename, vda)) {
std::cerr << "Error: problem loading the square corners" << std::endl;
return 1;
}
typedef SMP::Square_border_uniform_parameterizer_3<PolyMesh> Border_parameterizer;
typedef SMP::Discrete_conformal_map_parameterizer_3<PolyMesh, Border_parameterizer> Parameterizer;
Border_parameterizer border_param(vda[0], vda[1], vda[2], vda[3]);
return 1;
}
std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out);
return 0;
}