1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#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 <unordered_set>
#include <cstdlib>
#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> PolyMesh;
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 std::array<vertex_descriptor, 4> Vd_array;
typedef CGAL::Unique_hash_map<vertex_descriptor, Point_2> UV_uhm;
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.length()) < 14 || (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;
}
// The selection file is a list of integers, so we must build a correspondence
// between vertices and the integers.
std::vector<vertex_descriptor> vds;
vds.reserve(num_vertices(mesh));
vertex_iterator vi = vertices(mesh).begin(), vi_end = vertices(mesh).end();
CGAL_For_all(vi, vi_end) {
vds.push_back(*vi);
}
// Get the first line and read the fixed vertex indices
std::size_t counter = 0;
std::istringstream point_line(line);
std::size_t s;
std::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];
if(!is_border(vd, mesh)) { // must be on the border
std::cerr << "Error: vertex is not on the border of the mesh" << std::endl;
return false;
}
if(counter >= 4) { // too many border vertices
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] : CGAL::data_file_path("meshes/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;
// The 2D points of the uv parametrisation will be written into this map
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 EXIT_FAILURE;
}
typedef SMP::Square_border_uniform_parameterizer_3<PolyMesh> Border_parameterizer;
typedef SMP::Discrete_conformal_map_parameterizer_3<PolyMesh, Border_parameterizer> Parameterizer;
// Border parameterizers (pick one)
Border_parameterizer border_param(vda[0], vda[1], vda[2], vda[3]);
// Border_parameterizer border_param; // the border parameterizer will compute the corner vertices
SMP::Error_code err = SMP::parameterize(sm, Parameterizer(border_param), bhd, uv_map);
if(err != SMP::OK) {
std::cerr << "Error: " << SMP::get_error_message(err) << std::endl;
return 1;
}
std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out);
return EXIT_SUCCESS;
}
|