1 // Copyright (c) 1999-2004,2006-2009, 2017  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/Periodic_3_triangulation_3/include/CGAL/Periodic_3_Delaunay_triangulation_3.h $
7 // $Id: Periodic_3_Delaunay_triangulation_3.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s)     : Monique Teillaud <Monique.Teillaud@sophia.inria.fr>
11 //                 Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
12 //                 Andreas Fabri <Andreas.Fabri@sophia.inria.fr>
13 //                 Nico Kruithof <Nico.Kruithof@sophia.inria.fr>
14 //                 Manuel Caroli <Manuel.Caroli@sophia.inria.fr>
15 
16 #ifndef CGAL_PERIODIC_3_DELAUNAY_TRIANGULATION_3_H
17 #define CGAL_PERIODIC_3_DELAUNAY_TRIANGULATION_3_H
18 
19 #include <CGAL/license/Periodic_3_triangulation_3.h>
20 
21 #include <CGAL/Periodic_3_triangulation_3.h>
22 #include <CGAL/spatial_sort.h>
23 
24 // Needed by remove to fill the hole.
25 #include <CGAL/internal/Periodic_3_Delaunay_triangulation_remove_traits_3.h>
26 #include <CGAL/Delaunay_triangulation_3.h>
27 
28 #include <iostream>
29 #include <vector>
30 #include <utility>
31 
32 namespace CGAL {
33 
34 template < class GT, class TDS > class Periodic_3_Delaunay_triangulation_3;
35 template < class GT, class TDS > std::istream& operator>>
36     (std::istream& is, Periodic_3_Delaunay_triangulation_3<GT,TDS> &tr);
37 
38 template < class Gt,
39            class Tds = Triangulation_data_structure_3 <
40                          Triangulation_vertex_base_3<
41                            Gt, Periodic_3_triangulation_ds_vertex_base_3<>
42                          >,
43                          Triangulation_cell_base_3<
44                            Gt, Periodic_3_triangulation_ds_cell_base_3<>
45                          >
46                        >
47          >
48 class Periodic_3_Delaunay_triangulation_3 :
49   public Periodic_3_triangulation_3<Gt, Tds>
50 {
51   friend std::istream& operator>> <>
52   (std::istream& is, Periodic_3_Delaunay_triangulation_3<Gt, Tds> &tr);
53 
54   typedef Periodic_3_Delaunay_triangulation_3<Gt,Tds>          Self;
55 public:
56   typedef Periodic_3_triangulation_3<Gt,Tds>                   Base;
57 
58 public:
59   /** @name Template parameter types */
60   typedef Gt                                    Geometric_traits;
61   typedef Tds                                   Triangulation_data_structure;
62 
63 
64   ///Compatibility typedef:
65   typedef Geometric_traits                      Geom_traits;
66   typedef typename Gt::FT                       FT;
67 
68   typedef typename Gt::Point_3                  Point;
69   typedef typename Gt::Segment_3                Segment;
70   typedef typename Gt::Triangle_3               Triangle;
71   typedef typename Gt::Tetrahedron_3            Tetrahedron;
72 
73   typedef typename Base::Periodic_point         Periodic_point;
74   typedef typename Base::Periodic_segment       Periodic_segment;
75   typedef typename Base::Periodic_triangle      Periodic_triangle;
76   typedef typename Base::Periodic_tetrahedron   Periodic_tetrahedron;
77 
78   typedef typename Base::Cell_handle            Cell_handle;
79   typedef typename Base::Vertex_handle          Vertex_handle;
80 
81   typedef typename Base::Cell                   Cell;
82   typedef typename Base::Vertex                 Vertex;
83   typedef typename Base::Facet                  Facet;
84   typedef typename Base::Edge                   Edge;
85 
86   typedef typename Base::Cell_circulator        Cell_circulator;
87   typedef typename Base::Facet_circulator       Facet_circulator;
88   typedef typename Base::Cell_iterator          Cell_iterator;
89   typedef typename Base::Facet_iterator         Facet_iterator;
90   typedef typename Base::Edge_iterator          Edge_iterator;
91   typedef typename Base::Vertex_iterator        Vertex_iterator;
92 
93   typedef typename Base::All_cells_iterator     All_cells_iterator;
94   typedef typename Base::All_facets_iterator    All_facets_iterator;
95   typedef typename Base::All_edges_iterator     All_edges_iterator;
96   typedef typename Base::All_vertices_iterator  All_vertices_iterator;
97 
98   typedef typename Base::size_type              size_type;
99   typedef typename Base::difference_type        difference_type;
100 
101   typedef typename Base::Locate_type            Locate_type;
102   typedef typename Base::Iterator_type          Iterator_type;
103 
104   typedef typename Base::Offset                 Offset;
105   typedef typename Base::Iso_cuboid             Iso_cuboid;
106   typedef typename Base::Covering_sheets        Covering_sheets;
107   typedef typename Base::Periodic_segment_iterator  Periodic_segment_iterator;
108   typedef typename Base::Periodic_tetrahedron_iterator  Periodic_tetrahedron_iterator;
109 
110   //Tag to distinguish Delaunay from Regular triangulations
111   typedef Tag_false                             Weighted_tag;
112 
113   // Tag to distinguish periodic triangulations from others
114   typedef Tag_true                              Periodic_tag;
115 
116 #ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
117   using Base::cw;
118   using Base::ccw;
119   using Base::domain;
120   using Base::geom_traits;
121   using Base::insert_dummy_points;
122   using Base::int_to_off;
123   using Base::is_1_cover;
124   using Base::is_virtual;
125   using Base::number_of_sheets;
126   using Base::number_of_vertices;
127   using Base::number_of_edges;
128   using Base::number_of_facets;
129   using Base::number_of_cells;
130   using Base::next_around_edge;
131   using Base::vertex_triple_index;
132   using Base::mirror_vertex;
133   using Base::orientation;
134   using Base::point;
135   using Base::swap;
136   using Base::tds;
137   using Base::vertices_begin;
138   using Base::vertices_end;
139   using Base::edges_begin;
140   using Base::edges_end;
141   using Base::facets_begin;
142   using Base::facets_end;
143   using Base::cells_begin;
144   using Base::cells_end;
145 #endif
146 
147   // For strict-ansi compliance
148   using Base::adjacent_vertices;
149   using Base::combine_offsets;
150   using Base::construct_point;
151   using Base::convert_to_27_sheeted_covering;
152   using Base::draw_dual;
153   using Base::incident_edges;
154   using Base::incident_facets;
155   using Base::incident_cells;
156   using Base::is_valid_conflict;
157   using Base::get_offset;
158   using Base::get_original_vertex;
159   using Base::get_location_offset;
160   using Base::locate;
161   using Base::neighbor_offset;
162   using Base::periodic_point;
163 
164 private:
165   /// This threshold should be chosen such that if all edges are shorter,
166   /// we can be sure that there are no self-edges anymore.
167   FT edge_length_threshold;
168 
169   /// This adjacency list stores all edges that are longer than
170   /// edge_length_threshold.
171   std::map< Vertex_handle, std::list<Vertex_handle> > too_long_edges;
172   unsigned int too_long_edge_counter;
173 
174   class Cover_manager
175   {
176     Periodic_3_Delaunay_triangulation_3& tr;
177 
178   public:
Cover_manager(Periodic_3_Delaunay_triangulation_3 & tr)179     Cover_manager (Periodic_3_Delaunay_triangulation_3& tr)
180     : tr(tr)
181     {}
182 
create_initial_triangulation()183     void create_initial_triangulation()
184     {
185       tr.create_initial_triangulation();
186     }
187 
188     template <class CellIt>
delete_unsatisfying_elements(const CellIt begin,const CellIt end)189     void delete_unsatisfying_elements(const CellIt begin, const CellIt end)
190     {
191       tr.delete_too_long_edges(begin, end);
192     }
193 
194     template <class CellIt>
insert_unsatisfying_elements(Vertex_handle v,const CellIt begin,const CellIt end)195     void insert_unsatisfying_elements(Vertex_handle v, const CellIt begin, const CellIt end)
196     {
197       tr.insert_too_long_edges(v, begin, end);
198     }
199 
can_be_converted_to_1_sheet()200     bool can_be_converted_to_1_sheet () const
201     {
202       return tr.can_be_converted_to_1_sheet();
203     }
204 
update_cover_data_during_management(Cell_handle new_ch,const std::vector<Cell_handle> & new_cells,const bool abort_if_cover_change)205     bool update_cover_data_during_management(Cell_handle new_ch,
206                                              const std::vector<Cell_handle>& new_cells,
207                                              const bool abort_if_cover_change)
208     {
209       return tr.update_cover_data_during_management(new_ch, new_cells, abort_if_cover_change);
210     }
211   };
212 
213 public:
214   /** @name Creation */
215   Periodic_3_Delaunay_triangulation_3(const Iso_cuboid& domain = Iso_cuboid(0,0,0,1,1,1),
216                                       const Geometric_traits& gt = Geometric_traits())
Base(domain,gt)217     : Base(domain, gt), too_long_edge_counter(0)
218   {
219     edge_length_threshold = FT(0.166) * (domain.xmax()-domain.xmin())
220                                       * (domain.xmax()-domain.xmin());
221   }
222 
223   template < typename InputIterator >
224   Periodic_3_Delaunay_triangulation_3(InputIterator first, InputIterator last,
225                                       const Iso_cuboid& domain = Iso_cuboid(0,0,0,1,1,1),
226                                       const Geometric_traits& gt = Geometric_traits())
Base(domain,gt)227     : Base(domain, gt), too_long_edge_counter(0)
228   {
229     edge_length_threshold = FT(0.166) * (domain.xmax()-domain.xmin())
230                                       * (domain.xmax()-domain.xmin());
231     insert(first, last);
232   }
233 
234   // copy constructor duplicates vertices and cells
Periodic_3_Delaunay_triangulation_3(const Periodic_3_Delaunay_triangulation_3 & tr)235   Periodic_3_Delaunay_triangulation_3(const Periodic_3_Delaunay_triangulation_3& tr)
236     : Base(static_cast<const Base&>(tr)),
237       edge_length_threshold(tr.edge_length_threshold), too_long_edge_counter(0)
238   {
239     if(!is_1_cover())
240       compute_too_long_edges();
241 
242     CGAL_triangulation_expensive_postcondition(*this == tr);
243     CGAL_triangulation_expensive_postcondition(is_valid());
244   }
245 
246   Periodic_3_Delaunay_triangulation_3 operator=(Periodic_3_Delaunay_triangulation_3 tr)
247   {
248     tr.swap(*this);
249     return *this;
250   }
251 
swap(Periodic_3_Delaunay_triangulation_3 & tr)252   void swap(Periodic_3_Delaunay_triangulation_3&tr)
253   {
254     std::swap(edge_length_threshold,tr.edge_length_threshold);
255     std::swap(too_long_edges,tr.too_long_edges);
256     std::swap(too_long_edge_counter,tr.too_long_edge_counter);
257     Base::swap(tr);
258   }
259 
clear_covering_data()260   virtual void clear_covering_data()
261   {
262     too_long_edges.clear();
263     too_long_edge_counter = 0;
264   }
265 
update_cover_data_after_setting_domain()266   virtual void update_cover_data_after_setting_domain ()
267   {
268     edge_length_threshold = FT(0.166) * (domain().xmax()-domain().xmin())
269                                       * (domain().xmax()-domain().xmin());
270   }
271 
update_cover_data_after_converting_to_27_sheeted_covering()272   virtual void update_cover_data_after_converting_to_27_sheeted_covering()
273   {
274     compute_too_long_edges();
275   }
276 
277   bool is_extensible_triangulation_in_1_sheet_h1() const;
278   bool is_extensible_triangulation_in_1_sheet_h2() const;
279 
280   // iterates over all edges and store the ones that are longer than 'edge_length_threshold'
compute_too_long_edges()281   void compute_too_long_edges()
282   {
283     too_long_edge_counter = 0;
284     too_long_edges.clear();
285 
286     for(Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit)
287       too_long_edges[vit] = std::list<Vertex_handle>();
288 
289     std::pair<Vertex_handle, Vertex_handle> edge_to_add;
290     Point p1, p2;
291     int i, j;
292 
293     for(Edge_iterator eit = edges_begin(); eit != edges_end(); ++eit)
294     {
295       if(&*(eit->first->vertex(eit->second)) < &*(eit->first->vertex(eit->third))) {
296         i = eit->second; j = eit->third;
297       } else {
298         i = eit->third; j = eit->second;
299       }
300 
301       edge_to_add = std::make_pair(eit->first->vertex(i), eit->first->vertex(j));
302       p1 = construct_point(eit->first->vertex(i)->point(), get_offset(eit->first, i));
303       p2 = construct_point(eit->first->vertex(j)->point(), get_offset(eit->first, j));
304       Vertex_handle v_no = eit->first->vertex(i);
305       if(squared_distance(p1,p2) > edge_length_threshold)
306       {
307         CGAL_triangulation_assertion(find(too_long_edges[v_no].begin(),
308                                           too_long_edges[v_no].end(),
309                                           edge_to_add.second) == too_long_edges[v_no].end());
310         too_long_edges[v_no].push_back(edge_to_add.second);
311         ++too_long_edge_counter;
312       }
313     }
314   }
315 
create_initial_triangulation()316   void create_initial_triangulation()
317   {
318     // create the base for too_long_edges;
319     CGAL_triangulation_assertion( too_long_edges.empty() );
320     CGAL_triangulation_assertion(too_long_edge_counter == 0);
321 
322     for(Vertex_iterator vit = vertices_begin(); vit !=vertices_end(); ++vit )
323       too_long_edges[vit] = std::list<Vertex_handle>();;
324 
325     std::vector<Cell_handle> temp_inc_cells;
326     for(Vertex_iterator vit = vertices_begin(); vit !=vertices_end(); ++vit ) {
327       temp_inc_cells.clear();
328       incident_cells(vit, std::back_inserter(temp_inc_cells));
329       for(unsigned int i=0; i<temp_inc_cells.size(); i++) {
330         int k = temp_inc_cells[i]->index(vit);
331         for(int j=0; j<4; j++) {
332           if(j==k) continue;
333           if(&*vit > &*(temp_inc_cells[i]->vertex(j))) continue;
334           if((find(too_long_edges[vit].begin(),
335                    too_long_edges[vit].end(),
336                    temp_inc_cells[i]->vertex(j)) ==
337               too_long_edges[vit].end())) {
338             too_long_edges[vit].push_back(temp_inc_cells[i]->vertex(j));
339             too_long_edge_counter++;
340           }
341         }
342       }
343     }
344   }
345 
346   template <class CellIt>
delete_too_long_edges(const CellIt begin,const CellIt end)347   void delete_too_long_edges(const CellIt begin, const CellIt end)
348   {
349     std::pair< Vertex_handle, Vertex_handle > edge_to_delete, edge_to_delete2;
350     typename std::list< Vertex_handle >::iterator sit;
351     // Iterate over all cells that are in the star. That means that those cells
352     // are going to be deleted. Therefore, all of them have to be deleted from
353     // too_long_edges, if they are contained in it.
354     for(CellIt it = begin; it != end; ++it) {
355       for(int j=0; j<4; j++) {
356         for(int k=0; k<4; k++) {
357           if(&*((*it)->vertex(j)) < &*((*it)->vertex(k))) {
358             edge_to_delete = std::make_pair((*it)->vertex(j),(*it)->vertex(k));
359           } else {
360             edge_to_delete = std::make_pair((*it)->vertex(k),(*it)->vertex(j));
361           }
362           Vertex_handle v_no = edge_to_delete.first;
363           std::list<Vertex_handle>& vl = too_long_edges[v_no];
364           sit = std::find(vl.begin(), vl.end(), edge_to_delete.second);
365           if(sit != vl.end()) {
366             vl.erase(sit);
367             too_long_edge_counter--;
368           }
369         }
370       }
371     }
372   }
373 
374   template <class CellIt>
insert_too_long_edges(Vertex_handle v,const CellIt begin,const CellIt end)375   void insert_too_long_edges(Vertex_handle v, const CellIt begin, const CellIt end)
376   {
377     CGAL_triangulation_precondition(number_of_vertices() != 0);
378     // add newly added edges to too_long_edges, if necessary.
379     Point p1,p2;
380     std::pair< Vertex_handle, Vertex_handle > edge_to_add;
381     std::list<Vertex_handle> empty_list;
382     too_long_edges[v] = empty_list;
383     // Iterate over all cells of the new star.
384     for(CellIt it = begin; it != end; ++it) {
385       // Consider all possible vertex pairs.
386       for(int k=0; k<4; k++) {
387         for(int j=0; j<4; j++) {
388           if(j==k) continue;
389           if(&*((*it)->vertex(j)) > &*((*it)->vertex(k))) continue;
390           // make the offsets canonical (wrt. to some notion)
391           // add to too_long_edges, if not yet added and if "too long"
392           CGAL_triangulation_precondition(
393                 &*((*it)->vertex(j))< &*((*it)->vertex(k)));
394 
395           edge_to_add = std::make_pair((*it)->vertex(j), (*it)->vertex(k));
396 
397           p1 = construct_point((*it)->vertex(j)->point(), get_offset(*it, j));
398           p2 = construct_point((*it)->vertex(k)->point(), get_offset(*it, k));
399 
400           std::list<Vertex_handle>& vl = too_long_edges[(*it)->vertex(j)];
401 
402           if((squared_distance(p1,p2) > edge_length_threshold)
403              && (find(vl.begin(), vl.end(), edge_to_add.second)
404                  == vl.end())) {
405             vl.push_back(edge_to_add.second);
406             too_long_edge_counter++;
407           }
408         }
409       }
410     }
411   }
412 
can_be_converted_to_1_sheet()413   bool can_be_converted_to_1_sheet() const
414   {
415     return too_long_edge_counter == 0;
416   }
417 
update_cover_data_during_management(Cell_handle new_ch,const std::vector<Cell_handle> & new_cells,const bool abort_if_cover_change)418   bool update_cover_data_during_management(Cell_handle new_ch,
419                                            const std::vector<Cell_handle>& new_cells,
420                                            const bool abort_if_cover_change)
421   {
422     for(int i=0; i < 4; i++)
423     {
424       for(int j=0; j < 4; j++)
425       {
426         if(j==i)
427           continue;
428 
429         if(&*(new_ch->vertex(i)) > &*(new_ch->vertex(j)))
430           continue;
431 
432         Point p1 = construct_point(new_ch->vertex(i)->point(),
433                                    get_offset(new_ch, i));
434         Point p2 = construct_point(new_ch->vertex(j)->point(),
435                                    get_offset(new_ch, j));
436         Vertex_handle v_no = new_ch->vertex(i);
437 
438         if(squared_distance(p1, p2) > edge_length_threshold)
439         {
440           // If the cell does not fulfill the edge-length criterion
441           // revert all changes to the triangulation and transform it
442           // to a triangulation in the needed covering space.
443           if(is_1_cover())
444           {
445             if(abort_if_cover_change)
446               return true;
447 
448             tds().delete_cells(new_cells.begin(), new_cells.end());
449             convert_to_27_sheeted_covering();
450             return true;
451           }
452           else if(find(too_long_edges[v_no].begin(),
453                        too_long_edges[v_no].end(),
454                        new_ch->vertex(j)) == too_long_edges[v_no].end())
455           {
456             too_long_edges[v_no].push_back(new_ch->vertex(j));
457             too_long_edge_counter++;
458           }
459         }
460       }
461     }
462     return false;
463   }
464 
465   /** @name Insertion */
466   Vertex_handle insert(const Point& p, Cell_handle start = Cell_handle())
467   {
468     Conflict_tester tester(p, this);
469     Point_hider hider;
470     Cover_manager cover_manager(*this);
471     return Base::insert_in_conflict(p, start, tester, hider, cover_manager);
472   }
473 
insert(const Point & p,Locate_type lt,Cell_handle c,int li,int lj)474   Vertex_handle insert(const Point& p, Locate_type lt, Cell_handle c,
475                        int li, int lj)
476   {
477     Conflict_tester tester(p, this);
478     Point_hider hider;
479     Cover_manager cover_manager(*this);
480     return Base::insert_in_conflict(p,lt,c,li,lj, tester,hider, cover_manager);
481   }
482 
483   template < class InputIterator >
484   std::ptrdiff_t insert(InputIterator first, InputIterator last,
485                         bool is_large_point_set = false)
486   {
487     if(first == last) return 0;
488     size_type n = number_of_vertices();
489     // The heuristic discards the existing triangulation so it can only be
490     // applied to empty triangulations.
491     if(n!=0)
492       is_large_point_set = false;
493 
494     std::vector<Point> points(first, last);
495     std::vector<Vertex_handle> dummy_points, double_vertices;
496     typename std::vector<Point>::iterator pbegin = points.begin();
497     if(is_large_point_set)
498     {
499       dummy_points = insert_dummy_points();
500     } else {
501       CGAL::cpp98::random_shuffle(points.begin(), points.end());
502       pbegin = points.begin();
503       while(!is_1_cover()) {
504         insert(*pbegin);
505         ++pbegin;
506         if(pbegin == points.end())
507           return number_of_vertices() - n;
508       }
509     }
510 
511     CGAL_postcondition(is_1_cover());
512 
513     spatial_sort (pbegin, points.end(), this->geom_traits());
514 
515     Cell_handle hint;
516     Conflict_tester tester(*pbegin,this);
517     Point_hider hider;
518     Cover_manager cover_manager(*this);
519     double_vertices = Base::insert_in_conflict(
520       points.begin(), points.end(), hint, tester, hider, cover_manager);
521 
522     if(is_large_point_set) {
523       typedef CGAL::Periodic_3_Delaunay_triangulation_remove_traits_3<Gt> P3removeT;
524       typedef CGAL::Delaunay_triangulation_3< P3removeT > DT;
525       typedef Vertex_remover< DT > Remover;
526       P3removeT remove_traits(domain());
527       DT dt(remove_traits);
528       Remover remover(this,dt);
529       Conflict_tester t(this);
530       for(unsigned int i=0; i<dummy_points.size(); i++) {
531         if(std::find(double_vertices.begin(), double_vertices.end(),
532                       dummy_points[i]) == double_vertices.end())
533           Base::remove(dummy_points[i],remover,t, cover_manager);
534       }
535     }
536 
537     return number_of_vertices() - n;
538   }
539 
540   /** @name Point moving */
541   // @todo should be deprecated and a function move() should be introduced
542   // see what is done in /Triangulation_3
543   // Also need to introduce move() for periodic regular triangulations
544   Vertex_handle move_point(Vertex_handle v, const Point& p);
545 
546 
547 public:
548   /** @name Removal */
549   void remove(Vertex_handle v);
550 
551   // Undocumented function that tries to remove 'v' but only does so if removal
552   // does not make the triangulation become 27-sheeted. Useful for P3M3.
553   // \pre the triangulation is 1-sheeted
554   bool remove_if_no_cover_change(Vertex_handle v);
555 
556   template < typename InputIterator >
remove(InputIterator first,InputIterator beyond)557   std::ptrdiff_t remove(InputIterator first, InputIterator beyond)
558   {
559     std::size_t n = number_of_vertices();
560     while(first != beyond) {
561       remove(*first);
562       ++first;
563     }
564     return n - number_of_vertices();
565   }
566 
567 public:
568   /** @name Wrapping the traits */
side_of_oriented_sphere(const Point & p,const Point & q,const Point & r,const Point & s,const Point & t)569   Oriented_side side_of_oriented_sphere(const Point& p, const Point& q,
570                                         const Point& r, const Point& s,
571                                         const Point& t) const {
572     return geom_traits().side_of_oriented_sphere_3_object()(p,q,r,s,t);
573   }
side_of_oriented_sphere(const Point & p,const Point & q,const Point & r,const Point & s,const Point & t,const Offset & o_p,const Offset & o_q,const Offset & o_r,const Offset & o_s,const Offset & o_t)574   Oriented_side side_of_oriented_sphere(const Point& p, const Point& q,
575                                         const Point& r, const Point& s,
576                                         const Point& t,
577                                         const Offset& o_p, const Offset& o_q,
578                                         const Offset& o_r, const Offset& o_s,
579                                         const Offset& o_t) const {
580     return geom_traits().side_of_oriented_sphere_3_object()(
581           p,q,r,s,t,o_p,o_q,o_r,o_s,o_t);
582   }
compare_distance(const Point & p,const Point & q,const Point & r)583   Comparison_result compare_distance(const Point& p, const Point& q,
584                                      const Point& r) const {
585       return geom_traits().compare_distance_3_object()(p, q, r);
586   }
compare_distance(const Point & p,const Point & q,const Point & r,const Offset & o_p,const Offset & o_q,const Offset & o_r)587   Comparison_result compare_distance(const Point& p, const Point& q,
588                                      const Point& r,
589                                      const Offset& o_p, const Offset& o_q,
590                                      const Offset& o_r) const {
591     return geom_traits().compare_distance_3_object()(p, q, r, o_p, o_q, o_r);
592   }
593 
594 private:
595   /** @name Query helpers */
596   Bounded_side _side_of_sphere(const Cell_handle& c, const Point& p,
597       const Offset & offset = Offset(), bool perturb = false) const;
598 
599   Offset get_min_dist_offset(const Point& p, const Offset& o,
600                              const Vertex_handle vh) const;
601 
602 public:
603   /** @name Queries */
604   Bounded_side side_of_sphere(const Cell_handle& c, const Point& p,
605       const Offset & offset = Offset(), bool perturb = false) const{
606     Bounded_side bs = ON_UNBOUNDED_SIDE;
607     int i=0;
608     // TODO: optimize which copies to check depending on the offsets in
609     // the cell.
610     while(bs == ON_UNBOUNDED_SIDE && i<8) {
611       bs= _side_of_sphere(c,p,combine_offsets(offset,int_to_off(i)),perturb);
612       i++;
613     }
614     return bs;
615   }
616 
617   Vertex_handle nearest_vertex(const Point& p, Cell_handle c = Cell_handle()) const;
618   Vertex_handle nearest_vertex_in_cell(const Cell_handle& c, const Point & p,
619                                        const Offset & offset = Offset()) const;
620 
621   /// Undocumented wrapper for find_conflicts.
622   template <class OutputIteratorBoundaryFacets, class OutputIteratorCells>
623   std::pair<OutputIteratorBoundaryFacets, OutputIteratorCells>
find_conflicts(const Point & p,Cell_handle c,OutputIteratorBoundaryFacets bfit,OutputIteratorCells cit)624   find_conflicts(const Point &p, Cell_handle c,
625                  OutputIteratorBoundaryFacets bfit,
626                  OutputIteratorCells cit) const
627   {
628     Triple<OutputIteratorBoundaryFacets,OutputIteratorCells,Emptyset_iterator>
629     t = find_conflicts(p, c, bfit, cit, Emptyset_iterator());
630     return std::make_pair(t.first, t.second);
631   }
632 
633   template <class OutputIteratorBoundaryFacets, class OutputIteratorCells,
634             class OutputIteratorInternalFacets>
635   Triple<OutputIteratorBoundaryFacets, OutputIteratorCells,
636          OutputIteratorInternalFacets>
637   find_conflicts(const Point &p, Cell_handle c,
638                  OutputIteratorBoundaryFacets bfit, OutputIteratorCells cit,
639                  OutputIteratorInternalFacets ifit) const;
640 
641   /// Returns the vertices on the boundary of the conflict hole.
642   template <class OutputIterator>
643   OutputIterator vertices_in_conflict(const Point&p, Cell_handle c,
644                                       OutputIterator res) const;
645 
646   bool is_Gabriel(const Cell_handle c, int i) const;
647   bool is_Gabriel(const Cell_handle c, int i, int j) const;
is_Gabriel(const Facet & f)648   bool is_Gabriel(const Facet& f)const {
649     return is_Gabriel(f.first, f.second);
650   }
is_Gabriel(const Edge & e)651   bool is_Gabriel(const Edge& e) const {
652     return is_Gabriel(e.first, e.second, e.third);
653   }
654 
655 private:
656   /** @name Voronoi diagram helpers */
is_canonical(const Periodic_segment & ps)657   bool is_canonical(const Periodic_segment &ps) const
658   {
659     if(number_of_sheets() == make_array(1,1,1)) return true;
660     Offset o0 = ps.at(0).second;
661     Offset o1 = ps.at(1).second;
662     Offset cumm_off((std::min)(o0.x(),o1.x()),(std::min)(o0.y(),o1.y()),
663                     (std::min)(o0.z(),o1.z()));
664     return (cumm_off == Offset(0,0,0));
665   }
666 
667 public:
668   /** @name Geometric access functions */
669 
point(const Periodic_point & pp)670   Point point(const Periodic_point& pp) const
671   {
672     return point(pp, geom_traits().construct_point_3_object());
673   }
674 
675   // The following functions return the "real" position in space (unrestrained
676   // to the fundamental domain) of the vertices v and c->vertex(idx),
677   // respectively
678 
point(Vertex_handle v)679   Point point(Vertex_handle v) const
680   {
681     return point(v, geom_traits().construct_point_3_object());
682   }
683 
point(Cell_handle c,int idx)684   Point point(Cell_handle c, int idx) const
685   {
686     return point(c, idx, geom_traits().construct_point_3_object());
687   }
688 
689   // end of geometric functions
690 
periodic_circumcenter(Cell_handle c)691   Periodic_point periodic_circumcenter(Cell_handle c) const {
692     return Base::periodic_circumcenter(c, geom_traits().construct_circumcenter_3_object());
693   }
694 
695 public:
696   /** @name Voronoi diagram */
697   // cell dual
dual(Cell_handle c)698   Point dual(Cell_handle c) const {
699     return Base::construct_point(periodic_circumcenter(c).first);
700   }
701 
canonical_dual(Cell_handle c)702   Point canonical_dual(Cell_handle c) const {
703     return point(periodic_circumcenter(c));
704   }
705 
706   // facet dual
canonical_dual_segment(Cell_handle c,int i,Periodic_segment & ps)707   bool canonical_dual_segment(Cell_handle c, int i, Periodic_segment& ps) const {
708     return Base::canonical_dual_segment(c, i, ps, geom_traits().construct_circumcenter_3_object());
709   }
710 
dual(Cell_handle c,int i)711   Periodic_segment dual(Cell_handle c, int i) const
712   {
713     Periodic_segment ps;
714     canonical_dual_segment(c,i,ps);
715     return ps;
716   }
717 
dual(const Facet & f)718   Periodic_segment dual(const Facet & f) const {
719     return dual( f.first, f.second );
720   }
721 
722   // edge dual
723   template <class OutputIterator>
dual(Cell_handle c,int i,int j,OutputIterator points)724   OutputIterator dual(Cell_handle c, int i, int j, OutputIterator points) const {
725     Base::dual(c, i, j, points, geom_traits().construct_circumcenter_3_object());
726     return points;
727   }
728 
729   template <class OutputIterator>
dual(const Edge & e,OutputIterator points)730   OutputIterator dual(const Edge & e, OutputIterator points) const {
731     return dual(e.first, e.second, e.third, points);
732   }
733 
734   // vertex dual
735   template <class OutputIterator>
dual(Vertex_handle v,OutputIterator points)736   OutputIterator dual(Vertex_handle v, OutputIterator points) const {
737     Base::dual(v, points, geom_traits().construct_circumcenter_3_object());
738     return points;
739   }
740 
741   template <class Stream>
draw_dual(Stream & os)742   Stream& draw_dual(Stream& os) const {
743     return Base::draw_dual(os, geom_traits().construct_circumcenter_3_object());
744   }
745 
746   /// Volume computations
dual_volume(Vertex_handle v)747   FT dual_volume(Vertex_handle v) const {
748     return Base::dual_volume(v, geom_traits().construct_circumcenter_3_object());
749   }
750 
751   /// Centroid computations
dual_centroid(Vertex_handle v)752   Point dual_centroid(Vertex_handle v) const {
753     return Base::dual_centroid(v, geom_traits().construct_circumcenter_3_object());
754   }
755 
756   /** @name Checking */
757   bool is_valid(bool verbose = false, int level = 0) const;
758   bool is_valid(Cell_handle c, bool verbose = false, int level = 0) const;
759 
760 protected:
761   // Protected, because inheritors(e.g. periodic triangulation for meshing)
762   // of the class Periodic_3_Delaunay_triangulation_3 use this class
763   class Conflict_tester;
764 private:
765   class Point_hider;
766 
767 #ifndef CGAL_CFG_OUTOFLINE_TEMPLATE_MEMBER_DEFINITION_BUG
768   template <class TriangulationR3> struct Vertex_remover;
769 #else
770   template <class TriangulationR3>
771   struct Vertex_remover
772   {
773     typedef TriangulationR3      Triangulation_R3;
774 
775     typedef typename std::vector<Point>::iterator Hidden_points_iterator;
776 
777     typedef Triple < Vertex_handle, Vertex_handle, Vertex_handle > Vertex_triple;
778 
779     typedef typename Triangulation_R3::Triangulation_data_structure TDSE;
780     typedef typename Triangulation_R3::Cell_handle        CellE_handle;
781     typedef typename Triangulation_R3::Vertex_handle      VertexE_handle;
782     typedef typename Triangulation_R3::Facet              FacetE;
783     typedef typename Triangulation_R3::Finite_cells_iterator Finite_cellsE_iterator;
784 
785     typedef Triple< VertexE_handle, VertexE_handle, VertexE_handle >
786       VertexE_triple;
787 
788     typedef std::map<Vertex_triple,Facet> Vertex_triple_Facet_map;
789     typedef std::map<Vertex_triple, FacetE> Vertex_triple_FacetE_map;
790     typedef typename Vertex_triple_FacetE_map::iterator
791     Vertex_triple_FacetE_map_it;
792 
Vertex_removerVertex_remover793   Vertex_remover(const Self *t, Triangulation_R3 &tmp_) : _t(t),tmp(tmp_) {}
794 
795     const Self *_t;
796     Triangulation_R3 &tmp;
797 
add_hidden_pointsVertex_remover798     void add_hidden_points(Cell_handle) {
799       std::copy (hidden_points_begin(), hidden_points_end(),
800                  std::back_inserter(hidden));
801     }
802 
hidden_points_beginVertex_remover803     Hidden_points_iterator hidden_points_begin() {
804       return hidden.begin();
805     }
hidden_points_endVertex_remover806     Hidden_points_iterator hidden_points_end() {
807       return hidden.end();
808     }
809     //private:
810     // The removal of v may un-hide some points,
811     // Space functions output them.
812     std::vector<Point> hidden;
813   };
814 #endif //CGAL_CFG_OUTOFLINE_TEMPLATE_MEMBER_DEFINITION_BUG
815 };
816 
817 template < class GT, class Tds >
818 typename Periodic_3_Delaunay_triangulation_3<GT,Tds>::Vertex_handle
nearest_vertex(const Point & p,Cell_handle start)819 Periodic_3_Delaunay_triangulation_3<GT,Tds>::nearest_vertex(const Point& p,
820                                                             Cell_handle start) const
821 {
822   if(number_of_vertices() == 0)
823     return Vertex_handle();
824 
825   Locate_type lt;
826   int li, lj;
827   Offset query_offset;
828   Cell_handle c = locate(p, query_offset, lt, li, lj, start);
829 
830   if(lt == Base::VERTEX)
831     return c->vertex(li);
832 
833   // Take the opposite because periodic_locate() returns the offset such that
834   // cell + offset contains 'p' but here we need to move 'p'
835   query_offset = this->combine_offsets(Offset(), -query_offset);
836 
837   // - start with the closest vertex from the located cell.
838   // - repeatedly take the nearest of its incident vertices if any
839   // - if not, we're done.
840   Vertex_handle nearest = nearest_vertex_in_cell(c, p, query_offset);
841   Offset offset_of_nearest = get_min_dist_offset(p, query_offset, nearest);
842 
843   std::vector<Vertex_handle> vs;
844   vs.reserve(32);
845   while(true)
846   {
847     Vertex_handle tmp = nearest;
848     adjacent_vertices(nearest, std::back_inserter(vs));
849     for(typename std::vector<Vertex_handle>::const_iterator
850          vsit = vs.begin(); vsit != vs.end(); ++vsit)
851     {
852       // Can happen in 27-sheeted triangulations composed of few points
853       if((*vsit)->point() == nearest->point())
854         continue;
855 
856       const Offset min_dist_offset = get_min_dist_offset(p, query_offset, *vsit);
857       if(compare_distance(p, (*vsit)->point(), tmp->point(),
858                           query_offset, min_dist_offset, offset_of_nearest) == SMALLER)
859       {
860         tmp = *vsit;
861         offset_of_nearest = min_dist_offset;
862       }
863     }
864 
865     if(tmp == nearest)
866       break;
867 
868     vs.clear();
869     nearest = tmp;
870   }
871 
872   return get_original_vertex(nearest);
873 }
874 
875 // To use the function below, the offset 'o' must be appropriately chosen
876 // because we then only consider positive offsets from 'vh'. See example
877 // of use in nearest_power_vertex()
878 template < class GT, class Tds >
879 typename Periodic_3_Delaunay_triangulation_3<GT,Tds>::Offset
get_min_dist_offset(const Point & p,const Offset & o,const Vertex_handle vh)880 Periodic_3_Delaunay_triangulation_3<GT,Tds>::get_min_dist_offset(
881     const Point& p, const Offset& o, const Vertex_handle vh) const
882 {
883   Offset mdo = get_offset(vh);
884   Offset min = combine_offsets(mdo, Offset(0, 0, 0));
885 
886   for(int i=0; i<=1; ++i) {
887     for(int j=0; j<=1; ++j) {
888       for(int k=0; k<=1; ++k)
889       {
890         if(i==0 && j==0 && k==0)
891           continue;
892 
893         Offset loc_off = combine_offsets(mdo, Offset(i, j, k));
894         if(compare_distance(p, vh->point(), vh->point(), o, min, loc_off) == LARGER)
895           min = loc_off;
896       }
897     }
898   }
899 
900   return min;
901 }
902 
903 /// Returns the finite vertex of the cell c which is the closest to p.
904 template < class GT, class Tds >
905 typename Periodic_3_Delaunay_triangulation_3<GT,Tds>::Vertex_handle
nearest_vertex_in_cell(const Cell_handle & c,const Point & p,const Offset & o)906 Periodic_3_Delaunay_triangulation_3<GT,Tds>::nearest_vertex_in_cell(
907     const Cell_handle& c, const Point& p, const Offset& o) const
908 {
909   CGAL_triangulation_precondition(number_of_vertices() != 0);
910   Vertex_handle nearest = c->vertex(0);
911   for(int i=1; i<4; i++) {
912     nearest = (compare_distance(p,nearest->point(),c->vertex(i)->point(),
913                                 o, get_offset(c,c->index(nearest)),
914                                    get_offset(c,i)) == SMALLER) ?
915                 nearest : c->vertex(i);
916   }
917   return nearest;
918 }
919 
920 // ############################################################################
921 
922 // TODO: reintroduce the commented lines.
923 template < class Gt, class Tds >
924 typename Periodic_3_Delaunay_triangulation_3<Gt,Tds>::Vertex_handle
925 Periodic_3_Delaunay_triangulation_3<Gt,Tds>::
move_point(Vertex_handle v,const Point & p)926 move_point(Vertex_handle v, const Point& p)
927 {
928   CGAL_triangulation_expensive_precondition(is_vertex(v));
929   // Remember an incident vertex to restart
930   // the point location after the removal.
931   // Cell_handle c = v->cell();
932   //Vertex_handle old_neighbor = c->vertex(c->index(v) == 0 ? 1 : 0);
933   //  CGAL_triangulation_assertion(old_neighbor != v);
934 
935   remove(v);
936 
937   if(number_of_vertices() == 0)
938     return insert(p);
939   return insert(p);//, old_neighbor->cell());
940 }
941 
942 template < class Gt, class Tds >
remove(Vertex_handle v)943 void Periodic_3_Delaunay_triangulation_3<Gt,Tds>::remove(Vertex_handle v)
944 {
945   typedef CGAL::Periodic_3_Delaunay_triangulation_remove_traits_3<Gt> P3removeT;
946   typedef CGAL::Delaunay_triangulation_3< P3removeT >
947     Euclidean_triangulation;
948   typedef Vertex_remover< Euclidean_triangulation > Remover;
949   P3removeT remove_traits(domain());
950   Euclidean_triangulation tmp(remove_traits);
951   Remover remover(this, tmp);
952   Conflict_tester ct(this);
953   Cover_manager cover_manager(*this);
954 
955   Base::remove(v, remover, ct, cover_manager);
956   CGAL_triangulation_expensive_assertion(is_valid());
957 }
958 
959 // Undocumented function that tries to remove 'v' but only does so if removal
960 // does not make the triangulation become 27-sheeted. Useful for P3M3.
961 // \pre the triangulation is 1-sheeted
962 template < class Gt, class Tds >
963 bool
964 Periodic_3_Delaunay_triangulation_3<Gt,Tds>::
remove_if_no_cover_change(Vertex_handle v)965 remove_if_no_cover_change(Vertex_handle v)
966 {
967   CGAL_triangulation_precondition(this->is_1_cover());
968 
969   // Since we are in a 1-sheet configuration, we can call directly periodic_remove()
970   // and don't need the conflict tester. The rest is copied from above.
971 
972   typedef CGAL::Periodic_3_Delaunay_triangulation_remove_traits_3< Gt > P3removeT;
973   typedef CGAL::Delaunay_triangulation_3< P3removeT > Euclidean_triangulation;
974   typedef Vertex_remover< Euclidean_triangulation > Remover;
975 
976   P3removeT remove_traits(domain());
977   Euclidean_triangulation tmp(remove_traits);
978   Remover remover(this, tmp);
979   Cover_manager cover_manager(*this);
980 
981   if(!Base::periodic_remove(v, remover, cover_manager, true /*abort if cover change*/))
982   {
983 //    std::cerr << "Warning: removing " << &*v << " (" << v->point() << ") would change cover" << std::endl;
984 //    std::cerr << "Aborted removal." << std::endl;
985     return false; // removing would cause a cover change
986   }
987 
988   CGAL_triangulation_expensive_postcondition(is_valid());
989   CGAL_triangulation_postcondition(this->is_1_cover());
990   return true; // successfully removed the vertex
991 }
992 
993 template < class Gt, class Tds >
994 template <class OutputIteratorBoundaryFacets, class OutputIteratorCells,
995           class OutputIteratorInternalFacets>
996 Triple<OutputIteratorBoundaryFacets, OutputIteratorCells,
997        OutputIteratorInternalFacets>
find_conflicts(const Point & p,Cell_handle c,OutputIteratorBoundaryFacets bfit,OutputIteratorCells cit,OutputIteratorInternalFacets ifit)998 Periodic_3_Delaunay_triangulation_3<Gt,Tds>::find_conflicts(
999     const Point& p, Cell_handle c, OutputIteratorBoundaryFacets bfit,
1000     OutputIteratorCells cit, OutputIteratorInternalFacets ifit) const
1001 {
1002   CGAL_triangulation_precondition(number_of_vertices() != 0);
1003 
1004   std::vector<Facet> facets;
1005   facets.reserve(64);
1006   std::vector<Cell_handle> cells;
1007   cells.reserve(32);
1008 
1009   Conflict_tester tester(p, this);
1010   Triple<typename std::back_insert_iterator<std::vector<Facet> >,
1011          typename std::back_insert_iterator<std::vector<Cell_handle> >,
1012          OutputIteratorInternalFacets> tit = Base::find_conflicts(c, tester,
1013               make_triple(std::back_inserter(facets),
1014                       std::back_inserter(cells), ifit));
1015   ifit = tit.third;
1016 
1017   // Reset the conflict flag on the boundary.
1018   for(typename std::vector<Facet>::iterator fit=facets.begin();
1019       fit != facets.end(); ++fit) {
1020     fit->first->neighbor(fit->second)->tds_data().clear();
1021     *bfit++ = *fit;
1022   }
1023 
1024   // Reset the conflict flag in the conflict cells.
1025   for(typename std::vector<Cell_handle>::iterator ccit=cells.begin();
1026       ccit != cells.end(); ++ccit) {
1027     (*ccit)->tds_data().clear();
1028     *cit++ = *ccit;
1029   }
1030 
1031   for(typename std::vector<Vertex_handle>::iterator
1032       voit = this->v_offsets.begin();
1033       voit != this->v_offsets.end(); ++voit) {
1034     (*voit)->clear_offset();
1035   }
1036   this->v_offsets.clear();
1037 
1038   return make_triple(bfit, cit, ifit);
1039 }
1040 
1041 template < class Gt, class Tds >
1042 template <class OutputIterator>
1043 OutputIterator
vertices_in_conflict(const Point & p,Cell_handle c,OutputIterator res)1044 Periodic_3_Delaunay_triangulation_3<Gt,Tds>::vertices_in_conflict(
1045     const Point& p, Cell_handle c, OutputIterator res) const
1046 {
1047   if(number_of_vertices() == 0) return res;
1048 
1049   // Get the facets on the boundary of the hole.
1050   std::vector<Facet> facets;
1051   find_conflicts(p, c, std::back_inserter(facets), Emptyset_iterator());
1052 
1053   // Then extract uniquely the vertices.
1054   std::set<Vertex_handle> vertices;
1055   for(typename std::vector<Facet>::const_iterator i = facets.begin();
1056        i != facets.end(); ++i) {
1057     vertices.insert(i->first->vertex((i->second+1)&3));
1058     vertices.insert(i->first->vertex((i->second+2)&3));
1059     vertices.insert(i->first->vertex((i->second+3)&3));
1060   }
1061 
1062   return std::copy(vertices.begin(), vertices.end(), res);
1063 }
1064 
1065 template < class Gt, class Tds >
1066 Bounded_side Periodic_3_Delaunay_triangulation_3<Gt,Tds>::
_side_of_sphere(const Cell_handle & c,const Point & q,const Offset & offset,bool perturb)1067 _side_of_sphere(const Cell_handle& c, const Point& q,
1068                 const Offset& offset, bool perturb ) const
1069 {
1070   Point p0 = c->vertex(0)->point(),
1071         p1 = c->vertex(1)->point(),
1072         p2 = c->vertex(2)->point(),
1073         p3 = c->vertex(3)->point();
1074   Offset o0 = this->get_offset(c,0),
1075         o1 = this->get_offset(c,1),
1076         o2 = this->get_offset(c,2),
1077         o3 = this->get_offset(c,3),
1078         oq = offset;
1079 
1080   Oriented_side os = ON_NEGATIVE_SIDE;
1081   os= side_of_oriented_sphere(p0, p1, p2, p3, q, o0, o1, o2, o3, oq);
1082 
1083   if(os != ON_ORIENTED_BOUNDARY || !perturb)
1084     return enum_cast<Bounded_side>(os);
1085 
1086   //We are now in a degenerate case => we do a symbolic perturbation.
1087   // We sort the points lexicographically.
1088   Periodic_point pts[5] = {std::make_pair(p0,o0), std::make_pair(p1,o1),
1089                            std::make_pair(p2,o2), std::make_pair(p3,o3),
1090                            std::make_pair(q,oq)};
1091   const Periodic_point *points[5] = {&pts[0],&pts[1],&pts[2],&pts[3],&pts[4]};
1092 
1093   std::sort(points, points+5, typename Base::Perturbation_order(this));
1094 
1095   // We successively look whether the leading monomial, then 2nd monomial
1096   // of the determinant has non null coefficient.
1097   // 2 iterations are enough (cf paper)
1098   for(int i=4; i>2; --i) {
1099     if(points[i] == &pts[4]) {
1100       CGAL_triangulation_assertion(orientation(p0, p1, p2, p3, o0, o1, o2, o3)
1101           == POSITIVE);
1102       // since p0 p1 p2 p3 are non coplanar and positively oriented
1103       return ON_UNBOUNDED_SIDE;
1104     }
1105     Orientation o;
1106     if(points[i] == &pts[3] &&
1107         (o = orientation(p0, p1, p2, q, o0, o1, o2, oq)) != COPLANAR ) {
1108       return enum_cast<Bounded_side>(o);
1109     }
1110     if(points[i] == &pts[2] &&
1111         (o = orientation(p0, p1, q, p3, o0, o1, oq, o3)) != COPLANAR ) {
1112       return enum_cast<Bounded_side>(o);
1113     }
1114     if(points[i] == &pts[1] &&
1115         (o = orientation(p0, q, p2, p3, o0, oq, o2, o3)) != COPLANAR ) {
1116       return enum_cast<Bounded_side>(o);
1117     }
1118     if(points[i] == &pts[0] &&
1119         (o = orientation(q, p1, p2 ,p3, oq, o1, o2, o3)) != COPLANAR ) {
1120       return enum_cast<Bounded_side>(o);
1121     }
1122   }
1123 
1124   CGAL_triangulation_assertion(false);
1125   return ON_UNBOUNDED_SIDE;
1126 }
1127 
1128 template < class Gt, class Tds >
1129 bool Periodic_3_Delaunay_triangulation_3<Gt,Tds>::
is_Gabriel(const Cell_handle c,int i)1130 is_Gabriel(const Cell_handle c, int i) const
1131 {
1132   CGAL_triangulation_precondition(number_of_vertices() != 0);
1133   typename Geom_traits::Side_of_bounded_sphere_3
1134     side_of_bounded_sphere =
1135     geom_traits().side_of_bounded_sphere_3_object();
1136 
1137   if(side_of_bounded_sphere (
1138         c->vertex(vertex_triple_index(i,0))->point(),
1139         c->vertex(vertex_triple_index(i,1))->point(),
1140         c->vertex(vertex_triple_index(i,2))->point(),
1141         c->vertex(i)->point(),
1142         get_offset(c,vertex_triple_index(i,0)),
1143         get_offset(c,vertex_triple_index(i,1)),
1144         get_offset(c,vertex_triple_index(i,2)),
1145         get_offset(c,i) ) == ON_BOUNDED_SIDE )
1146     return false;
1147 
1148   Cell_handle neighbor = c->neighbor(i);
1149   int in = neighbor->index(c);
1150 
1151   if(side_of_bounded_sphere(
1152         neighbor->vertex(vertex_triple_index(in,0))->point(),
1153         neighbor->vertex(vertex_triple_index(in,1))->point(),
1154         neighbor->vertex(vertex_triple_index(in,2))->point(),
1155         neighbor->vertex(in)->point(),
1156         get_offset(neighbor,vertex_triple_index(in,0)),
1157         get_offset(neighbor,vertex_triple_index(in,1)),
1158         get_offset(neighbor,vertex_triple_index(in,2)),
1159         get_offset(neighbor, in) ) == ON_BOUNDED_SIDE )
1160     return false;
1161 
1162   return true;
1163 }
1164 
1165 template < class Gt, class Tds >
1166 bool Periodic_3_Delaunay_triangulation_3<Gt,Tds>::
is_Gabriel(const Cell_handle c,int i,int j)1167 is_Gabriel(const Cell_handle c, int i, int j) const
1168 {
1169   typename Geom_traits::Side_of_bounded_sphere_3
1170     side_of_bounded_sphere =
1171     geom_traits().side_of_bounded_sphere_3_object();
1172 
1173   Facet_circulator fcirc = incident_facets(c,i,j), fdone(fcirc);
1174   Vertex_handle v1 = c->vertex(i);
1175   Vertex_handle v2 = c->vertex(j);
1176   do {
1177     // test whether the vertex of cc opposite to *fcirc
1178     // is inside the sphere defined by the edge e = (s, i,j)
1179     // It is necessary to fetch the offsets from the current cell.
1180     Cell_handle cc = fcirc->first;
1181     int i1 = cc->index(v1);
1182     int i2 = cc->index(v2);
1183     int i3 = fcirc->second;
1184     Offset off1 = get_offset(cc, i1);
1185     Offset off2 = get_offset(cc, i2);
1186     Offset off3 = get_offset(cc, i3);
1187     if(side_of_bounded_sphere(
1188           v1->point(), v2->point(), cc->vertex(fcirc->second)->point(),
1189           off1, off2, off3) == ON_BOUNDED_SIDE ) return false;
1190   } while(++fcirc != fdone);
1191   return true;
1192 }
1193 
1194 template < class Gt, class Tds >
1195 bool
1196 Periodic_3_Delaunay_triangulation_3<Gt,Tds>::
is_valid(bool verbose,int level)1197 is_valid(bool verbose, int level) const
1198 {
1199   if(!Base::is_valid(verbose, level)) {
1200     if(verbose)
1201       std::cerr << "Delaunay: invalid base" << std::endl;
1202     return false;
1203   }
1204 
1205   Conflict_tester tester(this);
1206   if(!is_valid_conflict(tester, verbose, level)) {
1207     if(verbose)
1208       std::cerr << "Delaunay: conflict problems" << std::endl;
1209     return false;
1210   }
1211 
1212   if(verbose)
1213     std::cerr << "Delaunay valid triangulation" << std::endl;
1214   return true;
1215 }
1216 
1217 template < class GT, class TDS >
1218 bool
1219 Periodic_3_Delaunay_triangulation_3<GT,TDS>::
is_valid(Cell_handle ch,bool verbose,int level)1220 is_valid(Cell_handle ch, bool verbose, int level) const
1221 {
1222   bool error = false;
1223   if(!Base::is_valid(ch, verbose, level)) {
1224     error = true;
1225     if(verbose) {
1226       std::cerr << "geometrically invalid cell" << std::endl;
1227       for(int i=0; i<4; i++)
1228         std::cerr << ch->vertex(i)->point() << ", ";
1229       std::cerr << std::endl;
1230     }
1231   }
1232 
1233   for(Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++ vit) {
1234     for(int i=-1; i<=1; i++) {
1235       for(int j=-1; j<=1; j++) {
1236         for(int k=-1; k<=1; k++) {
1237           if(periodic_point(ch,0) == std::make_pair(periodic_point(vit).first,
1238                                                      periodic_point(vit).second+Offset(i,j,k))
1239               || periodic_point(ch,1) == std::make_pair(periodic_point(vit).first,
1240                                                         periodic_point(vit).second+Offset(i,j,k))
1241               || periodic_point(ch,2) == std::make_pair(periodic_point(vit).first,
1242                                                         periodic_point(vit).second+Offset(i,j,k))
1243               || periodic_point(ch,3) == std::make_pair(periodic_point(vit).first,
1244                                                         periodic_point(vit).second+Offset(i,j,k)) )
1245             continue;
1246           if(_side_of_sphere(ch, periodic_point(vit).first,
1247                               periodic_point(vit).second+Offset(i,j,k),true)
1248               != ON_UNBOUNDED_SIDE) {
1249             error = true;
1250             if(verbose) {
1251               std::cerr << "Delaunay invalid cell" << std::endl;
1252               for(int i=0; i<4; i++) {
1253                 Periodic_point pp = periodic_point(ch,i);
1254                 std::cerr <<"("<<pp.first <<","<<pp.second<< "), ";
1255               }
1256               std::cerr << std::endl;
1257             }
1258           }
1259         }
1260       }
1261     }
1262   }
1263   return !error;
1264 }
1265 
1266 template < class GT, class Tds >
1267 class Periodic_3_Delaunay_triangulation_3<GT,Tds>::Conflict_tester
1268 {
1269   // stores a pointer to the triangulation,
1270   // a point, and an offset
1271   const Self *t;
1272   Point p;
1273   // stores the offset of a point in 27-cover
1274   mutable Offset o;
1275 
1276 public:
1277   /// Constructor
Conflict_tester(const Self * _t)1278   Conflict_tester(const Self *_t) : t(_t), p(Point()) {}
Conflict_tester(const Point & pt,const Self * _t)1279   Conflict_tester(const Point &pt, const Self *_t) : t(_t), p(pt) { }
1280 
1281   /** The functor
1282     *
1283     * gives true if the circumcircle of c contains p
1284     */
operator()1285   bool operator()(const Cell_handle c, const Offset &off) const {
1286     return (t->_side_of_sphere(c, p, t->combine_offsets(o, off), true)
1287         == ON_BOUNDED_SIDE);
1288   }
1289 
operator()1290   bool operator()(const Cell_handle c, const Point& pt,
1291       const Offset &off) const {
1292     return (t->_side_of_sphere(c, pt, o + off, true) == ON_BOUNDED_SIDE);
1293   }
1294 
compare_weight(Point,Point)1295   int compare_weight(Point, Point) const
1296   {
1297     return 0;
1298   }
1299 
test_initial_cell(Cell_handle c,const Offset & off)1300   bool test_initial_cell(Cell_handle c, const Offset &off) const
1301   {
1302     if(!(operator()(c, off)))
1303       CGAL_triangulation_assertion(false);
1304     return true;
1305   }
1306 
set_point(const Point & _p)1307   void set_point(const Point &_p) {
1308     p = _p;
1309   }
1310 
set_offset(const Offset & off)1311   void set_offset(const Offset &off) const {
1312     o = off;
1313   }
1314 
get_offset()1315   const Offset &get_offset() const {
1316     return o;
1317   }
1318 
point()1319   const Point &point() const {
1320     return p;
1321   }
1322 
1323 };
1324 
1325 template < class GT, class Tds>
1326 class Periodic_3_Delaunay_triangulation_3<GT,Tds>::Point_hider
1327 {
1328 public:
Point_hider()1329   Point_hider() { }
1330 
set_original_cube(bool)1331   void set_original_cube (bool) const { }
1332 
1333   template <class InputIterator>
set_vertices(InputIterator,InputIterator)1334   inline void set_vertices(InputIterator, InputIterator) const { }
reinsert_vertices(Vertex_handle)1335   inline void reinsert_vertices(Vertex_handle ) { }
replace_vertex(Cell_handle c,int index,const Point &)1336   inline Vertex_handle replace_vertex(Cell_handle c, int index, const Point &) {
1337     return c->vertex(index);
1338   }
hide_point(Cell_handle,const Point &)1339   inline void hide_point(Cell_handle, const Point &) { }
1340 
hide(Point &,Cell_handle)1341   inline void hide(Point &, Cell_handle ) const {
1342     CGAL_triangulation_assertion(false);
1343   }
1344 
do_hide(const Point &,Cell_handle)1345   inline void do_hide(const Point &, Cell_handle ) const {
1346     CGAL_triangulation_assertion(false);
1347   }
1348   template < class Tester >
replace_vertex(const Point &,Vertex_handle,const Tester &)1349   inline bool replace_vertex(const Point &, Vertex_handle ,
1350                              const Tester &) const {
1351     return true;
1352   }
1353   template <class Conflict_tester>
hide_points(Vertex_handle,const Conflict_tester &)1354   inline void hide_points(Vertex_handle, const Conflict_tester &) {
1355     // No points to hide in the Delaunay triangulation.
1356   }
1357 };
1358 
1359 #ifndef CGAL_CFG_OUTOFLINE_TEMPLATE_MEMBER_DEFINITION_BUG
1360 template <class GT, class Tds>
1361 template <class TriangulationR3>
1362 struct Periodic_3_Delaunay_triangulation_3<GT,Tds>::Vertex_remover
1363 {
1364   typedef TriangulationR3      Triangulation_R3;
1365 
1366   typedef typename std::vector<Point>::iterator Hidden_points_iterator;
1367 
1368   typedef Triple < Vertex_handle, Vertex_handle, Vertex_handle > Vertex_triple;
1369 
1370   typedef typename Triangulation_R3::Triangulation_data_structure TDSE;
1371   typedef typename Triangulation_R3::Cell_handle        CellE_handle;
1372   typedef typename Triangulation_R3::Vertex_handle      VertexE_handle;
1373   typedef typename Triangulation_R3::Facet              FacetE;
1374   typedef typename Triangulation_R3::Finite_cells_iterator Finite_cellsE_iterator;
1375 
1376   typedef Triple< VertexE_handle, VertexE_handle, VertexE_handle > VertexE_triple;
1377 
1378   typedef std::map<Vertex_triple, Facet>  Vertex_triple_Facet_map;
1379   typedef std::map<Vertex_triple, FacetE> Vertex_triple_FacetE_map;
1380   typedef typename Vertex_triple_FacetE_map::iterator Vertex_triple_FacetE_map_it;
1381 
1382   Vertex_remover(const Self *t, Triangulation_R3 &tmp_) : _t(t),tmp(tmp_) {}
1383 
1384   const Self *_t;
1385   Triangulation_R3 &tmp;
1386 
1387   void add_hidden_points(Cell_handle) {
1388     std::copy(hidden_points_begin(), hidden_points_end(),
1389               std::back_inserter(hidden));
1390   }
1391 
1392   Hidden_points_iterator hidden_points_begin() {
1393     return hidden.begin();
1394   }
1395   Hidden_points_iterator hidden_points_end() {
1396     return hidden.end();
1397   }
1398   //private:
1399   // The removal of v may un-hide some points,
1400   // Space functions output them.
1401   std::vector<Point> hidden;
1402 };
1403 #endif //CGAL_CFG_OUTOFLINE_TEMPLATE_MEMBER_DEFINITION_BUG
1404 
1405 template < class GT, class TDS >
1406 inline bool
1407 Periodic_3_Delaunay_triangulation_3<GT,TDS>::
1408 is_extensible_triangulation_in_1_sheet_h1() const
1409 {
1410   if(!is_1_cover()) {
1411     if(too_long_edge_counter == 0) return true;
1412     else return false;
1413   } else {
1414     typename Geometric_traits::FT longest_edge_squared_length(0);
1415     Segment s;
1416     for(Periodic_segment_iterator psit = this->periodic_segments_begin(Base::UNIQUE);
1417         psit != this->periodic_segments_end(Base::UNIQUE); ++psit) {
1418       s = this->construct_segment(*psit);
1419       longest_edge_squared_length = (std::max)(longest_edge_squared_length,
1420     s.squared_length());
1421     }
1422     return (longest_edge_squared_length < edge_length_threshold);
1423   }
1424 }
1425 
1426 template < class GT, class TDS >
1427 inline bool
1428 Periodic_3_Delaunay_triangulation_3<GT,TDS>::
1429 is_extensible_triangulation_in_1_sheet_h2() const
1430 {
1431   typedef typename Geometric_traits::Construct_circumcenter_3
1432     Construct_circumcenter;
1433   typedef typename Geometric_traits::FT FT;
1434   Construct_circumcenter construct_circumcenter
1435     = geom_traits().construct_circumcenter_3_object();
1436   for(Periodic_tetrahedron_iterator tit = this->periodic_tetrahedra_begin(Base::UNIQUE);
1437        tit != this->periodic_tetrahedra_end(Base::UNIQUE); ++tit) {
1438     Point cc = construct_circumcenter(
1439   tit->at(0).first, tit->at(1).first,
1440   tit->at(2).first, tit->at(3).first,
1441   tit->at(0).second, tit->at(1).second,
1442   tit->at(2).second, tit->at(3).second);
1443 
1444     if( !(FT(16)*squared_distance(cc,point(tit->at(0)))
1445       < (domain().xmax()-domain().xmin())*(domain().xmax()-domain().xmin())) )
1446       return false;
1447   }
1448   return true;
1449 }
1450 
1451 template < class GT, class TDS >
1452 std::istream &
1453 operator>> (std::istream& is, Periodic_3_Delaunay_triangulation_3<GT,TDS> &tr)
1454 {
1455   typedef Periodic_3_Delaunay_triangulation_3<GT,TDS>   P3DT3;
1456   typedef typename P3DT3::Base                          Base;
1457   typedef typename GT::FT FT;
1458 
1459   is >> static_cast<Base&>(tr);
1460 
1461   tr.edge_length_threshold = FT(0.166) * (tr.domain().xmax()-tr.domain().xmin())
1462                                        * (tr.domain().xmax()-tr.domain().xmin());
1463 
1464   tr.compute_too_long_edges();
1465 
1466   CGAL_triangulation_expensive_assertion( tr.is_valid() );
1467   return is;
1468 }
1469 
1470 } // namespace CGAL
1471 
1472 #endif // CGAL_PERIODIC_3_DELAUNAY_TRIANGULATION_3_H
1473