// Copyright (c) 2009 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Mesh_3/include/CGAL/Mesh_3/sliver_criteria.h $ // $Id: sliver_criteria.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Stephane Tayeb // //****************************************************************************** // File Description : //****************************************************************************** #ifndef CGAL_MESH_3_SLIVER_CRITERIA_H #define CGAL_MESH_3_SLIVER_CRITERIA_H #include #include #include #include #include // for CGAL::IA_force_to_double #include namespace CGAL { namespace Mesh_3 { template > class Sliver_criterion { public: typedef typename Tr::Geom_traits Gt; typedef typename Tr::Cell_handle Cell_handle; typedef typename Gt::Tetrahedron_3 Tetrahedron_3; typedef Cell_vector_ Cell_vector; public: virtual double get_default_value() const = 0; virtual double get_max_value() const = 0; //Sliver_perturber performs perturbation "unit-per-unit" // so it needs to know how much is a unit for each criterion virtual double get_perturbation_unit() const = 0; // returns the value of the criterion for t virtual double operator()(Cell_handle cell) const { if(update_sliver_cache) { if( ! cell->is_cache_valid() ) { // cell->sliver_value() is stored in a plain 64 bits floating point // number, and the value computed by operator() might be // computed using the 80 bits floating point registers of the x87 // unit. // This could cause comparisons between sliver values to be // inconsistent when comparing caches and registers values // (see also the comment below) // IA_force_to_double is available in CGAL/FPU.h double value = CGAL::IA_force_to_double(operator()(tr_.tetrahedron(cell))); cell->set_sliver_value(value); } return cell->sliver_value(); } return operator()(tr_.tetrahedron(cell)); } virtual double operator()(const Tetrahedron_3& t) const = 0; virtual void before_move(const Cell_vector& cells) const = 0; virtual bool valid_move(const Cell_vector& cells, const bool soft = false) const = 0; // Sliver bound void set_sliver_bound(double bound) { sliver_bound_ = bound; } double sliver_bound() const { return sliver_bound_; } public: Sliver_criterion(const double& bound, const Tr& tr) : tr_(tr) , sliver_bound_(bound) {} virtual ~Sliver_criterion(){} protected: const Tr& tr_; double sliver_bound_; }; template class Min_value; template class Min_dihedral_angle_criterion : public Sliver_criterion { protected: typedef Sliver_criterion Base; typedef typename Base::Tetrahedron_3 Tetrahedron_3; typedef typename Base::Cell_vector Cell_vector; typedef typename Base::Gt Gt; public: typedef typename Base::Cell_handle Cell_handle; virtual double get_default_value() const { return 12.; } virtual double get_max_value() const { return 90.; } virtual double get_perturbation_unit() const { return 1.; } #if ( _MSC_VER != 1800 ) using Base::operator(); #else virtual double operator()(Cell_handle cell) const { return Base::operator()(cell); } #endif virtual double operator()(const Tetrahedron_3& t) const { return CGAL::to_double(minimum_dihedral_angle(t, this->tr_.geom_traits())); } virtual void before_move(const Cell_vector& cells) const { Min_value min_value_op(*this); min_value_before_move_ = min_value_op(cells); } virtual bool valid_move(const Cell_vector& cells, const bool soft = false) const { Min_value min_value_op(*this); double min_val = min_value_op(cells); return (min_val > min_value_before_move_) || (soft && min_val > this->sliver_bound_); } public: Min_dihedral_angle_criterion(const double& sliver_bound, const Tr& tr) : Base(sliver_bound, tr), min_value_before_move_(0.) {} private: mutable double min_value_before_move_; }; template class Radius_ratio_criterion : public Sliver_criterion { protected: typedef Sliver_criterion Base; typedef typename Base::Gt Gt; typedef typename Base::Tetrahedron_3 Tetrahedron_3; typedef typename Base::Cell_vector Cell_vector; typedef Radius_ratio_criterion RR_criterion; public: virtual double get_default_value() const { return 0.25; } virtual double get_max_value() const { return 1.; } virtual double get_perturbation_unit() const { return 0.05; } using Base::operator(); virtual double operator()(const Tetrahedron_3& t) const { return CGAL::to_double(radius_ratio(t, this->tr_.geom_traits())); } virtual void before_move(const Cell_vector& cells) const { Min_value min_value_op(*this); min_value_before_move_ = min_value_op(cells); } virtual bool valid_move(const Cell_vector& cells, const bool soft = false) const { Min_value min_value_op(*this); double min_val = min_value_op(cells); return (min_val > min_value_before_move_) || (soft && min_val > this->sliver_bound_); } public: Radius_ratio_criterion(const double& sliver_bound, const Tr& tr) : Base(sliver_bound, tr) {} private: mutable double min_value_before_move_; }; template class Min_value { public: double operator()(const Cell_vector& cells) { double minimum = criterion_.get_max_value(); typename Cell_vector::const_iterator it; for(it = cells.begin(); it != cells.end(); ++it) { typename SliverCriterion::Cell_handle c = *it; minimum = (std::min)(minimum, criterion_(c)); } return minimum; } Min_value(const SliverCriterion& criterion) : criterion_(criterion) {} private: SliverCriterion criterion_; }; } // end namespace Mesh_3 } // end namespace CGAL #include #endif // CGAL_MESH_3_SLIVER_CRITERIA_H