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