diff --git a/.gitignore b/.gitignore index c6f90d2c446..0e72878b613 100644 --- a/.gitignore +++ b/.gitignore @@ -131,8 +131,6 @@ CGAL_ImageIO/examples/CGALimageIO/convert_raw_image_to_inr CGAL_ImageIO/examples/CGALimageIO/makefile CGAL_ImageIO/examples/CGALimageIO/test_imageio CGAL_ImageIO/src/CGAL_ImageIO/Makefile -CGAL_ImageIO/test/CGAL_ImageIO/Makefile -CGAL_ImageIO/test/CGAL_ImageIO/test_trilinear_interpolation Circular_kernel_3/demo/Circular_kernel_3/Circular_kernel_3_demo Circular_kernel_3/demo/Circular_kernel_3/Makefile Circular_kernel_3/test/Circular_kernel_3/cgal_test_with_cmake @@ -384,6 +382,7 @@ Mesh_3/applications/stat_mesh Mesh_3/applications/test_off Mesh_3/demo/Mesh_3/Makefile Mesh_3/demo/Mesh_3/Mesh_3 +Mesh_3/demo/Mesh_3/build* Mesh_3/demo/Mesh_3/out.mesh Mesh_3/doxygen Mesh_3/examples/Mesh_3/*.cgal @@ -483,6 +482,54 @@ Mesh_3/test/Mesh_3/test_robust_weighted_circumcenter /Mesh_3/test/Mesh_3/test_mesh_3_implicit_vector_to_labeled_function_wrapper /Mesh_3/test/Mesh_3/test_mesh_3_labeled_mesh_domain_3 /Mesh_3/test/Mesh_3/test_meshing_3D_gray_image +Min_annulus_d/*.aux +Min_annulus_d/*.bbl +Min_annulus_d/*.blg +Min_annulus_d/*.dvi +Min_annulus_d/*.idx +Min_annulus_d/*.ilg +Min_annulus_d/*.ind +Min_annulus_d/*.log +Min_annulus_d/*.mxp +Min_annulus_d/*.toc +Min_annulus_d/.dep +Min_annulus_d/.obj +Min_annulus_d/.tmp +Min_annulus_d/Makefile +Min_annulus_d/bin +Min_annulus_d/doc_ps +Min_circle_2/*.aux +Min_circle_2/*.bbl +Min_circle_2/*.blg +Min_circle_2/*.dvi +Min_circle_2/*.idx +Min_circle_2/*.ilg +Min_circle_2/*.ind +Min_circle_2/*.log +Min_circle_2/*.mxp +Min_circle_2/*.toc +Min_circle_2/.dep +Min_circle_2/.obj +Min_circle_2/.tmp +Min_circle_2/Makefile +Min_circle_2/bin +Min_circle_2/doc_ps +Min_ellipse_2/*.aux +Min_ellipse_2/*.bbl +Min_ellipse_2/*.blg +Min_ellipse_2/*.dvi +Min_ellipse_2/*.idx +Min_ellipse_2/*.ilg +Min_ellipse_2/*.ind +Min_ellipse_2/*.log +Min_ellipse_2/*.mxp +Min_ellipse_2/*.toc +Min_ellipse_2/.dep +Min_ellipse_2/.obj +Min_ellipse_2/.tmp +Min_ellipse_2/Makefile +Min_ellipse_2/bin +Min_ellipse_2/doc_ps Minkowski_sum_3/test/Minkowski_sum_3/CMakeLists.txt Minkowski_sum_3/test/Minkowski_sum_3/cgal_test_with_cmake Nef_2/test/Nef_2/CMakeLists.txt diff --git a/CGAL_ImageIO/include/CGAL/Image_3.h b/CGAL_ImageIO/include/CGAL/Image_3.h index f77e5e6ca3c..34133fc176a 100644 --- a/CGAL_ImageIO/include/CGAL/Image_3.h +++ b/CGAL_ImageIO/include/CGAL/Image_3.h @@ -234,7 +234,8 @@ Image_3::trilinear_interpolation(const Coord_type& x, Image_transform transform) const { // Check on double/float coordinates, because (int)-0.1 gives 0 - if ( x < 0 || y < 0 || z < 0 ) return value_outside; + if ( x < 0 || y < 0 || z < 0 ) + return Target_word_type(value_outside); const Coord_type lx = x / image()->vx; const Coord_type ly = y / image()->vy; @@ -251,7 +252,7 @@ Image_3::trilinear_interpolation(const Coord_type& x, ly >= dimy-1 || lx >= dimx-1) { - return transform(value_outside); + return Target_word_type(transform(value_outside)); } // images are indexed by (z,y,x) @@ -290,17 +291,17 @@ Image_3::trilinear_interpolation(const Coord_type& x, Image_word_type* ptr = (Image_word_type*)image()->data; ptr += i1 * dimxy + j1 * dimx + k1; - const Target_word_type a = transform(*ptr); - const Target_word_type e = transform(*(ptr+1)); + const Target_word_type a = Target_word_type(transform(*ptr)); + const Target_word_type e = Target_word_type(transform(*(ptr+1))); ptr += dimxy; // i2 * dimxy + j1 * dimx + k1; - const Target_word_type b = transform(*ptr); - const Target_word_type f = transform(*(ptr+1)); + const Target_word_type b = Target_word_type(transform(*ptr)); + const Target_word_type f = Target_word_type(transform(*(ptr+1))); ptr += dimx; // i2 * dimxy + j2 * dimx + k1 - const Target_word_type c = transform(*ptr); - const Target_word_type g = transform(*(ptr+1)); + const Target_word_type c = Target_word_type(transform(*ptr)); + const Target_word_type g = Target_word_type(transform(*(ptr+1))); ptr -= dimxy; // i1 * dimxy + j2 * dimx + k1 - const Target_word_type d = transform(*ptr); - const Target_word_type h = transform(*(ptr+1)); + const Target_word_type d = Target_word_type(transform(*ptr)); + const Target_word_type h = Target_word_type(transform(*(ptr+1))); // const Target_word_type a = ((Image_word_type*)image()->data)[i1 * dimxy + j1 * dimx + k1]; @@ -312,7 +313,7 @@ Image_3::trilinear_interpolation(const Coord_type& x, // const Target_word_type g = ((Image_word_type*)image()->data)[i2 * dimxy + j2 * dimx + k2]; // const Target_word_type h = ((Image_word_type*)image()->data)[i1 * dimxy + j2 * dimx + k2]; -// const Target_word_type outside = transform(value_outside); +// const Target_word_type outside = Target_word_type(transform(value_outside); // if(x < 0.f || // y < 0.f || diff --git a/Installation/changes.html b/Installation/changes.html index 90f5fbd74f4..dbd6c1af3fe 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -160,6 +160,10 @@ and src/ directories). +

3D Mesh Generation

+

Polygon Mesh Processing

diff --git a/Mesh_3/doc/Mesh_3/CGAL/Gray_image_mesh_domain_3.h b/Mesh_3/doc/Mesh_3/CGAL/Gray_image_mesh_domain_3.h new file mode 100644 index 00000000000..3dfabf18aec --- /dev/null +++ b/Mesh_3/doc/Mesh_3/CGAL/Gray_image_mesh_domain_3.h @@ -0,0 +1,74 @@ +namespace CGAL { + +/*! +\ingroup PkgMesh_3Domains + +The class `Gray_image_mesh_domain_3` implements a domain described by a 3D +gray image. A 3D gray image is a grid of voxels, +where each voxel is associated with a gray level value. +This class is a model of the concept `MeshDomain_3`. +The domain to be discretized is the union of voxels that lie inside a surface +described by an isolevel value, called \a isovalue. + +This class includes a member function that provides, by interpolation, +a gray level value at any query point. +An intersection between a segment and bounding +surfaces is detected when both segment endpoints are associated with gray level +values which are on both sides of the isovalue. +The intersection is then constructed by bisection. +The bisection stops when the query segment is shorter than a given error bound +`e`. This error bound is given by `e=d`\f$ \times\f$`bound` where `d` is the +length of the diagonal of the bounding box (in world coordinates) and +`bound` is the argument passed to the constructor of `Labeled_image_mesh_domain_3`. + + +\tparam Image is the type of the input image. +This parameter must be a model of the concept +`LabeledImage_3`. + +\tparam BGT is a geometric traits class which provides +the basic operations to implement +intersection tests and intersection computations +through a bisection method. This parameter must be instantiated +with a model of the concept `BisectionGeometricTraits_3`. + +\tparam Image_word_type is the data type encoded in the `Image` +input file + + +\cgalModels `MeshDomain_3` + +\sa `BisectionGeometricTraits_3` +\sa `CGAL::make_mesh_3()`. + +*/ +template +class Gray_image_mesh_domain_3 +{ +public: + +/// \name Creation +/// @{ + +/*! +Construction from an image. +@param image the input image +@param iso_value the isovalue, inside `image`, + of the surface describing the boundary of the object to be meshed +@param value_outside the value attached to voxels outside of the domain + to be meshed +@param error_bound is relative to the size of the image. +*/ + Gray_image_mesh_domain_3( + const Image& image, + const Image_word_type iso_value, + const Image_word_type value_outside = + std::numeric_limits::max(), + const BGT::FT& error_bound = BGT::FT(1e-3)); + +/// @} + +}; /* end Labeled_image_mesh_domain_3 */ +} /* end namespace CGAL */ diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index 98d807b2410..71fed5ae5e6 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -98,6 +98,7 @@ and their associated classes: - `CGAL::Polyhedral_mesh_domain_3` - `CGAL::Polyhedral_mesh_domain_with_features_3` - `CGAL::Labeled_image_mesh_domain_3` +- `CGAL::Gray_image_mesh_domain_3` - `CGAL::Mesh_domain_with_polyline_features_3` - `CGAL::Mesh_polyhedron_3` - `CGAL::Triangle_accessor_3,K>` diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index f1dd4198064..57585206126 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -66,6 +66,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "mesh_optimization_example.cpp" ) create_single_source_cgal_program( "mesh_optimization_lloyd_example.cpp" ) create_single_source_cgal_program( "mesh_3D_image.cpp" ) + create_single_source_cgal_program( "mesh_3D_gray_image.cpp" ) create_single_source_cgal_program( "mesh_3D_image_variable_size.cpp" ) else() message( STATUS "NOTICE: The examples mesh_3D_image.cpp, mesh_3D_image_variable_size.cpp, mesh_optimization_example.cpp and mesh_optimization_lloyd_example.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." ) diff --git a/Mesh_3/examples/Mesh_3/data/skull_2.9.inr b/Mesh_3/examples/Mesh_3/data/skull_2.9.inr new file mode 100644 index 00000000000..d8dc23e59d9 Binary files /dev/null and b/Mesh_3/examples/Mesh_3/data/skull_2.9.inr differ diff --git a/Mesh_3/examples/Mesh_3/mesh_3D_gray_image.cpp b/Mesh_3/examples/Mesh_3/mesh_3D_gray_image.cpp new file mode 100644 index 00000000000..c7b61315113 --- /dev/null +++ b/Mesh_3/examples/Mesh_3/mesh_3D_gray_image.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2012 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Laurent Rineau +// +//****************************************************************************** +// File Description : +//*************************************************************************** + +#include + +#include +#include +#include + +#include +#include +#include +#include + +typedef float Image_word_type; + +// Domain +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Gray_image_mesh_domain_3 > > Mesh_domain; + +// Triangulation +typedef CGAL::Mesh_triangulation_3::type Tr; +typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + +// Criteria +typedef CGAL::Mesh_criteria_3 Mesh_criteria; + +// To avoid verbose function and named parameters call +using namespace CGAL::parameters; + +int main() +{ + // Loads image + CGAL::Image_3 image; + if(!image.read("data/skull_2.9.inr")) return 1; + + // Domain + Mesh_domain domain(image, std::bind1st(std::less(), 2.9f), 0.f); + + // Mesh criteria + Mesh_criteria criteria(facet_angle=30, facet_size=6, facet_distance=2, + cell_radius_edge_ratio=3, cell_size=8); + + // Meshing + C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria); + + // Output + std::ofstream medit_file("out.mesh"); + c3t3.output_to_medit(medit_file); + + return 0; +} diff --git a/Mesh_3/include/CGAL/Gray_image_mesh_domain_3.h b/Mesh_3/include/CGAL/Gray_image_mesh_domain_3.h new file mode 100644 index 00000000000..574f888be65 --- /dev/null +++ b/Mesh_3/include/CGAL/Gray_image_mesh_domain_3.h @@ -0,0 +1,121 @@ +// Copyright (c) 2009 INRIA Sophia-Antipolis (France). +// Copyright (c) 2012 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Stephane Tayeb, Laurent Rineau +// + +#ifndef CGAL_GRAY_IMAGE_MESH_DOMAIN_3_H +#define CGAL_GRAY_IMAGE_MESH_DOMAIN_3_H + +#include +#include +#include + +#include +#include + +namespace CGAL { + +/** + * @class Gray_image_mesh_domain_3 + * + * + */ +template >, + typename Subdomain_index = int> +class Gray_image_mesh_domain_3 + : public Labeled_mesh_domain_3< + Mesh_3::Image_to_labeled_function_wrapper , + BGT> +{ +public: + typedef Mesh_3::Image_to_labeled_function_wrapper Wrapper; + + typedef Labeled_mesh_domain_3 Base; + + typedef typename Base::Sphere_3 Sphere_3; + typedef typename Base::FT FT; + typedef BGT Geom_traits; + typedef CGAL::Bbox_3 Bbox_3; + + /// Constructor + Gray_image_mesh_domain_3(const Image& image, + const Image_word_type iso_value, + const Image_word_type value_outside = + (std::numeric_limits::max)(), + const FT& error_bound = FT(1e-3), + CGAL::Random* p_rng = NULL) + : Base(Wrapper(image, + Transform(std::less(), iso_value), + value_outside), + compute_bounding_box(image), + error_bound, + p_rng) + {} + + Gray_image_mesh_domain_3(const Image& image, + const Transform& transform, + const Image_word_type value_outside = + (std::numeric_limits::max)(), + const FT& error_bound = FT(1e-3), + CGAL::Random* p_rng = NULL) + : Base(Wrapper(image, transform, value_outside), + compute_bounding_box(image), + error_bound, + p_rng) + {} + + /// Destructor + virtual ~Gray_image_mesh_domain_3() {} + + +private: + /// Returns a box enclosing image \c im + Bbox_3 compute_bounding_box(const Image& im) const + { + return Bbox_3(-1,-1,-1, + im.xdim()*im.vx()+1, im.ydim()*im.vy()+1, im.zdim()*im.vz()+1); + } + +private: + // Disabled copy constructor & assignment operator + typedef Gray_image_mesh_domain_3 Self; + Gray_image_mesh_domain_3(const Self& src); + Self& operator=(const Self& src); + +}; // end class Gray_image_mesh_domain_3 + + + +} // end namespace CGAL + + + +#endif // CGAL_GRAY_IMAGE_MESH_DOMAIN_3_H diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/Mesh_3/include/CGAL/IO/File_medit.h index 929346e327f..452fe542041 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/Mesh_3/include/CGAL/IO/File_medit.h @@ -795,11 +795,11 @@ output_to_medit(std::ostream& os, { V[vit] = inum++; Point_3 p = vit->point(); - os << CGAL::to_double(p.x()) << " " - << CGAL::to_double(p.y()) << " " - << CGAL::to_double(p.z()) << " " + os << CGAL::to_double(p.x()) << ' ' + << CGAL::to_double(p.y()) << ' ' + << CGAL::to_double(p.z()) << ' ' << get(vertex_pmap, vit) - << '\n'; + << '\n'; } //------------------------------------------------------- @@ -822,7 +822,7 @@ output_to_medit(std::ostream& os, if (i != fit->second) { const Vertex_handle& vh = (*fit).first->vertex(i); - os << V[vh] << " "; + os << V[vh] << ' '; } } os << get(facet_pmap, *fit) << '\n'; @@ -835,7 +835,7 @@ output_to_medit(std::ostream& os, if (i != fit->second) { const Vertex_handle& vh = (*fit).first->vertex(i); - os << V[vh] << " "; + os << V[vh] << ' '; } } os << get(facet_twice_pmap, *fit) << '\n'; @@ -853,7 +853,7 @@ output_to_medit(std::ostream& os, ++cit ) { for (int i=0; i<4; i++) - os << V[cit->vertex(i)] << " "; + os << V[cit->vertex(i)] << ' '; os << get(cell_pmap, cit) << '\n'; } diff --git a/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h b/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h index 62eefd5afe6..19513ebad7c 100644 --- a/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Labeled_image_mesh_domain_3.h @@ -42,7 +42,11 @@ namespace CGAL { */ template > + typename Image_word_type = unsigned char, + typename Subdomain_index = int, + class Wrapper = Mesh_3::Image_to_labeled_function_wrapper > class Labeled_image_mesh_domain_3 : public Labeled_mesh_domain_3 { diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index be3288e1920..1e8863de3f9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -3026,6 +3026,9 @@ move_point_topo_change(const Vertex_handle& old_vertex, std::back_inserter(insertion_conflict_boundary), std::inserter(removal_conflict_cells, removal_conflict_cells.end()), could_lock_zone); + if (insertion_conflict_cells.empty()) + return old_vertex;//new_position coincides with an existing vertex (not old_vertex) + //and old_vertex should not be removed of the nb_vertices will change reset_circumcenter_cache(removal_conflict_cells); reset_sliver_cache(removal_conflict_cells); reset_circumcenter_cache(insertion_conflict_cells); diff --git a/Mesh_3/include/CGAL/Mesh_3/Image_to_labeled_function_wrapper.h b/Mesh_3/include/CGAL/Mesh_3/Image_to_labeled_function_wrapper.h index c200376f8df..9f26118da66 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Image_to_labeled_function_wrapper.h +++ b/Mesh_3/include/CGAL/Mesh_3/Image_to_labeled_function_wrapper.h @@ -27,9 +27,9 @@ #ifndef CGAL_MESH_3_IMAGE_TO_LABELED_FUNCTION_WRAPPER_H #define CGAL_MESH_3_IMAGE_TO_LABELED_FUNCTION_WRAPPER_H - - #include +#include + namespace CGAL { @@ -46,6 +46,8 @@ template, + bool labeled_image = true, bool use_trilinear_interpolation=true> class Image_to_labeled_function_wrapper { @@ -56,8 +58,13 @@ public: typedef typename BGT::Point_3 Point_3; /// Constructor - Image_to_labeled_function_wrapper(const Image_& image) - : r_im_(image) {} + Image_to_labeled_function_wrapper(const Image_& image, + const Transform& transform = Transform(), + const Image_word_type value_outside = 0) + : r_im_(image) + , transform(transform) + , value_outside(value_outside) + {} // Default copy constructor and assignment operator are ok @@ -73,12 +80,23 @@ public: { if ( use_trilinear_interpolation ) { - return static_cast( + if ( labeled_image ) + { + return static_cast(transform( r_im_.labellized_trilinear_interpolation( CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()), - word_type(0))); + value_outside))); + } else { + return static_cast(transform( + static_cast( + r_im_.template trilinear_interpolation( + CGAL::to_double(p.x()), + CGAL::to_double(p.y()), + CGAL::to_double(p.z()), + value_outside)))); + } } else { @@ -101,13 +119,16 @@ public: } const word_type* data = static_cast(r_im_.data()); - return data[ pz*dimy*dimx + py*dimx + px ]; + return static_cast(transform( + data[pz*dimy*dimx + py*dimx + px])); } } private: /// Labeled image to wrap const Image_& r_im_; + const Transform transform; + const Image_word_type value_outside; }; // end class Image_to_labeled_function_wrapper diff --git a/Mesh_3/include/CGAL/Mesh_3/global_parameters.h b/Mesh_3/include/CGAL/Mesh_3/global_parameters.h index fcb93bf19d1..e3fce732319 100644 --- a/Mesh_3/include/CGAL/Mesh_3/global_parameters.h +++ b/Mesh_3/include/CGAL/Mesh_3/global_parameters.h @@ -86,6 +86,7 @@ BOOST_PARAMETER_NAME( (dump_after_refine_prefix, tag ) dump_after_refine_prefix_ BOOST_PARAMETER_NAME( (dump_after_glob_opt_prefix, tag ) dump_after_glob_opt_prefix_) BOOST_PARAMETER_NAME( (dump_after_perturb_prefix, tag ) dump_after_perturb_prefix_) BOOST_PARAMETER_NAME( (dump_after_exude_prefix, tag ) dump_after_exude_prefix_) +BOOST_PARAMETER_NAME( (number_of_initial_points, tag) number_of_initial_points_) CGAL_PRAGMA_DIAG_POP } // end namespace parameters diff --git a/Mesh_3/include/CGAL/make_mesh_3.h b/Mesh_3/include/CGAL/make_mesh_3.h index de9d6490331..8a2fadb6b46 100644 --- a/Mesh_3/include/CGAL/make_mesh_3.h +++ b/Mesh_3/include/CGAL/make_mesh_3.h @@ -135,7 +135,8 @@ namespace Mesh_3 { template < typename C3T3, typename MeshDomain, typename MeshCriteria > void -init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&) +init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&, + const int nb_initial_points) { typedef typename MeshDomain::Point_3 Point_3; typedef typename MeshDomain::Index Index; @@ -145,7 +146,11 @@ init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&) // Mesh initialization : get some points and add them to the mesh Initial_points_vector initial_points; - domain.construct_initial_points_object()(std::back_inserter(initial_points)); + if (nb_initial_points > 0) + domain.construct_initial_points_object()(std::back_inserter(initial_points), + nb_initial_points); + else //use default number of points + domain.construct_initial_points_object()(std::back_inserter(initial_points)); // Insert points and set their index and dimension for ( Ipv_iterator it = initial_points.begin() ; @@ -211,7 +216,8 @@ struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, - bool with_features) + bool with_features, + const int nb_initial_points = -1) { if ( with_features ) { @@ -219,7 +225,7 @@ struct C3t3_initializer < C3T3, MD, MC, false, HasFeatures > << " without features !" << std::endl; } - init_c3t3(c3t3,domain,criteria); + init_c3t3(c3t3,domain,criteria,nb_initial_points); } }; @@ -231,10 +237,11 @@ struct C3t3_initializer < C3T3, MD, MC, true, HasFeatures > void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, - bool with_features) + bool with_features, + const int nb_initial_points = -1) { C3t3_initializer < C3T3, MD, MC, true, typename MD::Has_features >() - (c3t3,domain,criteria,with_features); + (c3t3,domain,criteria,with_features,nb_initial_points); } }; @@ -247,10 +254,11 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true > void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, - bool with_features) + bool with_features, + const int nb_initial_points = -1) { if ( with_features ) { init_c3t3_with_features(c3t3,domain,criteria); } - else { init_c3t3(c3t3,domain,criteria); } + else { init_c3t3(c3t3,domain,criteria,nb_initial_points); } } }; @@ -263,7 +271,8 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > void operator()(C3T3& c3t3, const MD& domain, const MC& criteria, - bool with_features) + bool with_features, + const int nb_initial_points = -1) { if ( with_features ) { @@ -271,7 +280,7 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > << " without features !" << std::endl; } - init_c3t3(c3t3,domain,criteria); + init_c3t3(c3t3,domain,criteria,nb_initial_points); } }; @@ -412,15 +421,17 @@ void make_mesh_3_impl(C3T3& c3t3, MeshDomain, MeshCriteria, internal::Mesh_3::has_Has_features::value > () (c3t3, - domain, - criteria, - with_features); - + domain, + criteria, + with_features, + mesh_options.number_of_initial_points); + // If c3t3 initialization is not sufficient (may happen if there is only // a planar curve as feature for example), add some surface points if ( c3t3.triangulation().dimension() != 3 ) { - internal::Mesh_3::init_c3t3(c3t3, domain, criteria); + internal::Mesh_3::init_c3t3(c3t3, domain, criteria, + mesh_options.number_of_initial_points); } CGAL_assertion( c3t3.triangulation().dimension() == 3 ); diff --git a/Mesh_3/include/CGAL/refine_mesh_3.h b/Mesh_3/include/CGAL/refine_mesh_3.h index 17c63c9c449..24fd93fce29 100644 --- a/Mesh_3/include/CGAL/refine_mesh_3.h +++ b/Mesh_3/include/CGAL/refine_mesh_3.h @@ -177,6 +177,7 @@ namespace parameters { , dump_after_glob_opt_prefix() , dump_after_perturb_prefix() , dump_after_exude_prefix() + , number_of_initial_points() {} std::string dump_after_init_prefix; @@ -185,6 +186,7 @@ namespace parameters { std::string dump_after_glob_opt_prefix; std::string dump_after_perturb_prefix; std::string dump_after_exude_prefix; + int number_of_initial_points; }; // end struct Mesh_3_options @@ -289,6 +291,7 @@ namespace parameters { (dump_after_glob_opt_prefix_, (std::string), "" ) (dump_after_perturb_prefix_, (std::string), "" ) (dump_after_exude_prefix_, (std::string), "" ) + (number_of_initial_points_, (int), -1) ) ) { @@ -300,7 +303,8 @@ namespace parameters { options.dump_after_glob_opt_prefix=dump_after_glob_opt_prefix_; options.dump_after_perturb_prefix=dump_after_perturb_prefix_; options.dump_after_exude_prefix=dump_after_exude_prefix_; - + options.number_of_initial_points=number_of_initial_points_; + return options; } diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index 7cf30f717fc..47a766b7d45 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -39,6 +39,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_mesh_criteria_creation.cpp" ) if(CGAL_ImageIO_USE_ZLIB) create_single_source_cgal_program( "test_meshing_3D_image.cpp" ) + create_single_source_cgal_program( "test_meshing_3D_gray_image.cpp" ) else() message(STATUS "test_meshing_3D_image requires the ZLIB library, and will not be compiled.") endif() diff --git a/Mesh_3/test/Mesh_3/data/skull_2.9.inr b/Mesh_3/test/Mesh_3/data/skull_2.9.inr new file mode 100644 index 00000000000..d8dc23e59d9 Binary files /dev/null and b/Mesh_3/test/Mesh_3/data/skull_2.9.inr differ diff --git a/Mesh_3/test/Mesh_3/test_meshing_3D_gray_image.cpp b/Mesh_3/test/Mesh_3/test_meshing_3D_gray_image.cpp new file mode 100644 index 00000000000..2658e3be79d --- /dev/null +++ b/Mesh_3/test/Mesh_3/test_meshing_3D_gray_image.cpp @@ -0,0 +1,109 @@ +// Copyright (c) 2015 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Laurent Rineau, Jane Tournois +// +//****************************************************************************** +// File Description : +//*************************************************************************** + +#include "test_meshing_utilities.h" +#include +#include +#include + +#include + +// To avoid verbose function and named parameters call +using namespace CGAL::parameters; + +template +struct Image_tester : public Tester +{ +public: + void image() const + { + typedef float Image_word_type; + typedef CGAL::Image_3 Image; + typedef CGAL::Gray_image_mesh_domain_3< + Image, + K_e_i, + Image_word_type, + std::binder1st< std::less > > Mesh_domain; + + typedef typename CGAL::Mesh_triangulation_3< + Mesh_domain, + CGAL::Kernel_traits::Kernel, + Concurrency_tag>::type Tr; + typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + typedef CGAL::Mesh_criteria_3 Mesh_criteria; + + CGAL_USE_TYPE(typename Mesh_domain::Surface_patch_index); + + //------------------------------------------------------- + // Data generation + //------------------------------------------------------- + Image image; + if (!image.read("data/skull_2.9.inr")) + { + std::cout << "Image reading error. Exit test.\n"; + return; + } + + std::cout << "\tSeed is\t" + << CGAL::default_random.get_seed() << std::endl; + + // Domain + Mesh_domain domain(image, + std::bind1st(std::less(), 2.9f),//transform + 0.f, //value_outside + 1e-3, //error_bound + &CGAL::default_random);//random generator for determinism + + // Mesh criteria + Mesh_criteria criteria(facet_angle = 30, + facet_size = 6, + facet_distance = 2, + cell_radius_edge_ratio = 3, + cell_size = 8); + + // Mesh generation + C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria, + mesh_3_options(number_of_initial_points = 30)); + + // Verify + this->verify_c3t3_volume(c3t3, 1236086 * 0.95, 1236086 * 1.05); + this->verify(c3t3, domain, criteria, Bissection_tag()); + } +}; + + +int main() +{ + Image_tester<> test_epic; + std::cerr << "Mesh generation from a 3D image:\n"; + test_epic.image(); + +#ifdef CGAL_LINKED_WITH_TBB + Image_tester test_epic_p; + std::cerr << "Parallel mesh generation from a 3D image:\n"; + test_epic_p.image(); +#endif + + return EXIT_SUCCESS; +}