// Copyright (c) 2009 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Stéphane Tayeb, Aymeric PELLE // //****************************************************************************** // File Description : // Implicit_to_labeling_function_wrapper and // Implicit_vector_to_labeling_function_wrapper class declaration // and implementation. // // See classes description to have more information. //****************************************************************************** #ifndef CGAL_IMPLICIT_TO_LABELING_FUNCTION_WRAPPER_H #define CGAL_IMPLICIT_TO_LABELING_FUNCTION_WRAPPER_H #include #include #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored #endif #include #include #include #include namespace CGAL { /** * @class Implicit_to_labeling_function_wrapper * * This class is designed to wrap an implicit function which describes a domain * by [p is inside if f(p)<0] to a function which takes its values into {0,1}. * f(p)=0 means that p is outside the domain. */ template class Implicit_to_labeling_function_wrapper { public: // Types typedef int return_type; typedef typename BGT::Point_3 Point_3; /// Constructor Implicit_to_labeling_function_wrapper(Function_ f) : f_(f) {} // Default copy constructor, assignment operator, and destructor are ok /// Operator () return_type operator()(const Point_3& p) const { return ( (f_(p)<0) ? 1 : 0 ); } private: typedef std::conditional_t, Function_*, Function_> Stored_function; /// Function to wrap Stored_function f_; }; // end class Implicit_to_labeling_function_wrapper template Implicit_to_labeling_function_wrapper make_implicit_to_labeling_function_wrapper(Function f) { return Implicit_to_labeling_function_wrapper(f); } /** * \deprecated * * @class Implicit_vector_to_labeling_function_wrapper * * Wraps a set of implicit function [f1,f2,...] to one function F which * takes its values into N. * * Let p be a point. * F(p) = 0b000000(f2(p)<0)(f1(p)<0) * * It can handle at most 8 functions. */ template class Implicit_vector_to_labeling_function_wrapper { public: // Types typedef int return_type; typedef std::vector Function_vector; typedef typename BGT::Point_3 Point_3; /// Constructor Implicit_vector_to_labeling_function_wrapper(const std::vector& v) : function_vector_(v) { if ( v.size() > 8 ) { CGAL_error_msg("We support at most 8 functions !"); } } // Default copy constructor and assignment operator are ok /// Destructor ~Implicit_vector_to_labeling_function_wrapper() {} /// Operator () return_type operator()(const Point_3& p) const { const int nb_func = static_cast(function_vector_.size()); char bits = 0; for ( int i = 0 ; i < nb_func ; ++i ) { // Insert value into bits : we compute fi(p) and insert result at // bit i of bits bits = char(bits | ( ((*function_vector_[i])(p) < 0) << i )); } return ( static_cast(bits) ); } private: /// Functions to wrap const Function_vector function_vector_; }; // end class Implicit_to_labeling_function_wrapper /*! \ingroup PkgMesh3Domains The class `Implicit_multi_domain_to_labeling_function_wrapper` is a helping class to get a function with integer values labeling the components of a multidomain. The multidomain is described through a set of functions {fi(p), i=1, ...n}. Each component corresponds to a sign vector [s1, s2, ..., sn] where si is the sign of the function fi(p) at a point p of the component. This wrapper class can be passed to `Labeled_mesh_domain_3` as first template parameter. \par Example For example, the multidomain described by the three functions [f1,f2,f3] and the two sign vectors [-,-,+] and [+,-,+] includes two components.
The first one matches the locus of points satisfying f1(p)<0 and f2(p)<0 and f3(p)>0.
The second one matches the locus of points satisfying f1(p)>0 and f2(p)<0 and f3(p)>0.
\tparam Function provides the definition of the function. This parameter stands for a model of the concept `ImplicitFunction` described in the surface mesh generation package. The number types `Function::FT` and `BGT::FT` are required to match. \sa `CGAL::Labeled_mesh_domain_3`. */ #ifdef DOXYGEN_RUNNING template #else template #endif class Implicit_multi_domain_to_labeling_function_wrapper { template class Implicit_function_traits { public: typedef typename T_::Point Point; }; template class Implicit_function_traits { public: typedef std::remove_reference_t< std::remove_cv_t< Point_ >> Point; }; public: /// \name Types /// @{ #ifdef DOXYGEN_RUNNING typedef typename Function::Point Point_3; #else typedef ImplicitFunction Function; typedef typename Implicit_function_traits::Point Point_3; typedef int return_type; #endif typedef std::vector Function_vector; /// @} private: std::vector funcs; typedef boost::dynamic_bitset Bmask; std::vector bmasks; public: /// \name Creation /// @{ /*! * \brief Construction from a vector of implicit functions and a vector of vector of signs. * * \param implicit_functions the vector of implicit functions. * \param position_vectors the vector of vector of signs. Each vector of positions describes a component. * * \sa `Sign` */ Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& implicit_functions, const std::vector >& position_vectors) : funcs(implicit_functions), bmasks(position_vectors.size(), Bmask(funcs.size() * 2, false)) { CGAL_assertion(funcs.size() != 0); std::size_t mask_index = 0; for (std::vector >::const_iterator mask_iter = position_vectors.begin(), mask_end_iter = position_vectors.end(); mask_iter != mask_end_iter; ++mask_iter) { const std::vector& mask = *mask_iter; CGAL_assertion(funcs.size() == mask.size()); Bmask& bmask = bmasks[mask_index++]; typename Bmask::size_type bit_index = 0; for (std::vector::const_iterator iter = mask.begin(), endIter = mask.end(); iter != endIter; ++iter) { Sign character = *iter; CGAL_assertion(character == POSITIVE || character == NEGATIVE); bmask[bit_index] = (character == POSITIVE); ++bit_index; bmask[bit_index] = (character == NEGATIVE); ++bit_index; } } std::sort(bmasks.begin(), bmasks.end()); } /*! * \brief Construction from a vector of implicit functions. * \param implicit_functions the vector of implicit functions. * * Position vectors are built automatically so that the union of components equals the union of the functions. */ Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& implicit_functions) : funcs(implicit_functions) { CGAL_assertion(funcs.size() != 0); bmasks.reserve((1 << funcs.size()) - 1); bmasks.push_back(Bmask(std::string("10"))); bmasks.push_back(Bmask(std::string("01"))); for (std::size_t i = 0; i < funcs.size()-1; ++i) { std::size_t c_size = bmasks.size(); for (std::size_t index = 0; index < c_size; ++index) { Bmask aux = bmasks[index]; aux.push_back(true); aux.push_back(false); bmasks.push_back(aux); bmasks[index].push_back(false); bmasks[index].push_back(true); } } bmasks.pop_back(); std::sort(bmasks.begin(), bmasks.end()); } /*! * \brief Construction from a vector of implicit functions and a vector of strings. * * \param implicit_functions the vector of implicit functions. * \param position_strings the vector of strings. The strings contained in this vector must contain '+' or '-' only. Each string (vector of positions) describes a component. */ Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& implicit_functions, const std::vector& position_strings) : funcs(implicit_functions), bmasks(position_strings.size(), Bmask(funcs.size() * 2, false)) { CGAL_assertion(funcs.size() != 0); std::size_t mask_index = 0; for (std::vector::const_iterator mask_iter = position_strings.begin(), mask_end_iter = position_strings.end(); mask_iter != mask_end_iter; ++mask_iter) { const std::string& mask_str = *mask_iter; CGAL_assertion(funcs.size() == mask_str.length()); Bmask& bmask = bmasks[mask_index++]; typename Bmask::size_type bit_index = 0; for (std::string::const_iterator iter = mask_str.begin(), endIter = mask_str.end(); iter != endIter; ++iter) { std::string::value_type character = *iter; CGAL_assertion(character == '+' || character == '-'); bmask[bit_index] = (character == '+'); ++bit_index; bmask[bit_index] = (character == '-'); ++bit_index; } } std::sort(bmasks.begin(), bmasks.end()); } /// @} return_type operator() (const Point_3& p) const { Bmask bmask(funcs.size() * 2, false); std::size_t i = 0; for (typename std::vector::const_iterator iter = funcs.begin(), endIter = funcs.end(); iter != endIter; ++iter) { const Function& function = *iter; double fres = function(p); bmask[i] = fres > 0; ++i; bmask[i] = fres < 0; ++i; } typename std::vector::const_iterator iter = std::lower_bound(bmasks.begin(), bmasks.end(), bmask); if (iter != bmasks.end() && *iter == bmask) return static_cast(1 + (iter - bmasks.begin())); return 0; } }; } // end namespace CGAL #if defined(BOOST_MSVC) # pragma warning(pop) #endif #include #endif // CGAL_IMPLICIT_TO_LABELING_FUNCTION_WRAPPER_H