mirror of https://github.com/CGAL/cgal
435 lines
13 KiB
C
435 lines
13 KiB
C
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
|
#include <CGAL/Regular_triangulation_3.h>
|
|
|
|
#include <CGAL/Regular_triangulation_cell_base_3.h>
|
|
|
|
#include <CGAL/Mesh_3/IO.h>
|
|
|
|
#include <CGAL/make_surface_mesh.h>
|
|
#include <CGAL/Polyhedral_surface_3.h>
|
|
|
|
#include <CGAL/Volume_mesher_cell_base_3.h>
|
|
#include <CGAL/Regular_triangulation_euclidean_traits_3.h>
|
|
#include <CGAL/Regular_triangulation_filtered_traits_3.h>
|
|
#include <CGAL/Implicit_surfaces_mesher_3.h>
|
|
|
|
#include <CGAL/Surface_mesher/Standard_criteria.h>
|
|
#include <CGAL/Surface_mesher/Vertices_on_the_same_surface_criterion.h>
|
|
#include <CGAL/Mesh_3/Slivers_exuder.h>
|
|
|
|
#include <CGAL/IO/Complex_2_in_triangulation_3_file_writer.h>
|
|
#include <CGAL/IO/File_medit.h>
|
|
|
|
#include <CGAL/Surface_mesher/Point_surface_indices_oracle_visitor.h>
|
|
|
|
#include <CGAL/Mesh_criteria_3.h>
|
|
|
|
#include <CGAL/Point_traits.h>
|
|
#include <CGAL/Weighted_point_with_surface_index_geom_traits.h>
|
|
|
|
#include "parameters.h"
|
|
|
|
#include "debug.h"
|
|
#include <CGAL/Timer.h>
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <boost/tuple/tuple.hpp> // boost::tie
|
|
|
|
using boost::tie;
|
|
|
|
/////////////// Types ///////////////
|
|
|
|
struct K : public CGAL::Exact_predicates_inexact_constructions_kernel {};
|
|
typedef CGAL::Regular_triangulation_filtered_traits_3<K> Regular_traits;
|
|
typedef CGAL::Weighted_point_with_surface_index_geom_traits<Regular_traits> My_traits;
|
|
typedef CGAL::Complex_2_in_triangulation_vertex_base_3<My_traits> Vb;
|
|
typedef CGAL::Regular_triangulation_cell_base_3<My_traits> Cb1;
|
|
typedef CGAL::Surface_mesh_cell_base_3<My_traits, Cb1> Cb2;
|
|
typedef CGAL::Volume_mesher_cell_base_3<My_traits, Cb2> Cb;
|
|
typedef CGAL::Triangulation_data_structure_3<Vb, Cb> Tds;
|
|
typedef CGAL::Regular_triangulation_3<My_traits, Tds> Tr;
|
|
|
|
typedef My_traits::Point_3 Point_3;
|
|
typedef My_traits::Sphere_3 Sphere_3;
|
|
typedef My_traits::FT FT;
|
|
|
|
typedef CGAL::Polyhedral_surface_3<My_traits> Surface;
|
|
|
|
|
|
// typedef CGAL::Triangulation_vertex_base_3<K> Del_Vb;
|
|
// typedef CGAL::Triangulation_cell_base_3<K> Del_Cb1;
|
|
// typedef CGAL::Mesh_3::Complex_2_in_triangulation_cell_base_3<K, Del_Cb1> Del_Cb;
|
|
// typedef CGAL::Triangulation_data_structure_3<Del_Vb, Del_Cb> Del_Tds;
|
|
// typedef CGAL::Delaunay_triangulation_3<K, Del_Tds> Del_tr;
|
|
|
|
typedef CGAL::Surface_mesher::Refine_criterion<Tr> Criterion;
|
|
typedef CGAL::Surface_mesher::Standard_criteria <Criterion > Criteria;
|
|
typedef CGAL::Mesh_criteria_3<Tr> Tets_criteria;
|
|
|
|
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
|
|
|
|
typedef CGAL::Surface_mesher::Point_surface_indices_visitor Volume_mesher_traits_visitor;
|
|
|
|
typedef CGAL::Surface_mesher::Polyhedral_oracle<
|
|
Surface,
|
|
CGAL::Creator_uniform_3<My_traits::FT, My_traits::Point_3>,
|
|
Volume_mesher_traits_visitor> Volume_mesh_traits;
|
|
|
|
typedef Volume_mesh_traits::Construct_initial_points Initial_points;
|
|
|
|
typedef CGAL::Implicit_surfaces_mesher_3<
|
|
C2t3,
|
|
Surface,
|
|
Criteria,
|
|
Tets_criteria,
|
|
Volume_mesh_traits> Mesher;
|
|
|
|
typedef CGAL::Simple_cartesian<double> Simple_kernel;
|
|
typedef Simple_kernel::Iso_rectangle_2 Rectangle_2;
|
|
typedef Simple_kernel::Segment_2 Segment_2;
|
|
typedef Simple_kernel::Point_2 Point_2;
|
|
|
|
typedef CGAL::Point_traits<Point_3> Point_traits;
|
|
typedef Point_traits::Bare_point Bare_point_3;
|
|
typedef Regular_traits::Point_3 Kernel_point_3;
|
|
|
|
/// Global variables
|
|
std::ostream *out = 0;
|
|
std::string filename = std::string();
|
|
std::string function_name = "sphere";
|
|
char* argv0 = "";
|
|
|
|
void usage(std::string error = "")
|
|
{
|
|
if( error != "" )
|
|
std:: cerr << "Error: " << error << std::endl;
|
|
std::cerr << "Usage:\n "
|
|
<< argv0
|
|
<< " [-f function_name]"
|
|
<< " [output_file.mesh|-]\n"
|
|
<< "If output_file.mesh is '-', outputs to standard out.\n"
|
|
<< "-f define the implicite function to use\n";
|
|
for(String_options::iterator it = string_options.begin();
|
|
it != string_options.end();
|
|
++it)
|
|
std::cerr << "--" << it->first << " default value is \""
|
|
<< it->second << "\".\n";
|
|
for(Double_options::iterator it = double_options.begin();
|
|
it != double_options.end();
|
|
++it)
|
|
std::cerr << "--" << it->first << " default value is "
|
|
<< it->second << ".\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
std::pair<std::ostream*, const bool>
|
|
open_file_for_writing(std::string filename,
|
|
std::string display_string = "Writing to ")
|
|
{
|
|
if( filename != "")
|
|
{
|
|
if( filename == "-" )
|
|
{
|
|
std::cerr << display_string << "standard out...\n";
|
|
return std::make_pair(&std::cout, false);
|
|
}
|
|
else
|
|
{
|
|
std::ofstream* result = new std::ofstream(filename.c_str());
|
|
if( *result )
|
|
{
|
|
std::cerr << display_string << "file " << filename << "...\n";
|
|
return std::make_pair(result, true);
|
|
}
|
|
else
|
|
{
|
|
delete result;
|
|
std::cerr << "Error: cannot create " << filename << "\n";
|
|
usage();
|
|
return std::pair<std::ostream*, bool>(0, false);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return std::pair<std::ostream*, bool>(0, false);
|
|
}
|
|
|
|
void parse_argv(int argc, char** argv, int extra_args = 0)
|
|
{
|
|
if (argc >=(2 + extra_args))
|
|
{
|
|
std::string arg = argv[1+extra_args];
|
|
if( arg == "-h" || arg == "--help")
|
|
usage();
|
|
else if( arg == "-f" )
|
|
{
|
|
if( argc < (3 + extra_args) )
|
|
usage("-f must be followed by a function name!");
|
|
function_name = argv[2 + extra_args];
|
|
parse_argv(argc, argv, extra_args + 2);
|
|
}
|
|
else if( arg.substr(0, 2) == "--" )
|
|
{
|
|
Double_options::iterator opt_it =
|
|
double_options.find(arg.substr(2, arg.length()-2));
|
|
if( opt_it != double_options.end() )
|
|
{
|
|
if( argc < (3 + extra_args) )
|
|
usage((arg + " must be followed by a double!").c_str());
|
|
std::stringstream s;
|
|
double val;
|
|
s << argv[extra_args + 2];
|
|
s >> val;
|
|
if( !s )
|
|
usage(("Bad double after " + arg + "!").c_str());
|
|
opt_it->second = val;
|
|
parse_argv(argc, argv, extra_args + 2);
|
|
}
|
|
else
|
|
{
|
|
String_options::iterator opt_it =
|
|
string_options.find(arg.substr(2, arg.length()-2));
|
|
if( opt_it != string_options.end() )
|
|
{
|
|
if( argc < (3 + extra_args) )
|
|
usage((arg + " must be followed by a string!").c_str());
|
|
std::string s = argv[extra_args + 2];
|
|
opt_it->second = s;
|
|
parse_argv(argc, argv, extra_args + 2);
|
|
}
|
|
else
|
|
usage(("Invalid option " + arg).c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
filename = argv[1+extra_args];
|
|
parse_argv(argc, argv, extra_args + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////// Main function ///////////////
|
|
|
|
int main(int argc, char **argv) {
|
|
argv0 = argv[0];
|
|
|
|
init_parameters();
|
|
|
|
parse_argv(argc, argv);
|
|
|
|
std::ifstream surface_ifs(function_name.c_str());
|
|
Surface surface(surface_ifs);
|
|
surface_ifs.close();
|
|
|
|
// 2D-complex in 3D-Delaunay triangulation
|
|
Tr tr;
|
|
C2t3 c2t3(tr);
|
|
|
|
CGAL::Timer timer;
|
|
|
|
bool need_delete = false;
|
|
std::ostream* out = 0;
|
|
|
|
// Create the volume_mesh_traits by hand, to pass it
|
|
// Point_surface_indices_visitor(1), that is a visitor for oracles that
|
|
// sets surface_index() to a given integer.
|
|
Volume_mesh_traits volume_mesh_traits(Volume_mesher_traits_visitor(1));
|
|
|
|
// Initial point sample
|
|
std::string read_initial_points = get_string_option("read_initial_points");
|
|
if( read_initial_points != "")
|
|
{
|
|
std::ifstream in( read_initial_points.c_str() );
|
|
int n;
|
|
in >> n;
|
|
CGAL_assertion(in);
|
|
while( !in.eof() )
|
|
{
|
|
Point_3 p;
|
|
if(in >> p)
|
|
{
|
|
tr.insert(p);
|
|
--n;
|
|
}
|
|
}
|
|
CGAL_assertion( n == 0 );
|
|
double_options["number_of_initial_points"] = 0;
|
|
}
|
|
else
|
|
{
|
|
const int number_of_initial_points =
|
|
static_cast<int>(get_double_option("number_of_initial_points"));
|
|
|
|
std::vector<Point_3> initial_point_sample;
|
|
initial_point_sample.reserve(number_of_initial_points);
|
|
|
|
Initial_points get_initial_points =
|
|
volume_mesh_traits.construct_initial_points_object();
|
|
|
|
get_initial_points(surface,
|
|
std::back_inserter(initial_point_sample),
|
|
number_of_initial_points);
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("dump_of_initial_points"),
|
|
"Writing initial points to ");
|
|
if( out )
|
|
{
|
|
*out << initial_point_sample.size() << "\n";
|
|
for(std::vector<Point_3>::const_iterator it =
|
|
initial_point_sample.begin();
|
|
it != initial_point_sample.end();
|
|
++it)
|
|
*out << *it <<"\n";
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
tr.insert (initial_point_sample.begin(), initial_point_sample.end());
|
|
}
|
|
|
|
// Meshing criteria
|
|
CGAL::Surface_mesher::Curvature_size_criterion<Tr>
|
|
curvature_size_criterion (get_double_option("distance_bound"));
|
|
CGAL::Surface_mesher::Uniform_size_criterion<Tr>
|
|
uniform_size_criterion (get_double_option("radius_bound"));
|
|
CGAL::Surface_mesher::Aspect_ratio_criterion<Tr>
|
|
aspect_ratio_criterion (get_double_option("angle_bound"));
|
|
CGAL::Surface_mesher::Vertices_on_the_same_surface_criterion<Tr>
|
|
vertices_on_the_same_surface_criterion;
|
|
|
|
std::vector<Criterion*> criterion_vector;
|
|
criterion_vector.push_back(&aspect_ratio_criterion);
|
|
criterion_vector.push_back(&uniform_size_criterion);
|
|
criterion_vector.push_back(&curvature_size_criterion);
|
|
criterion_vector.push_back(&vertices_on_the_same_surface_criterion);
|
|
Criteria criteria (criterion_vector);
|
|
|
|
Tets_criteria tets_criteria(get_double_option("tets_aspect_ratio_bound"),
|
|
get_double_option("tets_size_bound"));
|
|
|
|
std::cerr << "\nInitial number of points: " << tr.number_of_vertices()
|
|
<< std::endl;
|
|
|
|
|
|
// Surface meshing
|
|
|
|
Mesher mesher (c2t3, surface, criteria, tets_criteria, volume_mesh_traits);
|
|
timer.start();
|
|
mesher.refine_surface();
|
|
timer.stop();
|
|
std::cerr << "\nNumber of points after refine_surface(): "
|
|
<< tr.number_of_vertices() << std::endl
|
|
<< "Elapsed time: " << timer.time() << std::endl;
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("initial_surface_off"),
|
|
"Writing initial surface off to ");
|
|
if( out )
|
|
{
|
|
CGAL::output_oriented_surface_facets_to_off(*out, tr);
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
timer.start();
|
|
mesher.refine_mesh();
|
|
timer.stop();
|
|
|
|
std::cout.flush();
|
|
|
|
std::cerr << "\nFinal number of points: " << tr.number_of_vertices()
|
|
<< std::endl
|
|
<< "Total time: " << timer.time() << std::endl;
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(filename,
|
|
"Writing medit mesh before exudation to ");
|
|
if( out )
|
|
{
|
|
CGAL::output_to_medit(*out, mesher.complex_2_in_triangulation_3());
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("cgal_mesh_before_exudation"),
|
|
"Writing cgal mesh before exudation to ");
|
|
if( out )
|
|
{
|
|
CGAL::Mesh_3::output_mesh(*out, mesher.complex_2_in_triangulation_3());
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
|
|
CGAL::Mesh_3::Slivers_exuder<C2t3> exuder(tr);
|
|
exuder.pump_vertices(get_double_option("pumping_bound"));
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("cgal_mesh_after_filename"),
|
|
"Writing cgal mesh after exudation to ");
|
|
if( out )
|
|
{
|
|
CGAL::Mesh_3::output_mesh(*out, mesher.complex_2_in_triangulation_3());
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("mesh_after_filename"),
|
|
"Writing medit mesh after exudation to ");
|
|
if( out )
|
|
{
|
|
CGAL::output_to_medit(*out, mesher.complex_2_in_triangulation_3());
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("surface_off"),
|
|
"Writing finale surface off to ");
|
|
if( out )
|
|
{
|
|
CGAL::output_to_medit(*out, mesher.complex_2_in_triangulation_3());
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
// {
|
|
// std::string dump_final_surface_filename = get_string_option("surface_ghs");
|
|
// if( dump_final_surface_filename != "" )
|
|
// {
|
|
// std::ofstream dump_points((dump_final_surface_filename +
|
|
// ".points").c_str());
|
|
// std::ofstream dump_faces((dump_final_surface_filename +
|
|
// ".faces").c_str());
|
|
// if( dump_points && dump_faces ) {
|
|
// std::cerr << "Writing final surface to ghs file "
|
|
// << dump_final_surface_filename << "..." << std::endl;
|
|
// output_surface_facets_to_ghs(dump_points, dump_faces, tr);
|
|
// }
|
|
// else
|
|
// usage(("Error: cannot create " +
|
|
// dump_final_surface_filename).c_str());
|
|
// }
|
|
// }
|
|
|
|
tie(out, need_delete) =
|
|
open_file_for_writing(get_string_option("slivers_off"),
|
|
"Writing slivers off to ");
|
|
if( out )
|
|
{
|
|
CGAL::output_slivers_to_off(*out, tr, get_double_option("sliver_test"));
|
|
if(need_delete)
|
|
delete out;
|
|
}
|
|
|
|
std::cerr << " done\n";
|
|
|
|
#ifdef CGAL_SURFACE_MESHER_TEST_OPTIONS
|
|
check_all_options_have_been_used();
|
|
#endif
|
|
}
|