#include <CGAL/Simple_cartesian.h>
#include <CGAL/Monge_via_jet_fitting.h>
#include <fstream>
#include <cassert>
#include <CGAL/property_map.h>
#if defined(CGAL_USE_BOOST_PROGRAM_OPTIONS) && ! defined(DONT_USE_BOOST_PROGRAM_OPTIONS)
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#endif
using namespace std;
#include "PolyhedralSurf.h"
#include "PolyhedralSurf_operations.h"
#include "PolyhedralSurf_rings.h"
typedef double DFT;
typedef Data_Kernel::Point_3 DPoint;
typedef Data_Kernel::Vector_3 DVector;
typedef PolyhedralSurf::Vertex_handle Vertex_handle;
typedef PolyhedralSurf::Vertex Vertex;
typedef PolyhedralSurf::Halfedge_handle Halfedge_handle;
typedef PolyhedralSurf::Halfedge Halfedge;
typedef PolyhedralSurf::Vertex_iterator Vertex_iterator;
typedef PolyhedralSurf::Facet_handle Facet_handle;
typedef PolyhedralSurf::Facet Facet;
struct Hedge_cmp{
bool operator()(Halfedge_handle a, Halfedge_handle b) const{
return &*a < &*b;
}
};
struct Facet_cmp{
bool operator()(Facet_handle a, Facet_handle b) const{
return &*a < &*b;
}
};
typedef std::map<Vertex*, int> Vertex2int_map_type;
typedef boost::associative_property_map< Vertex2int_map_type > Vertex_PM_type;
typedef T_PolyhedralSurf_rings<PolyhedralSurf, Vertex_PM_type > Poly_rings;
typedef std::map<Halfedge_handle, double, Hedge_cmp> Hedge2double_map_type;
typedef boost::associative_property_map<Hedge2double_map_type> Hedge_PM_type;
typedef T_PolyhedralSurf_hedge_ops<PolyhedralSurf, Hedge_PM_type> Poly_hedge_ops;
typedef std::map<Facet_handle, Vector_3, Facet_cmp> Facet2normal_map_type;
typedef boost::associative_property_map<Facet2normal_map_type> Facet_PM_type;
typedef T_PolyhedralSurf_facet_ops<PolyhedralSurf, Facet_PM_type> Poly_facet_ops;
typedef double LFT;
typedef My_Monge_via_jet_fitting::Monge_form My_Monge_form;
unsigned int d_fitting = 2;
unsigned int d_monge = 2;
unsigned int nb_rings = 0;
unsigned int nb_points_to_use = 0;
bool verbose = false;
unsigned int min_nb_points = (d_fitting + 1) * (d_fitting + 2) / 2;
void gather_fitting_points(Vertex* v,
std::vector<DPoint> &in_points,
Vertex_PM_type& vpm)
{
std::vector<Vertex*> gathered;
in_points.clear();
if ( nb_points_to_use != 0 ) {
Poly_rings::collect_enough_rings(v, nb_points_to_use, gathered, vpm);
if ( gathered.size() > nb_points_to_use ) gathered.resize(nb_points_to_use);
}
else {
if ( nb_rings == 0 )
Poly_rings::collect_enough_rings(v, min_nb_points, gathered, vpm);
else Poly_rings::collect_i_rings(v, nb_rings, gathered, vpm);
}
std::vector<Vertex*>::iterator
itb = gathered.begin(), ite = gathered.end();
}
#if defined(CGAL_USE_BOOST_PROGRAM_OPTIONS) && ! defined(DONT_USE_BOOST_PROGRAM_OPTIONS)
int main(int argc, char *argv[])
#else
int main()
#endif
{
string if_name_string;
string if_name;
string w_if_name;
string res4openGL_fname;
string verbose_fname;
std::ofstream out_4ogl, out_verbose;
try {
#if defined(CGAL_USE_BOOST_PROGRAM_OPTIONS) && ! defined(DONT_USE_BOOST_PROGRAM_OPTIONS)
po::options_description desc("Allowed options");
desc.add_options()
("help,h", "produce help message.")
("input-file,f", po::value<string>(&if_name_string)->default_value("data/ellipe0.003.off"),
"name of the input off file")
("degree-jet,d", po::value<unsigned int>(&d_fitting)->default_value(2),
"degree of the jet, 1 <= degre-jet <= 4")
("degree-monge,m", po::value<unsigned int>(&d_monge)->default_value(2),
"degree of the Monge rep, 1 <= degree-monge <= degree-jet")
("nb-rings,a", po::value<unsigned int>(&nb_rings)->default_value(0),
"number of rings to collect neighbors. 0 means collect enough rings to make appro possible a>=1 fixes the nb of rings to be collected")
("nb-points,p", po::value<unsigned int>(&nb_points_to_use)->default_value(0),
"number of neighbors to use. 0 means this option is not considered, this is the default p>=1 fixes the nb of points to be used")
("verbose,v", po::value<bool>(&verbose)->default_value(false),
"verbose output on text file")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
cout << desc << "\n";
return 1;
}
#else
std::cerr << "Command-line options require Boost.ProgramOptions" << std::endl;
if_name_string = "data/ellipe0.003.off";
d_fitting = 2;
d_monge = 2;
nb_rings = 0;
nb_points_to_use = 0;
verbose = false;
#endif
}
catch(exception& e) {
cerr << "error: " << e.what() << "\n";
return 1;
}
catch(...) {
cerr << "Exception of unknown type!\n";
}
min_nb_points = (d_fitting + 1) * (d_fitting + 2) / 2;
if (nb_points_to_use < min_nb_points && nb_points_to_use != 0)
{std::cerr << "the nb of points asked is not enough to perform the fitting" << std::endl; exit(0);}
std::cerr << "if_name_string" << if_name_string << std::endl;
if_name = if_name_string;
w_if_name = if_name;
for(unsigned int i=0; i<w_if_name.size(); i++)
if (w_if_name[i] == '/') w_if_name[i]='_';
cerr << if_name << '\n';
cerr << w_if_name << '\n';
res4openGL_fname = w_if_name + ".4ogl.txt";
std::cerr << "res4openGL_fname" << res4openGL_fname << std::endl;
out_4ogl.open(res4openGL_fname.c_str(), std::ios::out);
assert(out_4ogl.good());
if(verbose){
verbose_fname = w_if_name + ".verb.txt";
out_verbose.open(verbose_fname.c_str(), std::ios::out);
assert(out_verbose.good());
}
unsigned int nb_vertices_considered = 0;
PolyhedralSurf P;
std::ifstream stream(if_name.c_str());
stream >> P;
std::cout << "loadMesh... "<< "Polysurf with " << P.size_of_vertices()
<< " vertices and " << P.size_of_facets()
<< " facets. " << std::endl;
if(verbose)
out_verbose << "Polysurf with " << P.size_of_vertices()
<< " vertices and " << P.size_of_facets()
<< " facets. " << std::endl;
if (min_nb_points > P.size_of_vertices()) exit(0);
Vertex2int_map_type vertex2props;
Vertex_PM_type vpm(vertex2props);
Hedge2double_map_type hedge2props;
Hedge_PM_type hepm(hedge2props);
Facet2normal_map_type facet2props;
Facet_PM_type fpm(facet2props);
Poly_hedge_ops::compute_edges_length(P, hepm);
Poly_facet_ops::compute_facets_normals(P, fpm);
std::vector<DPoint> in_points;
Vertex_iterator vitb, vite;
vitb = P.vertices_begin(); vite = P.vertices_end();
vitb = P.vertices_begin(); vite = P.vertices_end();
for (; vitb != vite; vitb++) {
Vertex* v = &(*vitb);
in_points.clear();
My_Monge_form monge_form;
gather_fitting_points(v, in_points, vpm);
if ( in_points.size() < min_nb_points )
{std::cerr << "not enough pts for fitting this vertex" << in_points.size() << std::endl;
continue;}
My_Monge_via_jet_fitting monge_fit;
monge_form = monge_fit(in_points.begin(), in_points.end(),
d_fitting, d_monge);
const DVector normal_mesh = Poly_facet_ops::compute_vertex_average_unit_normal(v, fpm);
monge_form.comply_wrt_given_normal(normal_mesh);
DFT scale_ppal_dir = Poly_hedge_ops::compute_mean_edges_length_around_vertex(v, hepm)/2;
out_4ogl << v->point() << " ";
monge_form.dump_4ogl(out_4ogl, scale_ppal_dir);
if (verbose) {
std::vector<DPoint>::iterator itbp = in_points.begin(), itep = in_points.end();
out_verbose << "in_points list : " << std::endl ;
for (;itbp!=itep;itbp++) out_verbose << *itbp << std::endl ;
out_verbose << "--- vertex " << ++nb_vertices_considered
<< " : " << v->point() << std::endl
<< "number of points used : " << in_points.size() << std::endl
;
}
}
out_4ogl.close();
if(verbose) {
out_verbose.close();
}
return 0;
}