1 // Copyright (c) 2009 INRIA Sophia-Antipolis (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Mesh_3/include/CGAL/Implicit_to_labeling_function_wrapper.h $
7 // $Id: Implicit_to_labeling_function_wrapper.h 254d60f 2019-10-19T15:23:19+02:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s)     : Stéphane Tayeb, Aymeric PELLE
12 //
13 //******************************************************************************
14 // File Description :
15 // Implicit_to_labeling_function_wrapper and
16 // Implicit_vector_to_labeling_function_wrapper class declaration
17 // and implementation.
18 //
19 // See classes description to have more information.
20 //******************************************************************************
21 
22 #ifndef CGAL_IMPLICIT_TO_LABELING_FUNCTION_WRAPPER_H
23 #define CGAL_IMPLICIT_TO_LABELING_FUNCTION_WRAPPER_H
24 
25 #include <CGAL/license/Mesh_3.h>
26 
27 #include <CGAL/disable_warnings.h>
28 
29 #if defined(BOOST_MSVC)
30 #  pragma warning(push)
31 #  pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored
32 #endif
33 
34 #include <boost/dynamic_bitset.hpp>
35 #include <boost/type_traits/remove_reference.hpp>
36 #include <boost/type_traits/remove_cv.hpp>
37 #include <boost/type_traits/is_function.hpp>
38 #include <boost/mpl/if.hpp>
39 
40 #include <CGAL/config.h>
41 #include <CGAL/assertions.h>
42 
43 namespace CGAL {
44 
45 /**
46  * @class Implicit_to_labeling_function_wrapper
47  *
48  * This class is designed to wrap an implicit function which describes a domain
49  * by [p is inside if f(p)<0] to a function which takes its values into {0,1}.
50  * f(p)=0 means that p is outside the domain.
51  */
52 template<class Function_, class BGT>
53 class Implicit_to_labeling_function_wrapper
54 {
55 public:
56   // Types
57   typedef int                     return_type;
58   typedef typename BGT::Point_3   Point_3;
59 
60   /// Constructor
Implicit_to_labeling_function_wrapper(Function_ f)61   Implicit_to_labeling_function_wrapper(Function_ f) : f_(f) {}
62 
63   // Default copy constructor, assignment operator, and destructor are ok
64 
65   /// Operator ()
operator()66   return_type operator()(const Point_3& p) const
67   {
68     return ( (f_(p)<0) ? 1 : 0 );
69   }
70 
71 private:
72   typedef typename boost::mpl::if_<boost::is_function<Function_>,
73                                    Function_*,
74                                    Function_>::type Stored_function;
75   /// Function to wrap
76   Stored_function f_;
77 
78 };  // end class Implicit_to_labeling_function_wrapper
79 
80 template <typename BGT, typename Function>
81 Implicit_to_labeling_function_wrapper<Function, BGT>
make_implicit_to_labeling_function_wrapper(Function f)82 make_implicit_to_labeling_function_wrapper(Function f)
83 {
84   return Implicit_to_labeling_function_wrapper<Function, BGT>(f);
85 }
86 
87 /**
88  * \deprecated
89  *
90  * @class Implicit_vector_to_labeling_function_wrapper
91  *
92  * Wraps a set of implicit function [f1,f2,...] to one function F which
93  * takes its values into N.
94  *
95  * Let p be a point.
96  * F(p) = 0b000000(f2(p)<0)(f1(p)<0)
97  *
98  * It can handle at most 8 functions.
99  */
100 template<class Function_, class BGT>
101 class Implicit_vector_to_labeling_function_wrapper
102 {
103 public:
104   // Types
105   typedef int                       return_type;
106   typedef std::vector<Function_*>   Function_vector;
107   typedef typename BGT::Point_3     Point_3;
108 
109   /// Constructor
Implicit_vector_to_labeling_function_wrapper(const std::vector<Function_ * > & v)110   Implicit_vector_to_labeling_function_wrapper(const std::vector<Function_*>& v)
111     : function_vector_(v)
112   {
113     if ( v.size() > 8 )
114     {
115       CGAL_error_msg("We support at most 8 functions !");
116     }
117   }
118 
119   // Default copy constructor and assignment operator are ok
120 
121   /// Destructor
~Implicit_vector_to_labeling_function_wrapper()122   ~Implicit_vector_to_labeling_function_wrapper() {}
123 
124   /// Operator ()
operator()125   return_type operator()(const Point_3& p) const
126   {
127     const int nb_func = static_cast<int>(function_vector_.size());
128     char bits = 0;
129     for ( int i = 0 ; i < nb_func ; ++i )
130     {
131       // Insert value into bits : we compute fi(p) and insert result at
132       // bit i of bits
133       bits = char(bits | ( ((*function_vector_[i])(p) < 0) << i ));
134     }
135 
136     return ( static_cast<return_type>(bits) );
137   }
138 
139 private:
140   /// Functions to wrap
141   const Function_vector function_vector_;
142 
143 };  // end class Implicit_to_labeling_function_wrapper
144 
145 template <class ImplicitFunction>
146 class Implicit_multi_domain_to_labeling_function_wrapper
147 {
148   template <class T_>
149   class Implicit_function_traits
150   {
151   public:
152     typedef typename T_::Point Point;
153   };
154 
155   template <class RT_, class Point_>
156   class Implicit_function_traits<RT_ (*)(Point_)>
157   {
158   public:
159     typedef typename boost::remove_reference<
160             typename boost::remove_cv< Point_ >::type>::type Point;
161   };
162 
163 public:
164   typedef int                     return_type;
165   typedef ImplicitFunction        Function;
166   typedef typename Implicit_function_traits<ImplicitFunction>::Point   Point_3;
167   typedef std::vector<Function>   Function_vector;
168 
169 private:
170   std::vector<Function> funcs;
171   typedef boost::dynamic_bitset<std::size_t> Bmask;
172   std::vector<Bmask> bmasks;
173 
174 public:
Implicit_multi_domain_to_labeling_function_wrapper(const Function_vector & vf,const std::vector<std::vector<Sign>> & vps)175   Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& vf, const std::vector<std::vector<Sign> >& vps)
176   : funcs(vf), bmasks(vps.size(), Bmask(funcs.size() * 2, false))
177   {
178     CGAL_assertion(funcs.size() != 0);
179 
180     std::size_t mask_index = 0;
181     for (std::vector<std::vector<Sign> >::const_iterator mask_iter = vps.begin(), mask_end_iter = vps.end();
182          mask_iter != mask_end_iter;
183          ++mask_iter)
184     {
185       const std::vector<Sign>& mask = *mask_iter;
186       CGAL_assertion(funcs.size() == mask.size());
187       Bmask& bmask = bmasks[mask_index++];
188 
189       typename Bmask::size_type bit_index = 0;
190       for (std::vector<Sign>::const_iterator iter = mask.begin(), endIter = mask.end(); iter != endIter; ++iter)
191       {
192         Sign character = *iter;
193         CGAL_assertion(character == POSITIVE || character == NEGATIVE);
194 
195         bmask[bit_index] = (character == POSITIVE);
196         ++bit_index;
197         bmask[bit_index] = (character == NEGATIVE);
198         ++bit_index;
199       }
200     }
201     std::sort(bmasks.begin(), bmasks.end());
202   }
203 
Implicit_multi_domain_to_labeling_function_wrapper(const Function_vector & vf)204   Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& vf)
205   : funcs(vf)
206   {
207     CGAL_assertion(funcs.size() != 0);
208 
209     bmasks.reserve((1 << funcs.size()) - 1);
210     bmasks.push_back(Bmask(std::string("10")));
211     bmasks.push_back(Bmask(std::string("01")));
212 
213     for (std::size_t i = 0; i < funcs.size()-1; ++i)
214     {
215       std::size_t c_size = bmasks.size();
216       for (std::size_t index = 0; index < c_size; ++index)
217       {
218         Bmask aux = bmasks[index];
219         aux.push_back(true);
220         aux.push_back(false);
221         bmasks.push_back(aux);
222         bmasks[index].push_back(false);
223         bmasks[index].push_back(true);
224       }
225     }
226     bmasks.pop_back();
227     std::sort(bmasks.begin(), bmasks.end());
228   }
229 
Implicit_multi_domain_to_labeling_function_wrapper(const Function_vector & vf,const std::vector<std::string> & vps)230   Implicit_multi_domain_to_labeling_function_wrapper (const Function_vector& vf, const std::vector<std::string>& vps)
231   : funcs(vf), bmasks(vps.size(), Bmask(funcs.size() * 2, false))
232   {
233     CGAL_assertion(funcs.size() != 0);
234 
235     std::size_t mask_index = 0;
236     for (std::vector<std::string>::const_iterator mask_iter = vps.begin(), mask_end_iter = vps.end();
237          mask_iter != mask_end_iter;
238          ++mask_iter)
239     {
240       const std::string& mask_str = *mask_iter;
241       CGAL_assertion(funcs.size() == mask_str.length());
242       Bmask& bmask = bmasks[mask_index++];
243 
244       typename Bmask::size_type bit_index = 0;
245       for (std::string::const_iterator iter = mask_str.begin(), endIter = mask_str.end(); iter != endIter; ++iter)
246       {
247         std::string::value_type character = *iter;
248         CGAL_assertion(character == '+' || character == '-');
249 
250         bmask[bit_index] = (character == '+');
251         ++bit_index;
252         bmask[bit_index] = (character == '-');
253         ++bit_index;
254       }
255     }
256     std::sort(bmasks.begin(), bmasks.end());
257   }
258 
operator()259   return_type operator() (const Point_3& p) const
260   {
261     Bmask bmask(funcs.size() * 2, false);
262 
263     std::size_t i = 0;
264     for (typename std::vector<Function>::const_iterator iter = funcs.begin(), endIter = funcs.end();
265          iter != endIter;
266          ++iter)
267     {
268       const Function& function = *iter;
269 
270       double fres = function(p);
271       bmask[i] = fres > 0;
272       ++i;
273       bmask[i] = fres < 0;
274       ++i;
275     }
276 
277     typename std::vector<Bmask>::const_iterator iter = std::lower_bound(bmasks.begin(), bmasks.end(), bmask);
278     if (iter != bmasks.end() && *iter == bmask)
279       return static_cast<return_type>(1 + (iter - bmasks.begin()));
280     return 0;
281   }
282 };
283 
284 }  // end namespace CGAL
285 
286 
287 
288 #if defined(BOOST_MSVC)
289 #  pragma warning(pop)
290 #endif
291 
292 #include <CGAL/enable_warnings.h>
293 
294 #endif // CGAL_IMPLICIT_TO_LABELING_FUNCTION_WRAPPER_H
295