// Copyright (c) 2007-2008 INRIA (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$ // SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Laurent RINEAU, Laurent Saboret #ifndef CGAL_POISSON_REFINE_TRIANGULATION_H #define CGAL_POISSON_REFINE_TRIANGULATION_H #include // CGAL #include #include #include #include #include #include namespace CGAL { /// \cond SKIP_IN_MANUAL /// Utility class for poisson_refine_triangulation(): /// implements Delaunay refinement in a loose bounding /// box of point set (break bad tetrahedra, where /// bad means badly shaped or too big). /// /// This class must be derived to inherit from Mesher_level. template > class Poisson_mesher_level_impl_base : public Mesh_3::Poisson_refine_tets_with_oracle_base { typedef Mesh_3::Poisson_refine_tets_with_oracle_base Base; public: // Inherited methods and fields used below using Base::triangulation_ref_impl; using Base::oracle; using Base::surface; using Base::should_be_refined; typedef typename Tr::Geom_traits Geom_traits; typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Point Point; typedef typename Base::Cell_quality Cell_quality; public: /** \name CONSTRUCTORS */ Poisson_mesher_level_impl_base(Tr& t, Criteria crit, unsigned int max_vert, Surface& surface, Oracle& oracle) : Base(t, crit, surface, oracle), max_vertices(max_vert) ///< number of vertices bound (ignored if zero) {} protected: /* --- protected functions --- */ bool test_if_cell_is_bad(const Cell_handle c) { Cell_quality q; if( is_in_domain(c) && should_be_refined(c, q) ) { this->add_bad_element(c, q); return true; } return false; } bool is_in_domain(const Cell_handle c) { return oracle.is_in_volume(surface, triangulation_ref_impl().dual(c)); } public: /* Overriden functions of this level: */ /* we override all methods that call test_if_cell_is_bad() */ void scan_triangulation_impl() { for(typename Tr::Finite_cells_iterator cit = triangulation_ref_impl().finite_cells_begin(), eit = triangulation_ref_impl().finite_cells_end(); cit != eit; ++cit) test_if_cell_is_bad(cit); } void after_insertion_impl(const Vertex_handle& v) { update_star(v); } void update_star(const Vertex_handle& v) { // scan refiner typedef std::vector Cells; typedef typename Cells::iterator Cell_iterator; Cells incident_cells; incident_cells.reserve(32); triangulation_ref_impl().incident_cells(v, std::back_inserter(incident_cells)); for(Cell_iterator cit = incident_cells.begin(); cit != incident_cells.end(); ++cit) { if( ! triangulation_ref_impl().is_infinite(*cit) ) test_if_cell_is_bad(*cit); } } /// Tells if the algorithm is done. bool no_longer_element_to_refine_impl() const { return Base::no_longer_element_to_refine_impl() || (max_vertices > 0 && triangulation_ref_impl().number_of_vertices() >= max_vertices); } private: /* --- private datas --- */ unsigned int max_vertices; ///< number of vertices bound (ignored if zero) }; // end Poisson_mesher_level_impl_base /// Utility class for poisson_refine_triangulation(): /// glue class that inherits from both Mesher_level /// and Poisson_mesher_level_impl_base. template ::type, typename PreviousLevel = Null_mesher_level > class Poisson_mesher_level : public Poisson_mesher_level_impl_base, public Mesher_level < Tr, Poisson_mesher_level, typename Tr::Cell_handle, PreviousLevel, Triangulation_mesher_level_traits_3 > { typedef Poisson_mesher_level_impl_base Base; public: typedef Mesher_level < Tr, Poisson_mesher_level, typename Tr::Cell_handle, PreviousLevel, Triangulation_mesher_level_traits_3 > Mesher; Poisson_mesher_level(Tr& t, Criteria criteria, unsigned int max_vertices, Surface& surface, Oracle& oracle, PreviousLevel& previous_level) : Base(t, criteria, max_vertices, surface, oracle), Mesher(previous_level) { } }; // end class Poisson_mesher_level /// Delaunay refinement in a loose bounding box /// of input point set (break bad tetrahedra, where /// bad means badly shaped or too big). /// @return the number of vertices inserted. /// /// @commentheading Preconditions: /// - Tr must use a geometric traits with robust circumcenter computation. /// - convergence is guaranteed if radius_edge_ratio_bound >= 1.0. /// /// @commentheading Template Parameters: /// @param Tr 3D Delaunay triangulation. /// @param Surface Sphere_3 or Iso_cuboid_3. /// @param Sizing_field A sizing field functor type /// @param Second_sizing_field A sizing field functor type /// /// @commentheading Sizing fields /// - The first sizing field is the real sizing field that is targeted by /// the refinement process. It may be costly to use. /// - The second sizing field is supposed to be a sizing field that is less /// costly to use (such as a constant sizing field). If a cell has a radius /// that is smaller than the value of the second sizing field at its /// center, then the cell is considered as small enough and the first /// sizing field is not evaluated for that cell. template unsigned int poisson_refine_triangulation( Tr& tr, double radius_edge_ratio_bound, ///< radius edge ratio bound (>= 1.0) const Sizing_field& sizing_field, ///< sizing field for cell radius bound const Second_sizing_field& second_sizing_field, ///< second sizing field for cell radius bound unsigned int max_vertices, ///< number of vertices bound (ignored if zero) Surface& enlarged_bbox) ///< new bounding sphere or box { // Convergence is guaranteed if radius_edge_ratio_bound >= 1.0 CGAL_surface_reconstruction_points_precondition(radius_edge_ratio_bound >= 1.0); // Mesher_level types typedef Poisson_mesh_cell_criteria_3< Tr , Sizing_field , Second_sizing_field > Tets_criteria; typedef typename CGAL::Surface_mesh_traits_generator_3::type Oracle; typedef Poisson_mesher_level Refiner; std::size_t nb_vertices = tr.number_of_vertices(); // get former #vertices // Delaunay refinement Tets_criteria tets_criteria(radius_edge_ratio_bound*radius_edge_ratio_bound, sizing_field, second_sizing_field); Oracle oracle; Null_mesher_level null_mesher_level; Refiner refiner(tr, tets_criteria, max_vertices, enlarged_bbox, oracle, null_mesher_level); refiner.scan_triangulation(); // Push bad cells to the queue refiner.refine(Null_mesh_visitor()); // Refine triangulation until queue is empty nb_vertices = tr.number_of_vertices() - nb_vertices; return static_cast(nb_vertices); } /// \endcond } //namespace CGAL #endif // CGAL_POISSON_REFINE_TRIANGULATION_H