Goosefoot Mesher - CGAL
Signed_mesh_domain_3.h
1 // Copyright (c) 2009 INRIA Sophia-Antipolis (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 // You can redistribute it and/or modify it under the terms of the GNU
6 // General Public License as published by the Free Software Foundation,
7 // either version 3 of the License, or (at your option) any later version.
8 //
9 // Licensees holding a valid commercial license may use this file in
10 // accordance with the commercial license agreement provided with the software.
11 //
12 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 //
15 // $URL$
16 // $Id$
17 //
18 //
19 // Author(s) : Stéphane Tayeb (original Labeled_mesh_domain_3.h)
20 // Author(s) : Phil Weir (NUMA Engineering modifications)
21 //
22 //******************************************************************************
23 // File Description :
24 // class Signed_mesh_domain_3. See class description.
25 //******************************************************************************
26 
27 
28 #ifndef CGAL_MESH_3_SIGNED_MESH_DOMAIN_3_H
29 #define CGAL_MESH_3_SIGNED_MESH_DOMAIN_3_H
30 
31 #if defined(BOOST_MSVC)
32 # pragma warning(push)
33 # pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored
34 #endif
35 
36 #include <CGAL/Mesh_3/Labeled_mesh_domain_3.h>
37 
38 namespace CGAL {
39 
40 
53 template<class Function, class BGT>
55  : public Mesh_3::Labeled_mesh_domain_3<Function, BGT >
56 {
57 public:
59  typedef Mesh_3::Labeled_mesh_domain_3<Function, BGT> Base;
60 
62  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Subdomain Subdomain;
63  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Subdomain_index Subdomain_index;
64  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Surface_patch Surface_patch;
65  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Segment_3 Segment_3;
66  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Ray_3 Ray_3;
67  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Line_3 Line_3;
68  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Vector_3 Vector_3;
69  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Surface_patch_index Surface_patch_index;
70  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Index Index;
71  typedef typename Mesh_3::Labeled_mesh_domain_3<Function, BGT>::Intersection Intersection;
72  typedef typename BGT::Iso_cuboid_3 Iso_cuboid_3;
73  typedef typename Base::Sphere_3 Sphere_3;
74  typedef typename Base::Point_3 Point_3;
75  typedef typename Base::FT FT;
76 
80  Signed_mesh_domain_3(const Function& f,
81  const Sphere_3& bounding_sphere,
82  const FT& error_bound = FT(1e-3),
83  CGAL::Random* p_rng = NULL);
84 
85  Signed_mesh_domain_3(const Function& f,
86  const Bbox_3& bbox,
87  const FT& error_bound = FT(1e-3),
88  CGAL::Random* p_rng = NULL);
89 
90  Signed_mesh_domain_3(const Function& f,
91  const Iso_cuboid_3& bbox,
92  const FT& error_bound = FT(1e-3),
93  CGAL::Random* p_rng = NULL);
94 
97  {
98  if(delete_rng_)
99  delete p_rng_;
100  }
101 
108  {
110  : r_domain_(domain) {}
111 
112  template<class OutputIterator>
113  OutputIterator operator()(OutputIterator pts, const int n = 12) const;
114 
115  private:
116  const Signed_mesh_domain_3& r_domain_;
117  };
118 
121  {
122  return Construct_initial_points(*this);
123  }
124 
126  {
127  Is_in_domain(const Signed_mesh_domain_3& domain) : r_domain_(domain) {}
128 
129  Subdomain operator()(const Point_3& p) const
130  {
131  // f(p)<=0 means p is outside the domain
132  Subdomain_index index = (r_domain_.signed_function_)(p);
133  if ( Subdomain_index() >= index )
134  return Subdomain();
135  else
136  return Subdomain(index);
137  }
138  private:
139  const Signed_mesh_domain_3& r_domain_;
140  };
141 
142  Is_in_domain is_in_domain_object() const { return Is_in_domain(*this); }
143 
154  {
156  : r_domain_(domain) {}
157 
158  Surface_patch operator()(const Segment_3& s) const
159  {
160  return this->operator()(s.source(), s.target());
161  }
162 
163  Surface_patch operator()(const Ray_3& r) const
164  {
165  return clip_to_segment(r);
166  }
167 
168  Surface_patch operator()(const Line_3& l) const
169  {
170  return clip_to_segment(l);
171  }
172 
173  private:
176  Surface_patch operator()(const Point_3& a, const Point_3& b) const
177  {
178  // If f(a) != f(b), then [a,b] intersects some surface. Here we consider
179  // [a,b] intersects surface_patch labelled <f(a),f(b)> (or <f(b),f(a)>).
180  // It may be false, further rafinement will improve precision
181  const Subdomain_index value_a = r_domain_.signed_function_(a);
182  const Subdomain_index value_b = r_domain_.signed_function_(b);
183 
184  if ( (value_a > 0 || value_b > 0) && value_a != value_b )
185  return Surface_patch(r_domain_.make_surface_index(value_a, value_b));
186  else
187  return Surface_patch();
188  }
189 
193  template<typename Query>
194  Surface_patch clip_to_segment(const Query& query) const
195  {
196  typename cpp11::result_of<typename BGT::Intersect_3(Query, Iso_cuboid_3)>::type
197  clipped = CGAL::intersection(query, r_domain_.bounding_box());
198 
199  if(clipped)
200 #if CGAL_INTERSECTION_VERSION > 1
201  if(const Segment_3* s = boost::get<Segment_3>(&*clipped))
202  return this->operator()(*s);
203 #else
204  if(const Segment_3* s = object_cast<Segment_3>(&clipped))
205  return this->operator()(*s);
206 #endif
207 
208  return Surface_patch();
209  }
210 
211  private:
212  const Signed_mesh_domain_3& r_domain_;
213  };
214 
217  {
218  return Do_intersect_surface(*this);
219  }
220 
231  {
233  : r_domain_(domain) {}
234 
235  Intersection operator()(const Segment_3& s) const
236  {
237 #ifndef CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3
238  CGAL_precondition(r_domain_.do_intersect_surface_object()(s));
239 #endif // NOT CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3
240  return this->operator()(s.source(),s.target());
241  }
242 
243  Intersection operator()(const Ray_3& r) const
244  {
245  return clip_to_segment(r);
246  }
247 
248  Intersection operator()(const Line_3& l) const
249  {
250  return clip_to_segment(l);
251  }
252 
253  private:
261  Intersection operator()(const Point_3& a, const Point_3& b) const
262  {
263  // Functors
264  typename BGT::Compute_squared_distance_3 squared_distance =
265  BGT().compute_squared_distance_3_object();
266  typename BGT::Construct_midpoint_3 midpoint =
267  BGT().construct_midpoint_3_object();
268 
269  // Non const points
270  Point_3 p1 = a;
271  Point_3 p2 = b;
272  Point_3 mid = midpoint(p1, p2);
273 
274  // Cannot be const: those values are modified below.
275  Subdomain_index value_at_p1 = r_domain_.signed_function_(p1);
276  Subdomain_index value_at_p2 = r_domain_.signed_function_(p2);
277  Subdomain_index value_at_mid = r_domain_.signed_function_(mid,true);
278 
279  // If both extremities are in the same subdomain,
280  // there is no intersection.
281  // This should not happen...
282  if( value_at_p1 == value_at_p2 || (value_at_p1 <= 0 && value_at_p2 <= 0) )
283  {
284  return Intersection();
285  }
286 
287  // Construct the surface patch index and index from the values at 'a'
288  // and 'b'. Even if the bissection find out a different pair of
289  // values, the reported index will be constructed from the initial
290  // values.
291  const Surface_patch_index sp_index =
292  r_domain_.make_surface_index(value_at_p1, value_at_p2);
293  const Index index = r_domain_.index_from_surface_patch_index(sp_index);
294 
295  // Else lets find a point (by bisection)
296  // Bisection ends when the point is near than error bound from surface
297  while(true)
298  {
299  // If the two points are enough close, then we return midpoint
300  if ( squared_distance(p1, p2) < r_domain_.squared_error_bound_ )
301  {
302  CGAL_assertion(value_at_p1 != value_at_p2 && (value_at_p1 > 0 || value_at_p2 > 0));
303  return Intersection(mid, index, 2);
304  }
305 
306  // Else we must go on
307  // Here we consider that p1(a) is the source point. Thus, we keep p1 and
308  // change p2 if f(p1)!=f(p2).
309  // That allows us to find the first intersection from a of [a,b] with
310  // a surface.
311  if ( value_at_p1 != value_at_mid && (value_at_p1 > 0 || value_at_mid > 0) )
312  {
313  p2 = mid;
314  value_at_p2 = value_at_mid;
315  }
316  else
317  {
318  p1 = mid;
319  value_at_p1 = value_at_mid;
320  }
321 
322  mid = midpoint(p1, p2);
323  value_at_mid = r_domain_.signed_function_(mid,true);
324  }
325  }
326 
328  template<typename Query>
329  Intersection clip_to_segment(const Query& query) const
330  {
331  typename cpp11::result_of<typename BGT::Intersect_3(Query, Iso_cuboid_3)>::type
332  clipped = CGAL::intersection(query, r_domain_.bounding_box());
333 
334  if(clipped)
335 #if CGAL_INTERSECTION_VERSION > 1
336  if(const Segment_3* s = boost::get<Segment_3>(&*clipped))
337  return this->operator()(*s);
338 #else
339  if(const Segment_3* s = object_cast<Segment_3>(&clipped))
340  return this->operator()(*s);
341 #endif
342 
343  return Intersection();
344  }
345 
346  private:
347  const Signed_mesh_domain_3& r_domain_;
348  };
349 
352  {
353  return Construct_intersection(*this);
354  }
355 
357  Sphere_3 bounding_sphere(const Iso_cuboid_3& bbox) const
358  {
359  typename BGT::Construct_sphere_3 sphere = BGT().construct_sphere_3_object();
360  return sphere((bbox.min)(), (bbox.max)());
361  }
362 
363 protected:
365  const Function signed_function_;
366  FT squared_error_bound_;
367 
368 private:
369  CGAL::Random* p_rng_;
370  bool delete_rng_;
371 
372 private:
373  // Disabled copy constructor & assignment operator
375  Signed_mesh_domain_3(const Self& src);
376  Self& operator=(const Self& src);
377 
378 private:
380  Surface_patch_index make_surface_index(const Subdomain_index i,
381  const Subdomain_index j) const
382  {
383  if ( i < j ) return Surface_patch_index(i,j);
384  else return Surface_patch_index(j,i);
385  }
386 
388  FT squared_error_bound(const Sphere_3& sphere, const FT& error) const
389  {
390  typename BGT::Compute_squared_radius_3 squared_radius =
391  BGT().compute_squared_radius_3_object();
392  return squared_radius(sphere)*error*error;
393  }
394 
395 }; // end class Signed_mesh_domain_3
396 
397 
398 //-------------------------------------------------------
399 // Method implementation
400 //-------------------------------------------------------
401 template<class F, class BGT>
403  const F& f,
404  const Sphere_3& bounding_sphere,
405  const FT& error_bound,
406  CGAL::Random* p_rng)
407 : CGAL::Mesh_3::Labeled_mesh_domain_3<F, BGT>(f, bounding_sphere, error_bound)
408 , signed_function_(f)
409 , squared_error_bound_(squared_error_bound(bounding_sphere,error_bound))
410 , p_rng_(p_rng)
411 , delete_rng_(false)
412 {
413  // TODO : CGAL_ASSERT(0 < f(bounding_sphere.get_center()) ) ?
414  if(!p_rng_)
415  {
416  p_rng_ = new CGAL::Random(0);
417  delete_rng_ = true;
418  }
419 }
420 
421 template<class F, class BGT>
423  const F& f,
424  const Bbox_3& bbox,
425  const FT& error_bound,
426  CGAL::Random* p_rng)
427 : CGAL::Mesh_3::Labeled_mesh_domain_3<F, BGT>(f, bbox, error_bound)
428 , signed_function_(f)
429 , squared_error_bound_(squared_error_bound(CGAL::Mesh_3::Labeled_mesh_domain_3<F, BGT>::bounding_box(),error_bound))
430 , p_rng_(p_rng)
431 , delete_rng_(false)
432 {
433  // TODO : CGAL_ASSERT(0 < f(bounding_sphere.get_center()) ) ?
434  if(!p_rng_)
435  {
436  p_rng_ = new CGAL::Random(0);
437  delete_rng_ = true;
438  }
439 }
440 
441 template<class F, class BGT>
443  const F& f,
444  const Iso_cuboid_3& bbox,
445  const FT& error_bound,
446  CGAL::Random* p_rng)
447 : CGAL::Mesh_3::Labeled_mesh_domain_3<F, BGT>(f, bbox, error_bound, p_rng)
448 , signed_function_(f)
449 , squared_error_bound_(squared_error_bound(CGAL::Mesh_3::Labeled_mesh_domain_3<F, BGT>::bounding_box(),error_bound))
450 , p_rng_(p_rng)
451 , delete_rng_(false)
452 {
453  // TODO : CGAL_ASSERT(0 < f( bbox.get_center()) ) ?
454  if(!p_rng_)
455  {
456  p_rng_ = new CGAL::Random(0);
457  delete_rng_ = true;
458  }
459 }
460 
461 template<class F, class BGT>
462 template<class OutputIterator>
463 OutputIterator
464 Signed_mesh_domain_3<F,BGT>::Construct_initial_points::operator()(
465  OutputIterator pts,
466  const int nb_points) const
467 {
468  // Create point_iterator on and in bounding_sphere
469  typedef Random_points_on_sphere_3<Point_3> Random_points_on_sphere_3;
470  typedef Random_points_in_sphere_3<Point_3> Random_points_in_sphere_3;
471 
472 
473  const FT squared_radius = BGT().compute_squared_radius_3_object()(
474  r_domain_.bounding_sphere(r_domain_.bounding_box()));
475 
476  const double radius = std::sqrt(CGAL::to_double(squared_radius));
477 
478  CGAL::Random& rng = *(r_domain_.p_rng_);
479  Random_points_on_sphere_3 random_point_on_sphere(radius, rng);
480  Random_points_in_sphere_3 random_point_in_sphere(radius, rng);
481 
482  // Get some functors
483  typename BGT::Construct_segment_3 segment_3 =
484  BGT().construct_segment_3_object();
485  typename BGT::Construct_vector_3 vector_3 =
486  BGT().construct_vector_3_object();
487  typename BGT::Construct_translated_point_3 translate =
488  BGT().construct_translated_point_3_object();
489  typename BGT::Construct_center_3 center = BGT().construct_center_3_object();
490 
491  // Get translation from origin to sphere center
492  Point_3 center_pt = center(r_domain_.bounding_sphere(r_domain_.bounding_box()));
493  const Vector_3 sphere_translation = vector_3(CGAL::ORIGIN, center_pt);
494 
495  // Create nb_point points
496  int n = nb_points;
497 #ifdef CGAL_MESH_3_VERBOSE
498  std::cerr << "construct initial points:\n";
499 #endif
500  while ( 0 != n )
501  {
502  // Get a random segment
503  const Point_3 random_point = translate(*random_point_on_sphere,
504  sphere_translation);
505  const Segment_3 random_seg = segment_3(center_pt, random_point);
506 
507  // Add the intersection to the output if it exists
508  Surface_patch surface = r_domain_.do_intersect_surface_object()(random_seg);
509  if ( surface )
510  {
511  const Point_3 intersect_pt = CGAL::cpp11::get<0>(
512  r_domain_.construct_intersection_object()(random_seg));
513  *pts++ = std::make_pair(intersect_pt,
514  r_domain_.index_from_surface_patch_index(*surface));
515  --n;
516 
517 #ifdef CGAL_MESH_3_VERBOSE
518  std::cerr << boost::format("\r \r"
519  "%1%/%2% initial point(s) found...")
520  % (nb_points - n)
521  % nb_points;
522 #endif
523  }
524  else
525  {
526  // Get a new random point into sphere as center of object
527  // It may be necessary if the center of the domain is empty, e.g. torus
528  // In general case, it is good for input point dispersion
529  ++random_point_in_sphere;
530  center_pt = translate(*random_point_in_sphere, sphere_translation);
531  }
532  ++random_point_on_sphere;
533  }
534 
535 #ifdef CGAL_MESH_3_VERBOSE
536  std::cerr << "\n";
537 #endif
538  return pts;
539 }
540 
541 
542 } // end namespace CGAL
543 
544 #if defined(BOOST_MSVC)
545 # pragma warning(pop)
546 #endif
547 
548 #endif // CGAL_SIGNED_MESH_DOMAIN_3_H
Definition: Signed_mesh_domain_3.h:230
virtual ~Signed_mesh_domain_3()
Destructor.
Definition: Signed_mesh_domain_3.h:96
Construct_initial_points construct_initial_points_object() const
Returns Construct_initial_points object.
Definition: Signed_mesh_domain_3.h:120
Definition: Signed_mesh_domain_3.h:107
Do_intersect_surface do_intersect_surface_object() const
Returns Do_intersect_surface object.
Definition: Signed_mesh_domain_3.h:216
Definition: Signed_mesh_domain_3.h:153
Definition: write_c3t3_to_gmsh_file.h:50
const Function signed_function_
The function which answers subdomain queries (this would not be required if Lmd3._function were prote...
Definition: Signed_mesh_domain_3.h:365
Definition: Signed_mesh_domain_3.h:54
Sphere_3 bounding_sphere(const Iso_cuboid_3 &bbox) const
Returns the bounding sphere of an Iso_cuboid_3.
Definition: Signed_mesh_domain_3.h:357
Mesh_3::Labeled_mesh_domain_3< Function, BGT >::Subdomain Subdomain
Public types.
Definition: Signed_mesh_domain_3.h:62
Construct_intersection construct_intersection_object() const
Returns Construct_intersection object.
Definition: Signed_mesh_domain_3.h:351
Definition: Signed_mesh_domain_3.h:125
Signed_mesh_domain_3(const Function &f, const Sphere_3 &bounding_sphere, const FT &error_bound=FT(1e-3), CGAL::Random *p_rng=NULL)
Constructor.
Mesh_3::Labeled_mesh_domain_3< Function, BGT > Base
Base type.
Definition: Signed_mesh_domain_3.h:59