1 // Copyright (c) 1997-2000 Max-Planck-Institute Saarbruecken (Germany).
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/Convex_hull_d/include/CGAL/Convex_hull_d.h $
7 // $Id: Convex_hull_d.h 0d66e19 2020-07-24T17:05:10+02:00 Mael Rouxel-Labbé
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
12 //---------------------------------------------------------------------
13 // file generated by notangle from Convex_hull_d.lw
14 // please debug or modify web file
15 // mails and bugs: Michael.Seel@mpi-sb.mpg.de
16 // based on LEDA architecture by S. Naeher, C. Uhrig
17 // coding: K. Mehlhorn, M. Seel
18 // debugging and templatization: M. Seel
19 //---------------------------------------------------------------------
20
21 #ifndef CGAL_CONVEX_HULL_D_H
22 #define CGAL_CONVEX_HULL_D_H
23
24 #include <CGAL/license/Convex_hull_d.h>
25
26 #define CGAL_DEPRECATED_HEADER "<CGAL/Convex_hull_d.h>"
27 #define CGAL_DEPRECATED_MESSAGE_DETAILS \
28 "The Triangulation package (see https://doc.cgal.org/latest/Triangulation) should be used instead."
29 #include <CGAL/internal/deprecation_warning.h>
30
31 /*{\Manpage {Convex_hull_d}{R}{Convex Hulls}{C}}*/
32
33 /*{\Mdefinition An instance |\Mvar| of type |\Mname| is the convex
34 hull of a multi-set |S| of points in $d$-dimensional space. We call
35 |S| the underlying point set and $d$ or |dim| the dimension of the
36 underlying space. We use |dcur| to denote the affine dimension of |S|.
37 The data type supports incremental construction of hulls.
38
39 The closure of the hull is maintained as a simplicial complex, i.e.,
40 as a collection of simplices. The intersection of any two is a face of
41 both\cgalFootnote{The empty set if a facet of every simplex.}. In the
42 sequel we reserve the word simplex for the simplices of dimension
43 |dcur|. For each simplex there is a handle of type |Simplex_handlex|
44 and for each vertex there is a handle of type |Vertex_handle|. Each
45 simplex has $1 + |dcur|$ vertices indexed from $0$ to |dcur|; for a
46 simplex $s$ and an index $i$, |C.vertex(s,i)| returns the $i$-th
47 vertex of $s$. For any simplex $s$ and any index $i$ of $s$ there may
48 or may not be a simplex $t$ opposite to the $i$-th vertex of $s$. The
49 function |C.opposite_simplex(s,i)| returns $t$ if it exists and
50 returns |Simplex_handle()| (the undefined handle) otherwise. If $t$
51 exists then $s$ and $t$ share |dcur| vertices, namely all but the
52 vertex with index $i$ of $s$ and the vertex with index
53 |C.index_of_vertex_in_opposite_simplex(s,i)| of $t$. Assume that $t$
54 exists and let |j = C.index_of_vertex_in_opposite_simplex(s,i)|. Then
55 $s =$ |C.opposite_simplex(t,j)| and $i =$
56 |C.index_of_vertex_in_opposite_simplex(t,j)|.
57
58 The boundary of the hull is also a simplicial complex. All simplices
59 in this complex have dimension $|dcur| - 1$. For each boundary simplex
60 there is a handle of type |Facet_handle|. Each facet has |dcur| vertices
61 indexed from $0$ to $|dcur| - 1$. If |dcur > 1| then for each facet $f$
62 and each index $i$, $0 \le i < |dcur|$, there is a facet $g$ opposite
63 to the $i$-th vertex of $f$. The function |C.opposite_facet(f,i)|
64 returns $g$. Two neighboring facets $f$ and $g$ share |dcur - 1|
65 vertices, namely all but the vertex with index $i$ of $f$ and the
66 vertex with index |C.index_of_vertex_in_opposite_facet(f,i)| of $g$.
67 Let |j = C.index_of_vertex_in_opposite_facet(f,i)|. Then
68 |f = C.opposite_facet(g,j)| and
69 |i = C.index_of_vertex_in_opposite_facet(g,j)|.}*/
70
71 #include <CGAL/basic.h>
72 #include <CGAL/Origin.h>
73 #include <CGAL/Unique_hash_map.h>
74 #include <CGAL/Regular_complex_d.h>
75 #include <CGAL/Handle_for.h>
76 #include <list>
77 #include <vector>
78
79 #include <CGAL/Kernel_d/debug.h>
80
81 namespace CGAL {
82
83 template <typename HP, typename H> class Facet_iterator_rep_;
84 template <typename HP, typename H> class Facet_iterator_;
85
86 template <typename Hull_pointer, typename Handle>
87 class Facet_iterator_rep_
88 {
89 CGAL::Unique_hash_map<Handle,bool>* pvisited_;
90 std::list<Handle>* pcandidates_;
91 Hull_pointer hull_;
92 Handle current_;
93 friend class Facet_iterator_<Hull_pointer,Handle>;
94
add_candidates()95 void add_candidates()
96 { CGAL_assertion(pvisited_ && pcandidates_ && hull_);
97 for(int i = 1; i <= hull_->current_dimension(); ++i) {
98 Handle f = hull_->opposite_simplex(current_,i);
99 if ( !(*pvisited_)[f] ) {
100 pcandidates_->push_front(f);
101 (*pvisited_)[f] = true;
102 }
103 }
104 }
105 public:
Facet_iterator_rep_()106 Facet_iterator_rep_() :
107 pvisited_(0), pcandidates_(0), hull_(0), current_() {}
Facet_iterator_rep_(Hull_pointer p,Handle h)108 Facet_iterator_rep_(Hull_pointer p, Handle h) :
109 pvisited_(0), pcandidates_(0), hull_(p), current_(h) {}
~Facet_iterator_rep_()110 ~Facet_iterator_rep_()
111 { if (pvisited_) delete pvisited_;
112 if (pcandidates_) delete pcandidates_; }
113 };
114
115 template <typename Hull_pointer, typename Handle>
116 class Facet_iterator_ : private
117 Handle_for<Facet_iterator_rep_<Hull_pointer,Handle> >
118 { typedef Facet_iterator_<Hull_pointer,Handle> Self;
119 typedef Facet_iterator_rep_<Hull_pointer,Handle> Rep;
120 typedef Handle_for< Facet_iterator_rep_<Hull_pointer,Handle> > Base;
121
122 using Base::ptr;
123
124 public:
125 typedef typename Handle::value_type value_type;
126 typedef typename Handle::pointer pointer;
127 typedef typename Handle::reference reference;
128 typedef typename Handle::difference_type difference_type;
129 typedef std::forward_iterator_tag iterator_category;
130
Facet_iterator_()131 Facet_iterator_() : Base( Rep() ) {}
Facet_iterator_(Hull_pointer p,Handle h)132 Facet_iterator_(Hull_pointer p, Handle h) : Base( Rep(p,h) )
133 { ptr()->pvisited_ = new Unique_hash_map<Handle,bool>(false);
134 ptr()->pcandidates_ = new std::list<Handle>;
135 (*(ptr()->pvisited_))[ptr()->current_]=true;
136 ptr()->add_candidates();
137 }
138
139 reference operator*() const
140 { return ptr()->current_.operator*(); }
141 pointer operator->() const
142 { return ptr()->current_.operator->(); }
143
144 Self& operator++()
145 { if ( ptr()->current_ == Handle() ) return *this;
146 if ( ptr()->pcandidates_->empty() ) ptr()->current_ = Handle();
147 else {
148 ptr()->current_ = ptr()->pcandidates_->back();
149 ptr()->pcandidates_->pop_back();
150 ptr()->add_candidates();
151 }
152 return *this;
153 }
154 Self operator++(int)
155 { Self tmp = *this; ++*this; return tmp; }
156 bool operator==(const Self& x) const
157 { return ptr()->current_ == x.ptr()->current_; }
158 bool operator!=(const Self& x) const
159 { return !operator==(x); }
160
Handle()161 operator Handle() { return ptr()->current_; }
162
163 };
164
165
166 template <typename HP, typename VH, typename FH>
167 class Hull_vertex_iterator_rep_;
168 template <typename HP, typename VH, typename FH>
169 class Hull_vertex_iterator_;
170
171 template <typename Hull_pointer, typename VHandle, typename FHandle>
172 class Hull_vertex_iterator_rep_
173 {
174 CGAL::Unique_hash_map<VHandle,bool>* pvisited_;
175 Hull_pointer hull_;
176 VHandle v_; FHandle f_; int i_;
177 friend class Hull_vertex_iterator_<Hull_pointer,VHandle,FHandle>;
178
advance()179 void advance()
180 { CGAL_assertion(pvisited_ && hull_);
181 if ( f_ == FHandle() ) return;
182 bool search_next = true; ++i_;
183 while ( search_next ) {
184 while(i_ < hull_->current_dimension()) {
185 v_ = hull_->vertex_of_facet(f_,i_);
186 if ( !(*pvisited_)[v_] ) { search_next=false; break; }
187 ++i_;
188 }
189 if ( search_next ) { i_=0; ++f_; }
190 if ( f_ == FHandle() )
191 { search_next=false; v_ = VHandle(); }
192 }
193 (*pvisited_)[v_] = true;
194 }
195 public:
Hull_vertex_iterator_rep_()196 Hull_vertex_iterator_rep_() :
197 pvisited_(0), hull_(0), i_(0) {}
Hull_vertex_iterator_rep_(Hull_pointer p,FHandle f)198 Hull_vertex_iterator_rep_(Hull_pointer p, FHandle f) :
199 pvisited_(0), hull_(p), f_(f), i_(-1) {}
~Hull_vertex_iterator_rep_()200 ~Hull_vertex_iterator_rep_()
201 { if (pvisited_) delete pvisited_; }
202 };
203
204 template <typename Hull_pointer, typename VHandle, typename FHandle>
205 class Hull_vertex_iterator_ : private
206 Handle_for< Hull_vertex_iterator_rep_<Hull_pointer,VHandle,FHandle> >
207 { typedef Hull_vertex_iterator_<Hull_pointer,VHandle,FHandle> Self;
208 typedef Hull_vertex_iterator_rep_<Hull_pointer,VHandle,FHandle> Rep;
209 typedef Handle_for< Rep > Base;
210
211 using Base::ptr;
212
213 public:
214 typedef typename VHandle::value_type value_type;
215 typedef typename VHandle::pointer pointer;
216 typedef typename VHandle::reference reference;
217 typedef typename VHandle::difference_type difference_type;
218 typedef std::forward_iterator_tag iterator_category;
219
Hull_vertex_iterator_()220 Hull_vertex_iterator_() : Base( Rep() ) {}
Hull_vertex_iterator_(Hull_pointer p,FHandle f)221 Hull_vertex_iterator_(Hull_pointer p, FHandle f) : Base( Rep(p,f) )
222 { ptr()->pvisited_ = new Unique_hash_map<VHandle,bool>(false);
223 ptr()->advance();
224 }
225
226 reference operator*() const
227 { return ptr()->v_.operator*(); }
228 pointer operator->() const
229 { return ptr()->v_.operator->(); }
230
231 Self& operator++()
232 { if ( ptr()->v_ == VHandle() ) return *this;
233 ptr()->advance();
234 return *this;
235 }
236 Self operator++(int)
237 { Self tmp = *this; ++*this; return tmp; }
238 bool operator==(const Self& x) const
239 { return ptr()->v_ == x.ptr()->v_; }
240 bool operator!=(const Self& x) const
241 { return !operator==(x); }
242
VHandle()243 operator VHandle() { return ptr()->v_; }
244
245 };
246
247 template <class Vertex, class Point>
248 struct Point_from_Vertex {
249 typedef Vertex argument_type;
250 typedef Point result_type;
operatorPoint_from_Vertex251 result_type& operator()(argument_type& x) const
252 { return x.point(); }
operatorPoint_from_Vertex253 const result_type& operator()(const argument_type& x) const
254 { return x.point(); }
255 };
256
257
258 template <typename H1, typename H2>
259 struct list_collector {
260 std::list<H1>& L_;
list_collectorlist_collector261 list_collector(std::list<H1>& L) : L_(L) {}
operatorlist_collector262 void operator()(H2 f) const
263 { L_.push_back(static_cast<H1>(f)); }
264 };
265
266
267 template <class R_>
268 class Convex_hull_d : public Regular_complex_d<R_>
269 {
270 typedef Regular_complex_d<R_> Base;
271 typedef Convex_hull_d<R_> Self;
272
273 public:
274
275 using Base::new_simplex;
276 using Base::new_vertex;
277 using Base::associate_vertex_with_simplex;
278 using Base::associate_point_with_vertex;
279 using Base::set_neighbor;
280
281 using Base::kernel;
282 using Base::dcur;
283
284 /*{\Xgeneralization Regular_complex_d<R>}*/
285 /*{\Mtypes 6.5}*/
286 typedef R_ R;
287 /*{\Mtypemember the representation class.}*/
288 typedef typename R::Point_d Point_d;
289 /*{\Mtypemember the point type.}*/
290 typedef typename R::Hyperplane_d Hyperplane_d;
291 /*{\Mtypemember the hyperplane type.}*/
292
293 typedef typename R::Vector_d Vector_d;
294 typedef typename R::Ray_d Ray_d;
295 typedef typename R::RT RT;
296 typedef std::list<Point_d> Point_list;
297 // make traits types locally available
298
299 typedef typename Base::Simplex_handle Simplex_handle;
300 /*{\Mtypemember handle for simplices.}*/
301
302 typedef typename Base::Simplex_handle Facet_handle;
303 /*{\Mtypemember handle for facets.}*/
304
305 typedef typename Base::Vertex_handle Vertex_handle;
306 /*{\Mtypemember handle for vertices.}*/
307
308 typedef typename Base::Simplex_iterator Simplex_iterator;
309 /*{\Mtypemember iterator for simplices.}*/
310
311 typedef typename Base::Vertex_iterator Vertex_iterator;
312 /*{\Mtypemember iterator for vertices.}*/
313
314 typedef Facet_iterator_<Self*,Facet_handle> Facet_iterator;
315 /*{\Mtypemember iterator for facets.}*/
316
317 typedef Hull_vertex_iterator_<Self*,Vertex_handle,Facet_iterator>
318 Hull_vertex_iterator;
319 /*{\Mtypemember iterator for vertices that are part of the convex hull.}*/
320
321 /*{\Mtext Note that each iterator fits the handle concept, i.e. iterators
322 can be used as handles. Note also that all iterator and handle types
323 come also in a const flavor, e.g., |Vertex_const_iterator| is the
324 constant version of |Vertex_iterator|. Thus use the const version
325 whenever the convex hull object is referenced as constant.}*/
326
327 #define CGAL_USING(t) typedef typename Base::t t
328 CGAL_USING(Simplex_const_iterator);CGAL_USING(Vertex_const_iterator);
329 CGAL_USING(Simplex_const_handle);CGAL_USING(Vertex_const_handle);
330 #undef CGAL_USING
331 typedef Simplex_const_handle Facet_const_handle;
332 typedef Facet_iterator_<const Self*,Facet_const_handle> Facet_const_iterator;
333 typedef Hull_vertex_iterator_<const Self*,Vertex_const_handle,
334 Facet_const_iterator> Hull_vertex_const_iterator;
335
336 typedef typename Point_list::const_iterator Point_const_iterator;
337 /*{\Mtypemember const iterator for all inserted points.}*/
338
339 typedef typename Vertex_handle::value_type Vertex;
340
341 typedef CGAL::Iterator_project<
342 Hull_vertex_const_iterator, Point_from_Vertex<Vertex,Point_d>,
343 const Point_d&, const Point_d*> Hull_point_const_iterator;
344 /*{\Mtypemember const iterator for all points of the hull.}*/
345
346 protected:
347 Point_list all_pnts_;
348 Vector_d quasi_center_; // sum of the vertices of origin simplex
349 Simplex_handle origin_simplex_; // pointer to the origin simplex
350 Facet_handle start_facet_; // pointer to some facet on the surface
351 Vertex_handle anti_origin_;
352
353 public: // until there are template friend functions possible
center()354 Point_d center() const // compute center from quasi center
355 { typename R::Vector_to_point_d to_point =
356 kernel().vector_to_point_d_object();
357 return to_point(quasi_center_/RT(dcur + 1)); }
quasi_center()358 const Vector_d& quasi_center() const
359 { return quasi_center_; }
origin_simplex()360 Simplex_const_handle origin_simplex() const
361 { return origin_simplex_; }
base_facet_plane(Simplex_handle s)362 Hyperplane_d base_facet_plane(Simplex_handle s) const
363 { return s -> hyperplane_of_base_facet(); }
base_facet_plane(Simplex_const_handle s)364 Hyperplane_d base_facet_plane(Simplex_const_handle s) const
365 { return s -> hyperplane_of_base_facet(); }
visited_mark(Simplex_handle s)366 bool& visited_mark(Simplex_handle s) const
367 { return s->visited(); }
368
369 protected:
370 std::size_t num_of_bounded_simplices;
371 std::size_t num_of_unbounded_simplices;
372 std::size_t num_of_visibility_tests;
373 std::size_t num_of_vertices;
374
375 void compute_equation_of_base_facet(Simplex_handle s);
376 /*{\Xop computes the equation of the base facet of $s$ and sets the
377 |base_facet| member of $s$. The equation is normalized such
378 that the origin simplex lies in the negative halfspace.}*/
379
is_base_facet_visible(Simplex_handle s,const Point_d & x)380 bool is_base_facet_visible(Simplex_handle s, const Point_d& x) const
381 { typename R::Has_on_positive_side_d has_on_positive_side =
382 kernel().has_on_positive_side_d_object();
383 return has_on_positive_side(s->hyperplane_of_base_facet(),x); }
384 /*{\Xop returns true if $x$ sees the base facet of $s$, i.e., lies in
385 its positive halfspace.}*/
386
387 bool contains_in_base_facet(Simplex_handle s, const Point_d& x) const;
388 /*{\Xop returns true if $x$ lies in the closure of the base facet of
389 $s$.}*/
390
391
392 void visibility_search(Simplex_handle S, const Point_d& x,
393 std::list<Simplex_handle>& visible_simplices,
394 std::size_t& num_of_visited_simplices,
395 int& location, Facet_handle& f) const;
396 /*{\Xop adds all unmarked unbounded simplices with $x$-visible base
397 facet to |visible_simplices| and marks them. In |location| the
398 procedure returns the position of |x| with respect to the
399 current hull: $-1$ for inside, $0$ for on the boundary,
400 and $+1$ for outside; the initial value of |location| for the
401 outermost call must be $-1$. If $x$ is contained in the
402 boundary of |\Mvar| then a facet incident to $x$ is returned
403 in $f$.}*/
404
405 void clear_visited_marks(Simplex_handle s) const;
406 /*{\Xop removes the mark bits from all marked simplices reachable from $s$.}*/
407
408 void dimension_jump(Simplex_handle S, Vertex_handle x);
409 /*{\Xop Adds a new vertex $x$ to the triangulation. The point associated
410 with $x$ lies outside the affine hull of the current point set. }*/
411
412 void visible_facets_search(Simplex_handle S, const Point_d& x,
413 std::list< Facet_handle >& VisibleFacets,
414 std::size_t& num_of_visited_facets) const;
415
416 public:
417
418 /*{\Mcreation 3}*/
419
420 Convex_hull_d(int d, const R& Kernel = R());
421 /*{\Mcreate creates an instance |\Mvar| of type |\Mtype|. The
422 dimension of the underlying space is $d$ and |S| is initialized to the
423 empty point set. The traits class |R| specifies the models of
424 all types and the implementations of all geometric primitives used by
425 the convex hull class. The default model is one of the $d$-dimensional
426 representation classes (e.g., |Homogeneous_d|).}*/
427
428 protected:
429 /*{\Mtext The data type |\Mtype| offers neither copy constructor nor
430 assignment operator.}*/
431 Convex_hull_d(const Self&);
432 Convex_hull_d& operator=(const Self&);
433 public:
434
435
436 /*{\Moperations 3}*/
437 /*{\Mtext All operations below that take a point |x| as argument have
438 the common precondition that |x| is a point of ambient space.}*/
439
dimension()440 int dimension() const { return Base::dimension(); }
441 /*{\Mop returns the dimension of ambient space}*/
current_dimension()442 int current_dimension() const { return Base::current_dimension(); }
443 /*{\Mop returns the affine dimension |dcur| of $S$.}*/
444
associated_point(Vertex_handle v)445 Point_d associated_point(Vertex_handle v) const
446 { return Base::associated_point(v); }
447 /*{\Mop returns the point associated with vertex $v$.}*/
associated_point(Vertex_const_handle v)448 Point_d associated_point(Vertex_const_handle v) const
449 { return Base::associated_point(v); }
450
vertex_of_simplex(Simplex_handle s,int i)451 Vertex_handle vertex_of_simplex(Simplex_handle s, int i) const
452 { return Base::vertex(s,i); }
453 /*{\Mop returns the vertex corresponding to the $i$-th vertex of $s$.\\
454 \precond $0 \leq i \leq |dcur|$. }*/
vertex_of_simplex(Simplex_const_handle s,int i)455 Vertex_const_handle vertex_of_simplex(Simplex_const_handle s, int i) const
456 { return Base::vertex(s,i); }
457
point_of_simplex(Simplex_handle s,int i)458 Point_d point_of_simplex(Simplex_handle s,int i) const
459 { return associated_point(vertex_of_simplex(s,i)); }
460 /*{\Mop same as |C.associated_point(C.vertex_of_simplex(s,i))|. }*/
point_of_simplex(Simplex_const_handle s,int i)461 Point_d point_of_simplex(Simplex_const_handle s,int i) const
462 { return associated_point(vertex_of_simplex(s,i)); }
463
464
opposite_simplex(Simplex_handle s,int i)465 Simplex_handle opposite_simplex(Simplex_handle s,int i) const
466 { return Base::opposite_simplex(s,i); }
467 /*{\Mop returns the simplex opposite to the $i$-th vertex of $s$
468 (|Simplex_handle()| if there is no such simplex).
469 \precond $0 \leq i \leq |dcur|$. }*/
opposite_simplex(Simplex_const_handle s,int i)470 Simplex_const_handle opposite_simplex(Simplex_const_handle s,int i) const
471 { return Base::opposite_simplex(s,i); }
472
473
index_of_vertex_in_opposite_simplex(Simplex_handle s,int i)474 int index_of_vertex_in_opposite_simplex(Simplex_handle s,int i) const
475 { return Base::index_of_opposite_vertex(s,i); }
476 /*{\Mop returns the index of the vertex opposite to the $i$-th vertex
477 of $s$. \precond $0 \leq i \leq |dcur|$ and there is a
478 simplex opposite to the $i$-th vertex of $s$. }*/
index_of_vertex_in_opposite_simplex(Simplex_const_handle s,int i)479 int index_of_vertex_in_opposite_simplex(Simplex_const_handle s,int i) const
480 { return Base::index_of_opposite_vertex(s,i); }
481
simplex(Vertex_handle v)482 Simplex_handle simplex(Vertex_handle v) const
483 { return Base::simplex(v); }
484 /*{\Mop returns a simplex of which $v$ is a node. Note that this
485 simplex is not unique. }*/
simplex(Vertex_const_handle v)486 Simplex_const_handle simplex(Vertex_const_handle v) const
487 { return Base::simplex(v); }
488
index(Vertex_handle v)489 int index(Vertex_handle v) const { return Base::index(v); }
490 /*{\Mop returns the index of $v$ in |simplex(v)|.}*/
index(Vertex_const_handle v)491 int index(Vertex_const_handle v) const { return Base::index(v); }
492
vertex_of_facet(Facet_handle f,int i)493 Vertex_handle vertex_of_facet(Facet_handle f, int i) const
494 { return vertex_of_simplex(f,i+1); }
495 /*{\Mop returns the vertex corresponding to the $i$-th vertex of $f$.
496 \precond $0 \leq i < |dcur|$. }*/
vertex_of_facet(Facet_const_handle f,int i)497 Vertex_const_handle vertex_of_facet(Facet_const_handle f, int i) const
498 { return vertex_of_simplex(f,i+1); }
499
point_of_facet(Facet_handle f,int i)500 Point_d point_of_facet(Facet_handle f, int i) const
501 { return point_of_simplex(f,i+1); }
502 /*{\Mop same as |C.associated_point(C.vertex_of_facet(f,i))|.}*/
point_of_facet(Facet_const_handle f,int i)503 Point_d point_of_facet(Facet_const_handle f, int i) const
504 { return point_of_simplex(f,i+1); }
505
opposite_facet(Facet_handle f,int i)506 Facet_handle opposite_facet(Facet_handle f, int i) const
507 { return opposite_simplex(f,i+1); }
508 /*{\Mop returns the facet opposite to the $i$-th vertex of $f$
509 (|Facet_handle()| if there is no such facet). \precond $0 \leq i <
510 |dcur|$ and |dcur > 1|. }*/
opposite_facet(Facet_const_handle f,int i)511 Facet_const_handle opposite_facet(Facet_const_handle f, int i) const
512 { return opposite_simplex(f,i+1); }
513
index_of_vertex_in_opposite_facet(Facet_handle f,int i)514 int index_of_vertex_in_opposite_facet(Facet_handle f, int i) const
515 { return index_of_vertex_in_opposite_simplex(f,i+1) - 1; }
516 /*{\Mop returns the index of the vertex opposite to the $i$-th vertex of
517 $f$. \precond $0 \leq i < |dcur|$ and |dcur > 1|.}*/
index_of_vertex_in_opposite_facet(Facet_const_handle f,int i)518 int index_of_vertex_in_opposite_facet(Facet_const_handle f, int i) const
519 { return index_of_vertex_in_opposite_simplex(f,i+1) - 1; }
520
hyperplane_supporting(Facet_handle f)521 Hyperplane_d hyperplane_supporting(Facet_handle f) const
522 { return f -> hyperplane_of_base_facet(); }
523 /*{\Mop returns a hyperplane supporting facet |f|. The hyperplane is
524 oriented such that the interior of |\Mvar| is on the negative
525 side of it. \precond |f| is a facet of |\Mvar| and |dcur > 1|.}*/
hyperplane_supporting(Facet_const_handle f)526 Hyperplane_d hyperplane_supporting(Facet_const_handle f) const
527 { return f -> hyperplane_of_base_facet(); }
528
529
530 Vertex_handle insert(const Point_d& x);
531 /*{\Mop adds point |x| to the underlying set of points. If $x$ is
532 equal to (the point associated with) a vertex of the current hull this
533 vertex is returned and its associated point is changed to $x$. If $x$
534 lies outside the current hull, a new vertex |v| with associated point
535 $x$ is added to the hull and returned. In all other cases, i.e., if
536 $x$ lies in the interior of the hull or on the boundary but not on a
537 vertex, the current hull is not changed and |Vertex_handle()| is
538 returned. If |CGAL_CHECK_EXPENSIVE| is defined then the validity
539 check |is_valid(true)| is executed as a post condition.}*/
540
541 template <typename Forward_iterator>
insert(Forward_iterator first,Forward_iterator last)542 void insert(Forward_iterator first, Forward_iterator last)
543 { while (first != last) insert(*first++); }
544 /*{\Mop adds |S = set [first,last)| to the underlying set of
545 points. If any point |S[i]| is equal to (the point associated with) a
546 vertex of the current hull its associated point is changed to |S[i]|.}*/
547
548
is_dimension_jump(const Point_d & x)549 bool is_dimension_jump(const Point_d& x) const
550 /*{\Mop returns true if $x$ is not contained in the affine hull of |S|.}*/
551 {
552 if (current_dimension() == dimension()) return false;
553 typename R::Contained_in_affine_hull_d contained_in_affine_hull =
554 kernel().contained_in_affine_hull_d_object();
555 return ( !contained_in_affine_hull(origin_simplex_->points_begin(),
556 origin_simplex_->points_begin()+current_dimension()+1,x) );
557 }
558
559
560 std::list<Facet_handle> facets_visible_from(const Point_d& x);
561 /*{\Mop returns the list of all facets that are visible from |x|.\\
562 \precond |x| is contained in the affine hull of |S|.}*/
563
564 Bounded_side bounded_side(const Point_d& x);
565 /*{\Mop returns |ON_BOUNDED_SIDE| (|ON_BOUNDARY|,|ON_UNBOUNDED_SIDE|)
566 if |x| is contained in the interior (lies on the boundary, is contained
567 in the exterior) of |\Mvar|. \precond |x| is contained in the affine
568 hull of |S|.}*/
569
570
is_unbounded_simplex(Simplex_handle S)571 bool is_unbounded_simplex(Simplex_handle S) const
572 { return vertex_of_simplex(S,0) == anti_origin_; }
is_unbounded_simplex(Simplex_const_handle S)573 bool is_unbounded_simplex(Simplex_const_handle S) const
574 { return vertex_of_simplex(S,0) == anti_origin_; }
is_bounded_simplex(Simplex_handle S)575 bool is_bounded_simplex(Simplex_handle S) const
576 { return vertex_of_simplex(S,0) != anti_origin_; }
is_bounded_simplex(Simplex_const_handle S)577 bool is_bounded_simplex(Simplex_const_handle S) const
578 { return vertex_of_simplex(S,0) != anti_origin_; }
579
clear(int d)580 void clear(int d)
581 /*{\Mop reinitializes |\Mvar| to an empty hull in $d$-dimensional space.}*/
582 {
583 typename R::Construct_vector_d create =
584 kernel().construct_vector_d_object();
585 quasi_center_ = create(d,NULL_VECTOR);
586 anti_origin_ = Vertex_handle();
587 origin_simplex_ = Simplex_handle();
588 all_pnts_.clear();
589 Base::clear(d);
590 num_of_vertices = 0;
591 num_of_unbounded_simplices = num_of_bounded_simplices = 0;
592 num_of_visibility_tests = 0;
593 }
594
number_of_vertices()595 std::size_t number_of_vertices() const
596 /*{\Mop returns the number of vertices of |\Mvar|.}*/
597 { return num_of_vertices; }
598
number_of_facets()599 std::size_t number_of_facets() const
600 /*{\Mop returns the number of facets of |\Mvar|.}*/
601 { return num_of_unbounded_simplices; }
602
number_of_simplices()603 std::size_t number_of_simplices() const
604 /*{\Mop returns the number of bounded simplices of |\Mvar|.}*/
605 { return num_of_bounded_simplices; }
606
print_statistics()607 void print_statistics()
608 /*{\Mop gives information about the size of the current hull and the
609 number of visibility tests performed.}*/
610 {
611 std::cout << "Convex_hull_d ("
612 << current_dimension() << "/" << dimension()
613 << ") - statistic" << std::endl;
614 std::cout<<" # points = " << all_pnts_.size() << std::endl;
615 std::cout<<" # vertices = " << num_of_vertices << std::endl;
616 std::cout<<" # unbounded simplices = " << num_of_unbounded_simplices
617 << std::endl;
618 std::cout<<" # bounded simplices = " << num_of_bounded_simplices
619 << std::endl;
620 std::cout<<" # visibility tests = " << num_of_visibility_tests
621 << std::endl;
622 }
623
624 class chull_has_double_coverage {};
625 class chull_has_local_non_convexity {};
626 class chull_has_center_on_wrong_side_of_hull_facet {};
627
628 bool is_valid(bool throw_exceptions = false) const;
629 /*{\Mop checks the validity of the data structure.
630 If |throw_exceptions == thrue| then the program throws
631 the following exceptions to inform about the problem.\\
632 [[chull_has_center_on_wrong_side_of_hull_facet]] the hyperplane
633 supporting a facet has the wrong orientation.\\
634 [[chull_has_local_non_convexity]] a ridge is locally non convex.\\
635 [[chull_has_double_coverage]] the hull has a winding number larger
636 than 1.
637 }*/
638
639 template <typename Forward_iterator>
initialize(Forward_iterator first,Forward_iterator last)640 void initialize(Forward_iterator first, Forward_iterator last)
641 /*{\Xop initializes the complex with the set |S = set [first,last)|.
642 The initialization uses the quickhull approach.}*/
643 { CGAL_assertion(current_dimension()==-1);
644 Vertex_handle z;
645 Forward_iterator it(first);
646 std::list< Point_d > OtherPoints;
647 typename std::list< Point_d >::iterator pit, pred;
648 while ( it != last ) {
649 Point_d x = *it++;
650 if ( current_dimension() == -1 ) {
651
652 Simplex_handle outer_simplex; // a pointer to the outer simplex
653 dcur = 0; // we jump from dimension - 1 to dimension 0
654 origin_simplex_ = new_simplex(); num_of_bounded_simplices ++;
655 outer_simplex = new_simplex(); num_of_unbounded_simplices ++;
656 start_facet_ = origin_simplex_;
657 z = new_vertex(x); num_of_vertices ++;
658 associate_vertex_with_simplex(origin_simplex_,0,z);
659 // z is the only point and the peak
660 associate_vertex_with_simplex(outer_simplex,0,anti_origin_);
661 set_neighbor(origin_simplex_,0,outer_simplex,0);
662 typename R::Point_to_vector_d to_vector =
663 kernel().point_to_vector_d_object();
664 quasi_center_ = to_vector(x);
665
666
667 }
668 else if ( is_dimension_jump(x) ) {
669 dcur++;
670 z = new_vertex(x); num_of_vertices++;
671 typename R::Point_to_vector_d to_vector =
672 kernel().point_to_vector_d_object();
673 quasi_center_ = quasi_center_ + to_vector(x);
674 dimension_jump(origin_simplex_, z);
675 clear_visited_marks(origin_simplex_);
676 Simplex_iterator S;
677 forall_rc_simplices(S,*this) compute_equation_of_base_facet(S);
678 num_of_unbounded_simplices += num_of_bounded_simplices;
679 if (dcur > 1) {
680 start_facet_ = opposite_simplex(origin_simplex_,dcur);
681 CGAL_assertion(vertex_of_simplex(start_facet_,0)==Vertex_handle());
682 }
683
684
685 } else {
686 OtherPoints.push_back(x);
687 }
688 }
689 all_pnts_.insert(all_pnts_.end(),first,last);
690
691 // what is the point of this line? ...
692 //int dcur = current_dimension();
693 Unique_hash_map<Facet_handle, std::list<Point_d> > PointsOf;
694 std::list<Facet_handle> FacetCandidates;
695 typename R::Oriented_side_d side_of =
696 kernel().oriented_side_d_object();
697 for (int i=0; i<=dcur; ++i) {
698 Simplex_handle f = opposite_simplex(origin_simplex_,i);
699 Hyperplane_d h = f->hyperplane_of_base_facet();
700 std::list<Point_d>& L = PointsOf[f];
701 pit = OtherPoints.begin();
702 while ( pit != OtherPoints.end() ) {
703 if ( side_of(h,*pit) == ON_POSITIVE_SIDE ) {
704 L.push_back(*pit); pred=pit; ++pit; OtherPoints.erase(pred);
705 } else ++pit; // not above h
706 }
707 if ( !L.empty() ) FacetCandidates.push_back(f);
708 }
709 OtherPoints.clear();
710
711 while ( !FacetCandidates.empty() ) {
712 Facet_handle f = *FacetCandidates.begin();
713 FacetCandidates.pop_front();
714 Hyperplane_d h = f->hyperplane_of_base_facet();
715 std::list<Point_d>& L = PointsOf[f];
716 if (L.empty()) { CGAL_assertion( is_bounded_simplex(f) ); continue; }
717 Point_d p = *L.begin();
718 typename R::Value_at_d value_at = kernel().value_at_d_object();
719 RT maxdist = value_at(h,p), dist;
720 for (pit = ++L.begin(); pit != L.end(); ++pit) {
721 dist = value_at(h,*pit);
722 if ( dist > maxdist ) { maxdist = dist; p = *pit; }
723 }
724 num_of_visibility_tests += L.size();
725
726 std::size_t num_of_visited_facets = 0;
727 std::list<Facet_handle> VisibleFacets;
728 VisibleFacets.push_back(f);
729 visible_facets_search(f, p, VisibleFacets, num_of_visited_facets);
730 num_of_visibility_tests += num_of_visited_facets;
731 num_of_bounded_simplices += VisibleFacets.size();
732 clear_visited_marks(f);
733
734 ++num_of_vertices;
735 Vertex_handle z = new_vertex(p);
736 std::list<Simplex_handle> NewSimplices;
737 typename std::list<Facet_handle>::iterator it;
738 CGAL_assertion(OtherPoints.empty());
739 for (it = VisibleFacets.begin(); it != VisibleFacets.end(); ++it) {
740 OtherPoints.splice(OtherPoints.end(),PointsOf[*it]);
741 Facet_handle S = *it;
742 associate_vertex_with_simplex(S,0,z);
743 for (int k = 1; k <= dcur; ++k) {
744 if (!is_base_facet_visible(opposite_simplex(S,k),p)) {
745 Simplex_handle T = new_simplex();
746 NewSimplices.push_back(T);
747
748 /* set the vertices of T as described above */
749 for (int i = 1; i < dcur; i++) {
750 if ( i != k )
751 associate_vertex_with_simplex(T,i,vertex_of_simplex(S,i));
752 }
753 if (k != dcur)
754 associate_vertex_with_simplex(T,k,vertex_of_simplex(S,dcur));
755 associate_vertex_with_simplex(T,dcur,z);
756 associate_vertex_with_simplex(T,0,anti_origin_);
757 /* in the above, it is tempting to drop the tests ( i != k ) and
758 ( k != dcur ) since the subsequent lines after will correct the
759 erroneous assignment. This reasoning is fallacious as the
760 procedure assoc_vertex_with_simplex also the internal data of
761 the third argument. */
762
763 /* compute the equation of its base facet */
764 compute_equation_of_base_facet(T);
765
766 /* record adjacency information for the two known neighbors */
767 set_neighbor(T,dcur,opposite_simplex(S,k),
768 index_of_vertex_in_opposite_simplex(S,k));
769 set_neighbor(T,0,S,k);
770
771
772 }
773 }
774 }
775 num_of_unbounded_simplices -= VisibleFacets.size();
776 if ( vertex_of_simplex(start_facet_,0) != Vertex_handle() )
777 start_facet_ = *(--NewSimplices.end());
778 CGAL_assertion( vertex_of_simplex(start_facet_,0)==Vertex_handle() );
779 for (it = NewSimplices.begin(); it != NewSimplices.end(); ++it) {
780 Simplex_handle Af = *it;
781 for (int k = 1; k < dcur ; k++) {
782 // neighbors 0 and dcur are already known
783 if (opposite_simplex(Af,k) == Simplex_handle()) {
784 // we have not performed the walk in the opposite direction yet
785 Simplex_handle T = opposite_simplex(Af,0);
786 int y1 = 0;
787 while ( vertex_of_simplex(T,y1) != vertex_of_simplex(Af,k) )
788 y1++;
789 // exercise: show that we can also start with y1 = 1
790 int y2 = index_of_vertex_in_opposite_simplex(Af,0);
791
792 while ( vertex_of_simplex(T,0) == z ) {
793 // while T has peak x do find new y_1 */
794 int new_y1 = 0;
795 while (vertex_of_simplex(opposite_simplex(T,y1),new_y1) !=
796 vertex_of_simplex(T,y2))
797 new_y1++;
798 // exercise: show that we can also start with new_y1 = 1
799 y2 = index_of_vertex_in_opposite_simplex(T,y1);
800 T = opposite_simplex(T,y1);
801 y1 = new_y1;
802 }
803 set_neighbor(Af,k,T,y1); // update adjacency information
804 }
805 }
806 }
807
808
809
810 for (it = NewSimplices.begin(); it != NewSimplices.end(); ++it) {
811 Facet_handle f = *it;
812 CGAL_assertion( is_unbounded_simplex(f) );
813 Hyperplane_d h = f->hyperplane_of_base_facet();
814 std::list<Point_d>& L = PointsOf[f];
815 pit = OtherPoints.begin();
816 while ( pit != OtherPoints.end() ) {
817 if ( side_of(h,*pit) == ON_POSITIVE_SIDE ) {
818 L.push_back(*pit); pred=pit; ++pit; OtherPoints.erase(pred);
819 } else ++pit; // not above h
820 }
821 if ( !L.empty() ) FacetCandidates.push_back(f);
822 }
823 OtherPoints.clear();
824
825 }
826
827 #ifdef CGAL_CHECK_EXPENSIVE
828 CGAL_assertion(is_valid(true));
829 #endif
830 }
831
832
833 /*{\Mtext \headerline{Lists and Iterators}
834 \setopdims{3.5cm}{3.5cm}}*/
835
vertices_begin()836 Vertex_iterator vertices_begin() { return Base::vertices_begin(); }
837 /*{\Mop returns an iterator to start iteration over all vertices
838 of |\Mvar|.}*/
vertices_end()839 Vertex_iterator vertices_end() { return Base::vertices_end(); }
840 /*{\Mop the past the end iterator for vertices.}*/
simplices_begin()841 Simplex_iterator simplices_begin() { return Base::simplices_begin(); }
842 /*{\Mop returns an iterator to start iteration over all simplices
843 of |\Mvar|.}*/
simplices_end()844 Simplex_iterator simplices_end() { return Base::simplices_end(); }
845 /*{\Mop the past the end iterator for simplices.}*/
facets_begin()846 Facet_iterator facets_begin() { return Facet_iterator(this,start_facet_); }
847 /*{\Mop returns an iterator to start iteration over all facets of |\Mvar|.}*/
facets_end()848 Facet_iterator facets_end() { return Facet_iterator(); }
849 /*{\Mop the past the end iterator for facets.}*/
hull_vertices_begin()850 Hull_vertex_iterator hull_vertices_begin()
851 { return Hull_vertex_iterator(this,facets_begin()); }
852 /*{\Mop returns an iterator to start iteration over all hull vertex
853 of |\Mvar|. Remember that the hull is a simplicial complex.}*/
hull_vertices_end()854 Hull_vertex_iterator hull_vertices_end()
855 { return Hull_vertex_iterator(); }
856 /*{\Mop the past the end iterator for hull vertices.}*/
857
points_begin()858 Point_const_iterator points_begin() const { return all_pnts_.begin(); }
859 /*{\Mop returns the start iterator for all points that have been
860 inserted to construct |\Mvar|.}*/
points_end()861 Point_const_iterator points_end() const { return all_pnts_.end(); }
862 /*{\Mop returns the past the end iterator for all points.}*/
863
hull_points_begin()864 Hull_point_const_iterator hull_points_begin() const
865 { return Hull_point_const_iterator(hull_vertices_begin()); }
866 /*{\Mop returns an iterator to start iteration over all inserted
867 points that are part of the convex hull |\Mvar|. Remember that the
868 hull is a simplicial complex.}*/
hull_points_end()869 Hull_point_const_iterator hull_points_end() const
870 { return Hull_point_const_iterator(hull_vertices_end()); }
871 /*{\Mop returns the past the end iterator for points of the hull.}*/
872
vertices_begin()873 Vertex_const_iterator vertices_begin() const
874 { return Base::vertices_begin(); }
vertices_end()875 Vertex_const_iterator vertices_end() const
876 { return Base::vertices_end(); }
simplices_begin()877 Simplex_const_iterator simplices_begin() const
878 { return Base::simplices_begin(); }
simplices_end()879 Simplex_const_iterator simplices_end() const
880 { return Base::simplices_end(); }
facets_begin()881 Facet_const_iterator facets_begin() const
882 { return Facet_const_iterator(this,start_facet_); }
facets_end()883 Facet_const_iterator facets_end() const
884 { return Facet_const_iterator(); }
hull_vertices_begin()885 Hull_vertex_const_iterator hull_vertices_begin() const
886 { return Hull_vertex_const_iterator(this,facets_begin()); }
hull_vertices_end()887 Hull_vertex_const_iterator hull_vertices_end() const
888 { return Hull_vertex_const_iterator(); }
889
890 /* We distinguish cases according to the current dimension. If the
891 dimension is less than one then the hull has no facets, if the
892 dimension is one then the hull has two facets which we extract by a
893 scan through the set of all simplices, and if the hull has
894 dimension at least two the boundary is a connected set and we
895 construct the list of facets by depth first search starting at
896 |start_facet_|.*/
897
898 /*{\Mtext\setopdims{5.5cm}{3.5cm}}*/
899 template <typename Visitor>
visit_all_facets(const Visitor & V)900 void visit_all_facets(const Visitor& V) const
901 /*{\Mop each facet of |\Mvar| is visited by the visitor object |V|.
902 |V| has to have a function call operator:\\
903 |void operator()(Facet_handle) const|}*/
904 {
905 if (current_dimension() > 1) {
906 Unique_hash_map<Facet_handle,bool> visited(false);
907 std::list<Facet_handle> candidates;
908 candidates.push_back(start_facet_);
909 visited[start_facet_] = true;
910 Facet_handle current;
911 while ( !candidates.empty() ) {
912 current = *(candidates.begin()); candidates.pop_front();
913 CGAL_assertion(vertex_of_simplex(current,0)==Vertex_handle());
914 V(current);
915 for(int i = 1; i <= dcur; ++i) {
916 Facet_handle f = opposite_simplex(current,i);
917 if ( !visited[f] ) {
918 candidates.push_back(f);
919 visited[f] = true;
920 }
921 }
922 }
923 }
924 else if ( current_dimension() == 1 ) { V(start_facet_); }
925 }
926
all_points()927 const std::list<Point_d>& all_points() const
928 /*{\Mop returns a list of all points in |\Mvar|.}*/
929 { return all_pnts_; }
930
all_vertices()931 std::list<Vertex_handle> all_vertices()
932 /*{\Mop returns a list of all vertices of |\Mvar|
933 (also interior ones).}*/
934 { return Base::all_vertices(); }
all_vertices()935 std::list<Vertex_const_handle> all_vertices() const
936 { return Base::all_vertices(); }
937
all_simplices()938 std::list<Simplex_handle> all_simplices()
939 /*{\Mop returns a list of all simplices in |\Mvar|.}*/
940 { return Base::all_simplices(); }
all_simplices()941 std::list<Simplex_const_handle> all_simplices() const
942 { return Base::all_simplices(); }
943
944
945
all_facets()946 std::list<Facet_handle> all_facets()
947 /*{\Mop returns a list of all facets of |\Mvar|.}*/
948 { std::list<Facet_handle> L;
949 list_collector<Facet_handle,Facet_handle> visitor(L);
950 visit_all_facets(visitor);
951 return L;
952 }
953
all_facets()954 std::list<Facet_const_handle> all_facets() const
955 { std::list<Facet_const_handle> L;
956 list_collector<Facet_const_handle,Facet_handle> visitor(L);
957 visit_all_facets(visitor);
958 return L;
959 }
960
961 #define forall_ch_vertices(x,CH)\
962 for(x = (CH).vertices_begin(); x != (CH).vertices_end(); ++x)
963 #define forall_ch_simplices(x,CH)\
964 for(x = (CH).simplices_begin(); x != (CH).simplices_end(); ++x)
965 #define forall_ch_facets(x,CH)\
966 for(x = (CH).facets_begin(); x != (CH).facets_end(); ++x)
967
968 /*{\Mtext
969 \headerline{Iteration Statements}
970
971 {\bf forall\_ch\_vertices}($v,C$)
972 $\{$ ``the vertices of $C$ are successively assigned to $v$'' $\}$
973
974 {\bf forall\_ch\_simplices}($s,C$)
975 $\{$ ``the simplices of $C$ are successively assigned to $s$'' $\}$
976
977 {\bf forall\_ch\_facets}($f,C$)
978 $\{$ ``the facets of $C$ are successively assigned to $f$'' $\}$
979
980 }*/
981
982
983 /*{\Mimplementation The implementation of type |\Mtype| is based on
984 \cgalCite{cms:fourresults} and \cgalCite{BMS:degeneracy}. The details of the
985 implementation can be found in the implementation document available
986 at the download site of this package.
987
988 The time and space requirements are input dependent. Let $C_1$, $C_2$,
989 $C_3$, \ldots be the sequence of hulls constructed and for a point $x$
990 let $k_i$ be the number of facets of $C_i$ that are visible from $x$
991 and that are not already facets of $C_{i-1}$. Then the time for
992 inserting $x$ is $O(|dim| \sum_i k_i)$ and the number of new simplices
993 constructed during the insertion of $x$ is the number of facets of the
994 hull which were not already facets of the hull before the insertion.
995
996 The data type |\Mtype| is derived from |Regular_complex_d|. The space
997 requirement of regular complexes is essentially $12(|dim| +2)$ bytes
998 times the number of simplices plus the space for the points. |\Mtype|
999 needs an additional $8 + (4 + x)|dim|$ bytes per simplex where $x$ is
1000 the space requirement of the underlying number type and an additional
1001 $12$ bytes per point. The total is therefore $(16 + x)|dim| + 32$
1002 bytes times the number of simplices plus $28 + x \cdot |dim|$ bytes
1003 times the number of points.}*/
1004
1005 /*{\Mtext\headerline{Traits requirements}
1006
1007 |\Mname| requires the following types from the kernel traits |R|:
1008 \begin{Mverb}
1009 Point_d Vector_d Ray_d Hyperplane_d
1010 \end{Mverb}
1011 and uses the following function objects from the kernel traits:
1012 \begin{Mverb}
1013 Construct_vector_d
1014 Construct_hyperplane_d
1015 Vector_to_point_d / Point_to_vector_d
1016 Orientation_d
1017 Orthogonal_vector_d
1018 Oriented_side_d / Has_on_positive_side_d
1019 Affinely_independent_d
1020 Contained_in_simplex_d
1021 Contained_in_affine_hull_d
1022 Intersect_d
1023 \end{Mverb}
1024 }*/
1025
1026 }; // Convex_hull_d<R>
1027
1028
1029
1030 template <class R>
Convex_hull_d(int d,const R & Kernel)1031 Convex_hull_d<R>::Convex_hull_d(int d, const R& Kernel) : Base(d,Kernel)
1032 {
1033 origin_simplex_ = Simplex_handle();
1034 start_facet_ = Facet_handle();
1035 anti_origin_ = Vertex_handle();
1036 num_of_vertices = 0;
1037 num_of_unbounded_simplices = num_of_bounded_simplices = 0;
1038 num_of_visibility_tests = 0;
1039 typename R::Construct_vector_d create =
1040 kernel().construct_vector_d_object();
1041 quasi_center_ = create(d,NULL_VECTOR);
1042 }
1043
1044 template <class R>
1045 bool Convex_hull_d<R>::
contains_in_base_facet(Simplex_handle s,const Point_d & x)1046 contains_in_base_facet(Simplex_handle s, const Point_d& x) const
1047 {
1048 typename R::Contained_in_simplex_d contained_in_simplex =
1049 kernel().contained_in_simplex_d_object();
1050 return contained_in_simplex(s->points_begin()+1,
1051 s->points_begin()+current_dimension()+1,x);
1052 }
1053
1054 template <class R>
1055 void Convex_hull_d<R>::
compute_equation_of_base_facet(Simplex_handle S)1056 compute_equation_of_base_facet(Simplex_handle S)
1057 {
1058 typename R::Construct_hyperplane_d hyperplane_through_points =
1059 kernel().construct_hyperplane_d_object();
1060 S->set_hyperplane_of_base_facet( hyperplane_through_points(
1061 S->points_begin()+1, S->points_begin()+1+current_dimension(),
1062 center(), ON_NEGATIVE_SIDE)); // skip the first point !
1063
1064 #ifdef CGAL_CHECK_EXPENSIVE
1065 { /* Let us check */
1066 typename R::Oriented_side_d side = kernel().oriented_side_d_object();
1067 for (int i = 1; i <= current_dimension(); i++)
1068 CGAL_assertion_msg(side(S->hyperplane_of_base_facet(),
1069 point_of_simplex(S,i)) == ON_ORIENTED_BOUNDARY,
1070 " hyperplane does not support base ");
1071 CGAL_assertion_msg(side(S->hyperplane_of_base_facet(),center()) ==
1072 ON_NEGATIVE_SIDE,
1073 " hyperplane has quasi center on wrong side ");
1074 }
1075 #endif
1076
1077
1078 }
1079
1080 template <class R>
1081 typename Convex_hull_d<R>::Vertex_handle
insert(const Point_d & x)1082 Convex_hull_d<R>::insert(const Point_d& x)
1083 {
1084 Vertex_handle z = Vertex_handle();
1085 all_pnts_.push_back(x);
1086 if (current_dimension() == -1) {
1087
1088 Simplex_handle outer_simplex; // a pointer to the outer simplex
1089 dcur = 0; // we jump from dimension - 1 to dimension 0
1090 origin_simplex_ = new_simplex(); num_of_bounded_simplices ++;
1091 outer_simplex = new_simplex(); num_of_unbounded_simplices ++;
1092 start_facet_ = origin_simplex_;
1093 z = new_vertex(x); num_of_vertices ++;
1094 associate_vertex_with_simplex(origin_simplex_,0,z);
1095 // z is the only point and the peak
1096 associate_vertex_with_simplex(outer_simplex,0,anti_origin_);
1097 set_neighbor(origin_simplex_,0,outer_simplex,0);
1098 typename R::Point_to_vector_d to_vector =
1099 kernel().point_to_vector_d_object();
1100 quasi_center_ = to_vector(x);
1101
1102
1103 } else if ( is_dimension_jump(x) ) {
1104 dcur++;
1105 z = new_vertex(x); num_of_vertices++;
1106 typename R::Point_to_vector_d to_vector =
1107 kernel().point_to_vector_d_object();
1108 quasi_center_ = quasi_center_ + to_vector(x);
1109 dimension_jump(origin_simplex_, z);
1110 clear_visited_marks(origin_simplex_);
1111 Simplex_iterator S;
1112 forall_rc_simplices(S,*this) compute_equation_of_base_facet(S);
1113 num_of_unbounded_simplices += num_of_bounded_simplices;
1114 if (dcur > 1) {
1115 start_facet_ = opposite_simplex(origin_simplex_,dcur);
1116 CGAL_assertion(vertex_of_simplex(start_facet_,0)==Vertex_handle());
1117 }
1118
1119
1120 } else {
1121 if ( current_dimension() == 0 ) {
1122 z = vertex_of_simplex(origin_simplex_,0);
1123 associate_point_with_vertex(z,x);
1124 return z;
1125 }
1126 std::list<Simplex_handle> visible_simplices;
1127 int location = -1;
1128 Facet_handle f;
1129
1130 std::size_t num_of_visited_simplices = 0;
1131
1132 visibility_search(origin_simplex_, x, visible_simplices,
1133 num_of_visited_simplices, location, f);
1134
1135 num_of_visibility_tests += num_of_visited_simplices;
1136
1137 #ifdef COUNTS
1138 cout << "\nthe number of visited simplices in this iteration is ";
1139 cout << num_of_visited_simplices << endl;
1140 #endif
1141
1142 clear_visited_marks(origin_simplex_);
1143
1144
1145 #ifdef COUNTS
1146 cout << "\nthe number of bounded simplices constructed ";
1147 cout << " in this iteration is " << visible_simplices.size() << endl;
1148 #endif
1149
1150 num_of_bounded_simplices += visible_simplices.size();
1151
1152 switch (location) {
1153 case -1:
1154 return Vertex_handle();
1155 case 0:
1156 { for (int i = 0; i < current_dimension(); i++) {
1157 if ( x == point_of_facet(f,i) ) {
1158 z = vertex_of_facet(f,i);
1159 associate_point_with_vertex(z,x);
1160 return z;
1161 }
1162 }
1163 return Vertex_handle();
1164 }
1165 case 1:
1166 { num_of_vertices++;
1167 z = new_vertex(x);
1168 std::list<Simplex_handle> NewSimplices; // list of new simplices
1169 typename std::list<Simplex_handle>::iterator it;
1170
1171 for (it = visible_simplices.begin();
1172 it != visible_simplices.end(); ++it) {
1173 Simplex_handle S = *it;
1174 associate_vertex_with_simplex(S,0,z);
1175 for (int k = 1; k <= dcur; k++) {
1176 if (!is_base_facet_visible(opposite_simplex(S,k),x)) {
1177 Simplex_handle T = new_simplex();
1178 NewSimplices.push_back(T);
1179
1180 /* set the vertices of T as described above */
1181 for (int i = 1; i < dcur; i++) {
1182 if ( i != k )
1183 associate_vertex_with_simplex(T,i,vertex_of_simplex(S,i));
1184 }
1185 if (k != dcur)
1186 associate_vertex_with_simplex(T,k,vertex_of_simplex(S,dcur));
1187 associate_vertex_with_simplex(T,dcur,z);
1188 associate_vertex_with_simplex(T,0,anti_origin_);
1189 /* in the above, it is tempting to drop the tests ( i != k )
1190 and ( k != dcur ) since the subsequent lines after will
1191 correct the erroneous assignment. This reasoning is
1192 fallacious as the procedure assoc_vertex_with_simplex also
1193 the internal data of the third argument. */
1194
1195 /* compute the equation of its base facet */
1196 compute_equation_of_base_facet(T);
1197
1198 /* record adjacency information for the two known neighbors */
1199 set_neighbor(T,dcur,opposite_simplex(S,k),
1200 index_of_vertex_in_opposite_simplex(S,k));
1201 set_neighbor(T,0,S,k);
1202
1203
1204 }
1205 }
1206 }
1207 num_of_unbounded_simplices -= visible_simplices.size();
1208 if ( vertex_of_simplex(start_facet_,0) != Vertex_handle() )
1209 start_facet_ = *(--NewSimplices.end());
1210 CGAL_assertion( vertex_of_simplex(start_facet_,0)==Vertex_handle() );
1211 for (it = NewSimplices.begin(); it != NewSimplices.end(); ++it) {
1212 Simplex_handle Af = *it;
1213 for (int k = 1; k < dcur ; k++) {
1214 // neighbors 0 and dcur are already known
1215 if (opposite_simplex(Af,k) == Simplex_handle()) {
1216 // we have not performed the walk in the opposite direction yet
1217 Simplex_handle T = opposite_simplex(Af,0);
1218 int y1 = 0;
1219 while ( vertex_of_simplex(T,y1) != vertex_of_simplex(Af,k) )
1220 y1++;
1221 // exercise: show that we can also start with y1 = 1
1222 int y2 = index_of_vertex_in_opposite_simplex(Af,0);
1223
1224 while ( vertex_of_simplex(T,0) == z ) {
1225 // while T has peak x do find new y_1 */
1226 int new_y1 = 0;
1227 while (vertex_of_simplex(opposite_simplex(T,y1),new_y1) !=
1228 vertex_of_simplex(T,y2))
1229 new_y1++;
1230 // exercise: show that we can also start with new_y1 = 1
1231 y2 = index_of_vertex_in_opposite_simplex(T,y1);
1232 T = opposite_simplex(T,y1);
1233 y1 = new_y1;
1234 }
1235 set_neighbor(Af,k,T,y1); // update adjacency information
1236 }
1237 }
1238 }
1239
1240
1241 }
1242 }
1243
1244 }
1245 #ifdef CGAL_CHECK_EXPENSIVE
1246 CGAL_assertion(is_valid(true));
1247 #endif
1248 return z;
1249 }
1250
1251
1252 template <class R>
1253 void Convex_hull_d<R>::
visibility_search(Simplex_handle S,const Point_d & x,std::list<Simplex_handle> & visible_simplices,std::size_t & num_of_visited_simplices,int & location,Simplex_handle & f)1254 visibility_search(Simplex_handle S, const Point_d& x,
1255 std::list< Simplex_handle >& visible_simplices,
1256 std::size_t& num_of_visited_simplices, int& location,
1257 Simplex_handle& f) const
1258 {
1259 num_of_visited_simplices ++;
1260 S->visited() = true; // we have visited S and never come back ...
1261 for(int i = 0; i <= current_dimension(); ++i) {
1262 Simplex_handle T = opposite_simplex(S,i); // for all neighbors T of S
1263 if ( !T->visited() ) {
1264 typename R::Oriented_side_d side_of =
1265 kernel().oriented_side_d_object();
1266 int side = side_of(T->hyperplane_of_base_facet(),x);
1267 if ( is_unbounded_simplex(T) ) {
1268 if ( side == ON_POSITIVE_SIDE ) {
1269 // T is an unbounded simplex with x-visible base facet
1270 visible_simplices.push_back(T);
1271 location = 1;
1272 }
1273 if ( side == ON_ORIENTED_BOUNDARY &&
1274 location == -1 && contains_in_base_facet(T,x) ) {
1275 location = 0; f = T;
1276 return;
1277 }
1278 }
1279 if ( side == ON_POSITIVE_SIDE ||
1280 (side == ON_ORIENTED_BOUNDARY && location == -1) ) {
1281 visibility_search(T,x,visible_simplices,
1282 num_of_visited_simplices,location,f);
1283 // do the recursive search
1284 }
1285 } // end visited
1286 else {
1287 }
1288 } // end for
1289 }
1290
1291 template <class R>
clear_visited_marks(Simplex_handle S)1292 void Convex_hull_d<R>::clear_visited_marks(Simplex_handle S) const
1293 {
1294 S->visited() = false; // clear the visit - bit
1295 for(int i = 0; i <= current_dimension(); i++) // for all neighbors of S
1296 if (opposite_simplex(S,i)->visited())
1297 // if the i - th neighbor has been visited
1298 clear_visited_marks(opposite_simplex(S,i));
1299 // clear its bit recursively
1300 }
1301
1302 template <class R>
1303 std::list< typename Convex_hull_d<R>::Simplex_handle >
facets_visible_from(const Point_d & x)1304 Convex_hull_d<R>::facets_visible_from(const Point_d& x)
1305 {
1306 std::list<Simplex_handle> visible_simplices;
1307 int location = -1; // intialization is important
1308 std::size_t num_of_visited_simplices = 0; // irrelevant
1309 Facet_handle f; // irrelevant
1310
1311 visibility_search(origin_simplex_, x, visible_simplices,
1312 num_of_visited_simplices, location, f);
1313 clear_visited_marks(origin_simplex_);
1314 return visible_simplices;
1315 }
1316
1317 template <class R>
bounded_side(const Point_d & x)1318 Bounded_side Convex_hull_d<R>::bounded_side(const Point_d& x)
1319 {
1320 if ( is_dimension_jump(x) ) return ON_UNBOUNDED_SIDE;
1321 std::list<Simplex_handle> visible_simplices;
1322 int location = -1; // intialization is important
1323 std::size_t num_of_visited_simplices = 0; // irrelevant
1324 Facet_handle f;
1325
1326 visibility_search(origin_simplex_, x, visible_simplices,
1327 num_of_visited_simplices, location, f);
1328 clear_visited_marks(origin_simplex_);
1329 switch (location) {
1330 case -1: return ON_BOUNDED_SIDE;
1331 case 0: return ON_BOUNDARY;
1332 case 1: return ON_UNBOUNDED_SIDE;
1333 }
1334 CGAL_error(); return ON_BOUNDARY; // never come here
1335 }
1336
1337
1338 template <class R>
1339 void Convex_hull_d<R>::
dimension_jump(Simplex_handle S,Vertex_handle x)1340 dimension_jump(Simplex_handle S, Vertex_handle x)
1341 {
1342 Simplex_handle S_new;
1343 S->visited() = true;
1344 associate_vertex_with_simplex(S,dcur,x);
1345 if ( !is_unbounded_simplex(S) ) { // S is bounded
1346 S_new = new_simplex();
1347 set_neighbor(S,dcur,S_new,0);
1348 associate_vertex_with_simplex(S_new,0,anti_origin_);
1349 for (int k = 1; k <= dcur; k++) {
1350 associate_vertex_with_simplex(S_new,k,vertex_of_simplex(S,k-1));
1351 }
1352
1353 }
1354 /* visit unvisited neighbors 0 to dcur - 1 */
1355 for (int k = 0; k <= dcur - 1; k++) {
1356 if ( !opposite_simplex(S,k) -> visited() ) {
1357 dimension_jump(opposite_simplex(S,k), x);
1358 }
1359 }
1360 /* the recursive calls ensure that all neighbors exist */
1361 if ( is_unbounded_simplex(S) ) {
1362 set_neighbor(S,dcur,opposite_simplex(opposite_simplex(S,0),dcur),
1363 index_of_vertex_in_opposite_simplex(S,0) + 1);
1364
1365 } else {
1366 for (int k = 0; k < dcur; k++) {
1367 if ( is_unbounded_simplex(opposite_simplex(S,k)) ) {
1368 // if F' is unbounded
1369 set_neighbor(S_new,k + 1,opposite_simplex(S,k),dcur);
1370 // the neighbor of S_new opposite to v is S' and
1371 // x is in position dcur
1372 } else { // F' is bounded
1373 set_neighbor(S_new,k + 1,opposite_simplex(opposite_simplex(S,k),dcur),
1374 index_of_vertex_in_opposite_simplex(S,k) + 1);
1375 // neighbor of S_new opposite to v is S_new'
1376 // the vertex opposite to v remains the same but ...
1377 // remember the shifting of the vertices one step to the right
1378 }
1379 }
1380
1381 }
1382 }
1383
1384 template <class R>
is_valid(bool throw_exceptions)1385 bool Convex_hull_d<R>::is_valid(bool throw_exceptions) const
1386 {
1387 this->check_topology();
1388 if (current_dimension() < 1) return true;
1389
1390 /* Recall that center() gives us the center-point of the origin
1391 simplex. We check whether it is locally inside with respect to
1392 all hull facets. */
1393
1394 typename R::Oriented_side_d side =
1395 kernel().oriented_side_d_object();
1396 Point_d centerpoint = center();
1397 Simplex_const_iterator S;
1398 forall_rc_simplices(S,*this) {
1399 if ( is_unbounded_simplex(S) &&
1400 side(S->hyperplane_of_base_facet(),centerpoint) !=
1401 ON_NEGATIVE_SIDE) {
1402 if (throw_exceptions)
1403 throw chull_has_center_on_wrong_side_of_hull_facet();
1404 return false;
1405 }
1406 }
1407 /* next we check convexity at every ridge. Let |S| be any hull
1408 simplex and let |v| be any vertex of its base facet. The vertex
1409 opposite to |v| must not be on the positive side of the base
1410 facet.*/
1411
1412 forall_rc_simplices(S,*this) {
1413 if ( is_unbounded_simplex(S) ) {
1414 for (int i = 1; i <= dcur; i++) {
1415 int k = index_of_vertex_in_opposite_simplex(S,i);
1416 if (side(S->hyperplane_of_base_facet(),
1417 point_of_simplex(opposite_simplex(S,i),k)) ==
1418 ON_POSITIVE_SIDE) {
1419 if (throw_exceptions)
1420 throw chull_has_local_non_convexity();
1421 return false;
1422 }
1423 }
1424 }
1425 }
1426
1427 /* next we select one hull facet */
1428
1429 Simplex_const_handle selected_hull_simplex;
1430 forall_rc_simplices(S,*this) {
1431 if ( is_unbounded_simplex(S) ) { selected_hull_simplex = S; break; }
1432 }
1433
1434 /* we compute the center of gravity of the base facet of the
1435 hull simplex */
1436
1437 typename R::Point_to_vector_d to_vector =
1438 kernel().point_to_vector_d_object();
1439 typename R::Vector_to_point_d to_point =
1440 kernel().vector_to_point_d_object();
1441 typename R::Construct_vector_d create =
1442 kernel().construct_vector_d_object();
1443 Vector_d center_of_hull_facet = create(dimension(),NULL_VECTOR);
1444 for (int i = 1; i <= current_dimension(); i++) {
1445 center_of_hull_facet = center_of_hull_facet +
1446 to_vector(point_of_simplex(selected_hull_simplex,i));
1447 }
1448 Point_d center_of_hull_facet_point =
1449 to_point(center_of_hull_facet/RT(dcur));
1450
1451 /* we set up the ray from the center to the center of the hull facet */
1452
1453 Ray_d l(centerpoint, center_of_hull_facet_point);
1454
1455 /* and check whether it intersects the interior of any hull facet */
1456
1457 typename R::Contained_in_simplex_d contained_in_simplex =
1458 kernel().contained_in_simplex_d_object();
1459 typename R::Intersect_d intersect =
1460 kernel().intersect_d_object();
1461
1462 forall_rc_simplices(S,*this) {
1463 if ( is_unbounded_simplex(S) && S != selected_hull_simplex ) {
1464 Point_d p; Object op;
1465 Hyperplane_d h = S->hyperplane_of_base_facet();
1466 if ( (op = intersect(l,h), assign(p,op)) ) {
1467 if ( contained_in_simplex(S->points_begin()+1,
1468 S->points_begin()+1+current_dimension(),p) ) {
1469 if ( throw_exceptions )
1470 throw chull_has_double_coverage();
1471 return false;
1472 }
1473 }
1474 }
1475 }
1476 return true;
1477 }
1478
1479 template <class R>
1480 void Convex_hull_d<R>::
visible_facets_search(Simplex_handle S,const Point_d & x,std::list<Facet_handle> & VisibleFacets,std::size_t & num_of_visited_facets)1481 visible_facets_search(Simplex_handle S, const Point_d& x,
1482 std::list< Facet_handle >& VisibleFacets,
1483 std::size_t& num_of_visited_facets) const
1484 {
1485 ++num_of_visited_facets;
1486 S->visited() = true; // we have visited S and never come back ...
1487 for(int i = 1; i <= current_dimension(); ++i) {
1488 Simplex_handle T = opposite_simplex(S,i); // for all neighbors T of S
1489 if ( !T->visited() ) {
1490 typename R::Oriented_side_d side_of =
1491 kernel().oriented_side_d_object();
1492 int side = side_of(T->hyperplane_of_base_facet(),x);
1493 CGAL_assertion( is_unbounded_simplex(T) );
1494 if ( side == ON_POSITIVE_SIDE ) {
1495 VisibleFacets.push_back(T);
1496 visible_facets_search(T,x,VisibleFacets,num_of_visited_facets);
1497 // do the recursive search
1498 }
1499 } // end visited
1500 } // end for
1501 }
1502
1503
1504
1505
1506 } //namespace CGAL
1507 #endif // CGAL_CONVEX_HULL_D_H
1508