1 // Copyright (c) 2014  INRIA Sophia-Antipolis (France), INRIA Lorraine LORIA.
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/Optimal_transportation_reconstruction_2/include/CGAL/OTR_2/Reconstruction_triangulation_2.h $
7 // $Id: Reconstruction_triangulation_2.h 263ad6b 2020-08-20T18:25:01+02:00 Dmitry Anisimov
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s)     : Fernando de Goes, Pierre Alliez, Ivo Vigan, Clément Jamin
11 
12 #ifndef CGAL_RECONSTRUCTION_TRIANGULATION_2_H
13 #define CGAL_RECONSTRUCTION_TRIANGULATION_2_H
14 
15 #include <CGAL/license/Optimal_transportation_reconstruction_2.h>
16 
17 
18 // local
19 #include <CGAL/OTR_2/Sample.h>
20 #include <CGAL/OTR_2/Reconstruction_edge_2.h>
21 #include <CGAL/OTR_2/Cost.h>
22 #include <CGAL/OTR_2/Reconstruction_vertex_base_2.h>
23 #include <CGAL/OTR_2/Reconstruction_face_base_2.h>
24 
25 // CGAL
26 #include <CGAL/basic.h>
27 #include <CGAL/Random.h>
28 #include <CGAL/intersections.h>
29 #include <CGAL/Delaunay_triangulation_2.h>
30 
31 // boost
32 #include <boost/multi_index/mem_fun.hpp>
33 #include <boost/multi_index_container.hpp>
34 #include <boost/multi_index/ordered_index.hpp>
35 #include <boost/multi_index/identity.hpp>
36 #include <boost/multi_index/member.hpp>
37 #include <boost/container/deque.hpp>
38 #include <boost/optional.hpp>
39 
40 // STL
41 #include <map>
42 #include <set>
43 #include <vector>
44 #include <queue>
45 #include <iostream>
46 
47 #define CGAL_EPS   1e-15
48 
49 namespace CGAL {
50 namespace OTR_2 {
51 
52 /// \internal
53 ///  The Reconstruction_triangulation_2 class
54 ///  provides the reconstruction simplex as well as the transportation plan.
55 /// - Each vertex stores a normal vector.
56 /// - A vertex a Sample which got assigned to it by the transportation plan,
57 ///   well as the corresponding relocated Point (of type Traits_::Point_2).
58 /// - In order to solve a linear system over the triangulation, a vertex may be constrained
59 ///   or not (i.e. may contribute to the right or left member of the linear system),
60 ///   and has a unique index.
61 /// The vertex class must derive from Reconstruction_vertex_base_3.
62 ///
63 ///  @param Traits_   The traits class
64 ///  @param Tds       Model of TriangulationDataStructure_2.
65 ///  The vertex class must derive from Reconstruction_vertex_base_2.
66 ///  The face   class must derive from Reconstruction_face_base_2.
67 template<
68   class Traits_,
69   class Tds_ = Triangulation_data_structure_2<
70   Reconstruction_vertex_base_2<Traits_>,
71   Reconstruction_face_base_2<Traits_> > >
72 class Reconstruction_triangulation_2
73   : public Delaunay_triangulation_2<Traits_, Tds_>
74 {
75 public:
76 
77   typedef Delaunay_triangulation_2<Traits_, Tds_> Base;
78 
79   typedef typename Traits_::FT FT;
80   typedef typename Traits_::Point_2 Point;
81   typedef typename Traits_::Vector_2 Vector;
82   typedef typename Traits_::Line_2 Line;
83   typedef typename Traits_::Segment_2 Segment;
84   typedef typename Traits_::Triangle_2 Triangle;
85 
86   typedef typename Base::Vertex Vertex;
87   typedef typename Base::Vertex_handle Vertex_handle;
88   typedef typename Base::Vertex_iterator Vertex_iterator;
89   typedef typename Base::Vertex_circulator Vertex_circulator;
90   typedef typename Base::Finite_vertices_iterator Finite_vertices_iterator;
91 
92   typedef typename Base::Edge Edge;
93   typedef typename Base::Edge_circulator Edge_circulator;
94   typedef typename Base::Finite_edges_iterator Finite_edges_iterator;
95 
96   typedef typename Base::Face_handle Face_handle;
97   typedef typename Base::Face_circulator Face_circulator;
98   typedef typename Base::Finite_faces_iterator Finite_faces_iterator;
99 
100   typedef std::map<Vertex_handle, Vertex_handle,
101       less_Vertex_handle<Vertex_handle> > Vertex_handle_map;
102   typedef std::map<Face_handle, Face_handle,
103                    less_Face_handle<Face_handle> > Face_handle_map;
104 
105   typedef std::set<Vertex_handle,
106                    less_Vertex_handle<Vertex_handle> > Vertex_handle_set;
107   typedef std::set<Edge, less_Edge<Edge> > Edge_set;
108 
109   typedef std::vector<Edge> Edge_vector;
110 
111   typedef OTR_2::Cost<FT> Cost_;
112   typedef OTR_2::Sample<Traits_> Sample_;
113   typedef std::vector<Sample_*> Sample_vector;
114   typedef typename Sample_vector::const_iterator Sample_vector_const_iterator;
115 
116   typedef OTR_2::Sample_with_priority<Sample_> PSample;
117   typedef std::priority_queue<PSample, boost::container::deque<PSample>,
118       OTR_2::greater_priority<PSample> > SQueue;
119 
120   typedef Reconstruction_edge_2<FT, Edge,
121                                 Vertex_handle, Face_handle> Rec_edge_2;
122 
123   using Base::geom_traits;
124 
125   typedef boost::multi_index_container<
126       Rec_edge_2,
127       boost::multi_index::indexed_by<
128       // sort by Rec_edge_2::operator<
129       boost::multi_index::ordered_unique< boost::multi_index::identity<
130       Rec_edge_2 > > ,
131       // sort by Rec_edge_2::priority()
132       boost::multi_index::ordered_non_unique<
133       boost::multi_index::const_mem_fun<
134       Rec_edge_2,const FT,&Rec_edge_2::priority> >
135   >
136   > MultiIndex;
137 
138   FT m_factor; // ghost vs solid
139   mutable Random rng;
140 
141 public:
142   Reconstruction_triangulation_2(Traits_ traits = Traits_())
Base(traits)143   : Base(traits), m_factor(1.)
144   {
145   }
146 
~Reconstruction_triangulation_2()147   ~Reconstruction_triangulation_2() {
148   }
149 
ghost_factor()150   FT& ghost_factor() {
151     return m_factor;
152   }
153 
ghost_factor()154   FT ghost_factor() const {
155     return m_factor;
156   }
157 
random_finite_edge()158   Edge random_finite_edge() const {
159     std::size_t nbf = Base::number_of_faces();
160     int offset = rng.get_int(0, static_cast<int>(nbf - 1));
161     Finite_faces_iterator fi = Base::finite_faces_begin();
162     for (int i = 0; i < offset; i++)
163       fi++;
164     Face_handle face = fi;
165     int index = rng.get_int(0, 40) % 3;
166     return Edge(face, index);
167   }
168 
169   // ACCESS //
170 
source_vertex(const Edge & edge)171   Vertex_handle source_vertex(const Edge& edge) const {
172     return edge.first->vertex(Base::ccw(edge.second));
173   }
174 
target_vertex(const Edge & edge)175   Vertex_handle target_vertex(const Edge& edge) const {
176     return edge.first->vertex(Base::cw(edge.second));
177   }
178 
opposite_vertex(const Edge & edge)179   Vertex_handle opposite_vertex(const Edge& edge) const {
180     return edge.first->vertex(edge.second);
181   }
182 
is_pinned(const Edge & edge)183   bool is_pinned(const Edge& edge) const {
184     Vertex_handle s = source_vertex(edge);
185     if (s->pinned())
186       return true;
187     return false;
188   }
189 
twin_edge(const Edge & edge)190   Edge twin_edge(const Edge& edge) const {
191     Face_handle f = edge.first;
192     Vertex_handle v = source_vertex(edge);
193     Face_handle nf = f->neighbor(edge.second);
194     return Edge(nf, Base::ccw(nf->index(v)));
195   }
196 
next_edge(const Edge & edge)197   Edge next_edge(const Edge& edge) const {
198     Face_handle f = edge.first;
199     int index = Base::ccw(edge.second);
200     return Edge(f, index);
201   }
202 
prev_edge(const Edge & edge)203   Edge prev_edge(const Edge& edge) const {
204     Face_handle f = edge.first;
205     int index = Base::cw(edge.second);
206     return Edge(f, index);
207   }
208 
get_length(const Edge & edge)209   FT get_length(const Edge& edge) const {
210     Segment segment = get_segment(edge);
211     return CGAL::approximate_sqrt(segment.squared_length());
212   }
213 
get_segment(const Edge & edge)214   Segment get_segment(const Edge& edge) const {
215     const Point& ps = source_vertex(edge)->point();
216     const Point& pt = target_vertex(edge)->point();
217     return geom_traits().construct_segment_2_object()(ps, pt);
218   }
219 
get_triangle(Face_handle face)220   Triangle get_triangle(Face_handle face) const {
221     Vertex_handle v0 = face->vertex(0);
222     Vertex_handle v1 = face->vertex(1);
223     Vertex_handle v2 = face->vertex(2);
224     return geom_traits().construct_triangle_2_object()(
225       v0->point(), v1->point(), v2->point());
226   }
227 
228   // GET LINK //
229 
get_vertices_from_edge_link(const Edge & edge,Vertex_handle_set & vertices)230   void get_vertices_from_edge_link(const Edge& edge,
231       Vertex_handle_set& vertices) const {
232     vertices.insert(opposite_vertex(edge));
233     vertices.insert(opposite_vertex(twin_edge(edge)));
234   }
235 
get_vertices_from_vertex_link(Vertex_handle vertex,Vertex_handle_set & vertices)236   void get_vertices_from_vertex_link(Vertex_handle vertex,
237       Vertex_handle_set& vertices) const {
238     Vertex_circulator vcirc = Base::incident_vertices(vertex);
239     Vertex_circulator vend = vcirc;
240     CGAL_For_all(vcirc, vend)
241     {
242       Vertex_handle v = vcirc;
243       vertices.insert(v);
244     }
245   }
246 
247   // boundary of star(vertex)
248   // 'outward' chooses the orientation of the boundary
249   void get_edges_from_star_minus_link(Vertex_handle vertex, Edge_vector& hull,
250       bool outward = false) const {
251     Face_circulator fcirc = Base::incident_faces(vertex);
252     Face_circulator fend = fcirc;
CGAL_For_all(fcirc,fend)253     CGAL_For_all(fcirc, fend)
254     {
255       Face_handle face = fcirc;
256       int index = face->index(vertex);
257       Edge edge(face, index);
258       if (outward)
259         edge = twin_edge(edge);
260       hull.push_back(edge);
261     }
262   }
263 
264   // ATTRIBUTES //
265 
is_ghost(const Edge & edge)266   bool is_ghost(const Edge& edge) const {
267     return edge.first->ghost(edge.second);
268   }
269 
get_plan(const Edge & edge)270   int get_plan(const Edge& edge) const {
271     return edge.first->plan(edge.second);
272   }
273 
set_plan(const Edge & edge,int simplex)274   void set_plan(const Edge& edge, int simplex) const {
275     edge.first->plan(edge.second) = simplex;
276   }
277 
get_mass(const Edge & edge)278   FT get_mass(const Edge& edge) const {
279     return edge.first->mass(edge.second);
280   }
281 
set_mass(const Edge & edge,const FT mass)282   void set_mass(const Edge& edge, const FT mass) const {
283     edge.first->mass(edge.second) = mass;
284   }
285 
get_cost(const Edge & edge)286   const Cost_& get_cost(const Edge& edge) const {
287     return edge.first->cost(edge.second);
288   }
289 
set_vertex_cost(const Edge & edge,const Cost_ & cost)290   void set_vertex_cost(const Edge& edge, const Cost_& cost) const {
291     edge.first->vertex_cost(edge.second) = cost;
292   }
293 
set_edge_cost(const Edge & edge,const Cost_ & cost)294   void set_edge_cost(const Edge& edge, const Cost_& cost) const {
295     edge.first->edge_cost(edge.second) = cost;
296   }
297 
get_vertex_minus_edge_cost(const Edge & edge)298   FT get_vertex_minus_edge_cost(const Edge& edge) const {
299     const Cost_& vcost = edge.first->vertex_cost(edge.second);
300     const Cost_& ecost = edge.first->edge_cost(edge.second);
301     return vcost.finalize() - m_factor * ecost.finalize();
302   }
303 
get_vertex_over_edge_cost(const Edge & edge)304   FT get_vertex_over_edge_cost(const Edge& edge) const {
305     FT vvalue = edge.first->vertex_cost(edge.second).finalize();
306     FT evalue = edge.first->edge_cost(edge.second).finalize();
307     if (evalue == vvalue)
308       return FT(1) / m_factor;
309     return vvalue / (m_factor * evalue);
310   }
311 
get_edge_relevance(const Edge & edge)312   FT get_edge_relevance(const Edge& edge) const {
313     FT M = get_mass(edge);
314     if (M == FT(0))
315       return FT(0);
316 
317     FT L = get_length(edge);
318     FT cost = get_cost(edge).finalize();
319     return M * L * L / cost;
320   }
321 
get_density(const Edge & edge)322   FT get_density(const Edge& edge) const {
323     FT length = get_length(edge);
324     FT mass = get_mass(edge);
325     return (mass / length);
326   }
327 
nb_samples(const Edge & edge)328   unsigned int nb_samples(const Edge& edge) const {
329     Edge twin = twin_edge(edge);
330     return edge.first->samples(edge.second).size()
331       + twin.first->samples(twin.second).size();
332   }
333 
collect_samples_from_edge(const Edge & edge,Sample_vector & samples)334   void collect_samples_from_edge(
335     const Edge& edge, Sample_vector& samples) const
336   {
337     const Sample_vector& edge_samples = edge.first->samples(edge.second);
338     samples.insert(samples.end(), edge_samples.begin(), edge_samples.end());
339   }
340 
collect_samples_from_vertex(Vertex_handle vertex,Sample_vector & samples,bool cleanup)341   void collect_samples_from_vertex(
342     Vertex_handle vertex, Sample_vector& samples, bool cleanup) const
343   {
344     Face_circulator fcirc = Base::incident_faces(vertex);
345     Face_circulator fend = fcirc;
346     CGAL_For_all(fcirc, fend)
347     {
348       Face_handle face = fcirc;
349       int index = face->index(vertex);
350 
351       Edge edge(face, index);
352       collect_samples_from_edge(edge, samples);
353 
354       Edge next = next_edge(edge);
355       collect_samples_from_edge(next, samples);
356 
357       Edge prev = prev_edge(edge);
358       collect_samples_from_edge(prev, samples);
359 
360       if (cleanup)
361         face->clean_all_samples();
362     }
363     Sample_* sample = vertex->sample();
364     if (sample)
365       samples.push_back(sample);
366     if (cleanup)
367       vertex->set_sample(nullptr);
368   }
369 
collect_all_samples(Sample_vector & samples)370   void collect_all_samples(Sample_vector& samples) const {
371     for (Finite_edges_iterator ei = Base::finite_edges_begin();
372         ei != Base::finite_edges_end(); ++ei) {
373       Edge edge = *ei;
374       Edge twin = twin_edge(edge);
375       collect_samples_from_edge(edge, samples);
376       collect_samples_from_edge(twin, samples);
377     }
378     for (Finite_vertices_iterator vi = Base::finite_vertices_begin();
379         vi != Base::finite_vertices_end(); ++vi) {
380       Vertex_handle v = vi;
381       Sample_* sample = v->sample();
382       if (sample)
383         samples.push_back(sample);
384     }
385   }
386 
cleanup_assignments()387   void cleanup_assignments() {
388     for (Finite_faces_iterator fi = Base::finite_faces_begin();
389         fi != Base::finite_faces_end(); ++fi) {
390       fi->clean_all_samples();
391     }
392     for (Finite_vertices_iterator vi = Base::finite_vertices_begin();
393         vi != Base::finite_vertices_end(); ++vi) {
394       vi->set_sample(nullptr);
395     }
396   }
397 
398   // COST //
399 
compute_total_cost()400   Cost_ compute_total_cost() const {
401     Cost_ sum;
402     for (Finite_edges_iterator ei = Base::finite_edges_begin();
403         ei != Base::finite_edges_end(); ++ei) {
404       Edge edge = *ei;
405       const Cost_& cost = get_cost(edge);
406       sum.update_max(cost);
407       sum.add(cost);
408     }
409     return sum;
410   }
411 
compute_cost_around_vertex(Vertex_handle vertex)412   Cost_ compute_cost_around_vertex(Vertex_handle vertex) const {
413     Cost_ inner;
414     Cost_ outer;
415     Face_circulator fcirc = Base::incident_faces(vertex);
416     Face_circulator fend = fcirc;
417     CGAL_For_all(fcirc, fend)
418     {
419       Face_handle face = fcirc;
420       int index = face->index(vertex);
421 
422       Edge edge(face, index);
423       Cost_ cost = get_cost(edge);
424       outer.update_max(cost);
425       outer.add(cost);
426 
427       edge = next_edge(edge);
428       cost = get_cost(edge);
429       inner.update_max(cost);
430       inner.add(cost);
431 
432       edge = next_edge(edge);
433       cost = get_cost(edge);
434       inner.update_max(cost);
435       inner.add(cost);
436     }
437     inner.divide(2.0);
438 
439     Cost_ sum;
440     sum.add(inner);
441     sum.add(outer);
442     sum.update_max(inner);
443     sum.update_max(outer);
444     return sum;
445   }
446 
reset_all_costs()447   void reset_all_costs() {
448     for (Finite_edges_iterator ei = Base::finite_edges_begin();
449         ei != Base::finite_edges_end(); ++ei) {
450       Edge edge = *ei;
451       update_cost(edge);
452     }
453   }
454 
update_cost(const Edge & edge)455   void update_cost(const Edge& edge) {
456     compute_mass(edge);
457     compute_edge_cost(edge);
458     compute_vertex_cost(edge);
459     select_plan(edge);
460   }
461 
compute_mass(const Edge & edge)462   void compute_mass(const Edge& edge) const {
463     FT mass = 0;
464 
465     typename Sample_vector::const_iterator it;
466     const Sample_vector& samples0 = edge.first->samples(edge.second);
467     for (it = samples0.begin(); it != samples0.end(); ++it) {
468       Sample_* sample = *it;
469       mass += sample->mass();
470     }
471 
472     Edge twin = twin_edge(edge);
473     const Sample_vector& samples1 = twin.first->samples(twin.second);
474     for (it = samples1.begin(); it != samples1.end(); ++it) {
475       Sample_* sample = *it;
476       mass += sample->mass();
477     }
478 
479     set_mass(edge, mass);
480     set_mass(twin, mass);
481   }
482 
select_plan(const Edge & edge)483   void select_plan(const Edge& edge) const {
484     // transport plan:
485     // 0 - to vertex
486     // 1 - to edge
487 
488     int plan = 0;
489     FT diff = get_vertex_minus_edge_cost(edge);
490     if (diff >= 0.0)
491       plan = 1;
492 
493     Edge twin = twin_edge(edge);
494     set_plan(edge, plan);
495     set_plan(twin, plan);
496   }
497 
compute_edge_cost(const Edge & edge)498   void compute_edge_cost(const Edge& edge) const {
499     SQueue squeue;
500     FT M = get_mass(edge);
501     FT L = get_length(edge);
502     sort_samples_from_edge(edge, squeue);
503     Cost_ cost = compute_cost_from_squeue(squeue, M, L);
504 
505     Edge twin = twin_edge(edge);
506     set_edge_cost(edge, cost);
507     set_edge_cost(twin, cost);
508   }
509 
sort_samples_from_edge(const Edge & edge,SQueue & squeue)510   void sort_samples_from_edge(const Edge& edge, SQueue& squeue) const {
511     typename Sample_vector::const_iterator it;
512     const Sample_vector& samples0 = edge.first->samples(edge.second);
513     for (it = samples0.begin(); it != samples0.end(); ++it) {
514       Sample_* sample = *it;
515       squeue.push(PSample(sample, sample->coordinate()));
516     }
517 
518     Edge twin = twin_edge(edge);
519     const Sample_vector& samples1 = twin.first->samples(twin.second);
520     for (it = samples1.begin(); it != samples1.end(); ++it) {
521       Sample_* sample = *it;
522       squeue.push(PSample(sample, 1.0 - sample->coordinate()));
523     }
524   }
525 
compute_cost_from_squeue(SQueue & squeue,const FT M,const FT L)526   Cost_ compute_cost_from_squeue(SQueue& squeue, const FT M, const FT L) const
527   {
528     if (squeue.empty())
529       return Cost_();
530     if (M == FT(0))
531       return Cost_();
532 
533     Cost_ sum;
534     FT start = 0;
535     FT coef = L / M;
536     while (!squeue.empty()) {
537       PSample psample = squeue.top();
538       squeue.pop();
539 
540       FT mass = psample.sample()->mass();
541       FT coord = psample.priority() * L;
542       FT bin = mass * coef;
543       FT center = start + FT(0.5) * bin;
544       FT pos = coord - center;
545 
546       FT norm2 = psample.sample()->distance2();
547       FT tang2 = bin * bin / 12 + pos * pos;
548 
549       sum.add(Cost_(norm2, tang2), mass);
550       sum.compute_max(norm2, tang2);
551 
552       start += bin;
553     }
554     return sum;
555   }
556 
compute_vertex_cost(const Edge & edge)557   void compute_vertex_cost(const Edge& edge) const {
558     Edge twin = twin_edge(edge);
559     const Point& ps = source_vertex(edge)->point();
560     const Point& pt = target_vertex(edge)->point();
561 
562     Sample_vector samples;
563     collect_samples_from_edge(edge, samples);
564     collect_samples_from_edge(twin, samples);
565 
566     Cost_ sum;
567     for (Sample_vector_const_iterator it = samples.begin();
568         it != samples.end(); ++it) {
569       Sample_* sample = *it;
570       FT mass = sample->mass();
571       const Point& query = sample->point();
572 
573       FT Ds = geom_traits().compute_squared_distance_2_object()(query, ps);
574       FT Dt = geom_traits().compute_squared_distance_2_object()(query, pt);
575       FT dist2 = ((std::min))(Ds, Dt);
576 
577       FT norm2 = sample->distance2();
578       FT tang2 = dist2 - norm2;
579 
580       sum.add(Cost_(norm2, tang2), mass);
581       sum.compute_max(norm2, tang2);
582     }
583     set_vertex_cost(edge, sum);
584     set_vertex_cost(twin, sum);
585   }
586 
587   // SAMPLE //
588 
589   template<class Iterator> // value_type = Sample_*
assign_samples(Iterator begin,Iterator end)590   void assign_samples(Iterator begin, Iterator end) {
591     for (Iterator it = begin; it != end; ++it) {
592       Sample_* sample = *it;
593       assign_sample(sample);
594     }
595   }
596 
597   template<class Iterator> // value_type = Sample_*
assign_samples_brute_force(Iterator begin,Iterator end)598   void assign_samples_brute_force(Iterator begin, Iterator end) {
599     for (Iterator it = begin; it != end; ++it) {
600       Sample_* sample = *it;
601       assign_sample_brute_force(sample);
602     }
603   }
604 
assign_sample(Sample_ * sample)605   bool assign_sample(Sample_* sample) {
606     const Point& point = sample->point();
607     Face_handle face = Base::locate(point);
608 
609     if (face == Face_handle() || Base::is_infinite(face)) {
610       //std::cout << "free bird" << std::endl;
611       return false;
612     }
613 
614     Vertex_handle vertex = find_nearest_vertex(point, face);
615     if (vertex != Vertex_handle()) {
616       assign_sample_to_vertex(sample, vertex);
617       return true;
618     }
619 
620     Edge edge = find_nearest_edge(point, face);
621     assign_sample_to_edge(sample, edge);
622     return true;
623   }
624 
assign_sample_brute_force(Sample_ * sample)625   bool assign_sample_brute_force(Sample_* sample) {
626     const Point& point = sample->point();
627     Face_handle nearest_face = Face_handle();
628     for (Finite_faces_iterator fi = Base::finite_faces_begin();
629         fi != Base::finite_faces_end(); ++fi) {
630       Face_handle face = fi;
631       if (face_has_point(face, point)) {
632         nearest_face = face;
633         break;
634       }
635     }
636 
637     if (nearest_face == Face_handle()) {
638       //std::cout << "free bird" << std::endl;
639       return false;
640     }
641 
642     Vertex_handle vertex = find_nearest_vertex(point, nearest_face);
643     if (vertex != Vertex_handle()) {
644       assign_sample_to_vertex(sample, vertex);
645       return true;
646     }
647 
648     Edge edge = find_nearest_edge(point, nearest_face);
649     assign_sample_to_edge(sample, edge);
650     return true;
651   }
652 
face_has_point(Face_handle face,const Point & query)653   bool face_has_point(Face_handle face, const Point& query) const {
654     for (int i = 0; i < 3; ++i) {
655       Edge edge(face, i);
656       const Point& ps = source_vertex(edge)->point();
657       const Point& pt = target_vertex(edge)->point();
658       if (!compute_triangle_ccw(ps, pt, query))
659         return false;
660     }
661     return true;
662   }
663 
find_nearest_vertex(const Point & point,Face_handle face)664   Vertex_handle find_nearest_vertex(const Point& point, Face_handle face) const
665   {
666     for (int i = 0; i < 3; ++i) {
667       Vertex_handle vi = face->vertex(i);
668       const Point& pi = vi->point();
669       if (pi == point)
670         return vi;
671     }
672     return Vertex_handle();
673   }
674 
find_nearest_edge(const Point & point,Face_handle face)675   Edge find_nearest_edge(const Point& point, Face_handle face) const {
676     Edge nearest(face, 0);
677     FT min_dist2 = compute_distance2(point, get_segment(nearest));
678     for (int i = 1; i < 3; ++i) {
679       Edge edge(face, i);
680       Segment segment = get_segment(edge);
681       FT dist2 = compute_distance2(point, segment);
682       if (dist2 < min_dist2) {
683         min_dist2 = dist2;
684         nearest = edge;
685       }
686     }
687 
688     return nearest;
689   }
690 
assign_sample_to_vertex(Sample_ * sample,Vertex_handle vertex)691   void assign_sample_to_vertex(Sample_* sample, Vertex_handle vertex) const {
692     /*if (vertex->sample()) {
693       std::cout << "assign to vertex: vertex already has sample"
694           << std::endl;
695     }*/
696 
697     sample->distance2() = FT(0);
698     sample->coordinate() = FT(0);
699     vertex->set_sample(sample);
700   }
701 
assign_sample_to_edge(Sample_ * sample,const Edge & edge)702   void assign_sample_to_edge(Sample_* sample, const Edge& edge) const {
703     Segment segment = get_segment(edge);
704     const Point& query = sample->point();
705     sample->distance2() = compute_distance2(query, segment);
706     sample->coordinate() = compute_coordinate(query, segment);
707     edge.first->add_sample(edge.second, sample);
708   }
709 
compute_distance2(const Point & query,const Segment & segment)710   FT compute_distance2(const Point& query, const Segment& segment) const {
711 
712     if (geom_traits().orientation_2_object()(segment.source(), segment.target(), query) == COLLINEAR)
713       return FT(0);
714 
715     Line line = geom_traits().construct_line_2_object()(segment);
716     return geom_traits().compute_squared_distance_2_object()(query, line);
717   }
718 
compute_coordinate(const Point & q,const Segment & segment)719   FT compute_coordinate(const Point& q, const Segment& segment) const {
720     const Point& p0 = segment.source();
721     const Point& p1 = segment.target();
722     Vector p0p1 = geom_traits().construct_vector_2_object()(p0, p1);
723     Vector p0q  = geom_traits().construct_vector_2_object()(p0, q);
724 
725     FT t = geom_traits().compute_scalar_product_2_object()(p0q, p0p1)
726          / geom_traits().compute_scalar_product_2_object()(p0p1, p0p1);
727     return t; // [0,1]
728   }
729 
730   // SIGNED DISTANCE //
731 
732   // signed distance from line(a,b) to point t
signed_distance(Vertex_handle a,Vertex_handle b,Vertex_handle t)733   FT signed_distance(Vertex_handle a, Vertex_handle b,
734       Vertex_handle t) const {
735     const Point& pa = a->point();
736     const Point& pb = b->point();
737     const Point& pt = t->point();
738     return compute_signed_distance(pa, pb, pt);
739   }
740 
741   // signed distance from line(a,b) to point t
compute_signed_distance(const Point & pa,const Point & pb,const Point & pt)742   FT compute_signed_distance(
743     const Point& pa, const Point& pb, const Point& pt) const
744   {
745     if (pt == pa)
746       return FT(0);
747     if (pt == pb)
748       return FT(0);
749     if (pa == pb)
750       return CGAL::approximate_sqrt(geom_traits().compute_squared_distance_2_object()(pa, pt));
751 
752     Vector vab = geom_traits().construct_vector_2_object()(pa, pb);
753     // Normalize vab
754     vab = geom_traits().construct_scaled_vector_2_object()(
755       vab,
756       FT(1) / CGAL::approximate_sqrt(geom_traits().compute_squared_length_2_object()(vab)));
757     Vector vab90 = geom_traits().construct_vector_2_object()(-vab.y(), vab.x());
758     Vector vat = geom_traits().construct_vector_2_object()(pa, pt);
759     return geom_traits().compute_scalar_product_2_object()(vat, vab90);
760   }
761 
762   // signed distance from t to the intersection of line(a,b) and line(t,s)
763   // the pair::first is false if sign==-1 and true otherwise
764   std::pair<bool,boost::optional<FT> >
signed_distance_from_intersection(Vertex_handle a,Vertex_handle b,Vertex_handle t,Vertex_handle s)765   signed_distance_from_intersection(Vertex_handle a, Vertex_handle b,
766       Vertex_handle t, Vertex_handle s) const {
767     const Point& pa = a->point();
768     const Point& pb = b->point();
769     const Point& pt = t->point();
770     const Point& ps = s->point();
771     return compute_signed_distance_from_intersection(pa, pb, pt, ps);
772   }
773 
774   // signed distance from t to the intersection of line(a,b) and line(t,s)
775   // the pair::first is false if sign==-1 and true otherwise
776   std::pair<bool,boost::optional<FT> >
compute_signed_distance_from_intersection(const Point & pa,const Point & pb,const Point & pt,const Point & ps)777   compute_signed_distance_from_intersection(
778     const Point& pa, const Point& pb, const Point& pt, const Point& ps) const
779   {
780     FT Dabt = compute_signed_distance(pa, pb, pt);
781     if (Dabt == FT(0))
782       return std::make_pair(true,boost::make_optional(FT(0)));
783 
784     Line lab = geom_traits().construct_line_2_object()(
785       pa, geom_traits().construct_vector_2_object()(pa, pb));
786     Line lts = geom_traits().construct_line_2_object()(
787       pt, geom_traits().construct_vector_2_object()(pt, ps));
788 
789     boost::optional<FT> Dqt;
790     const auto result = intersection(lab, lts);
791     if (result)
792     {
793       const Point* iq = boost::get<Point>(&(*result));
794       if (iq)
795         Dqt = CGAL::approximate_sqrt(geom_traits().compute_squared_distance_2_object()(*iq, pt));
796     }
797 
798     return std::make_pair( (Dabt < FT(0) ? false : true) ,Dqt );
799   }
800 
is_triangle_ccw(Vertex_handle a,Vertex_handle b,Vertex_handle c)801   bool is_triangle_ccw(Vertex_handle a, Vertex_handle b, Vertex_handle c) const
802   {
803     const Point& pa = a->point();
804     const Point& pb = b->point();
805     const Point& pc = c->point();
806     return compute_triangle_ccw(pa, pb, pc);
807   }
808 
compute_triangle_ccw(const Point & pa,const Point & pb,const Point & pc)809   bool compute_triangle_ccw(
810     const Point& pa, const Point& pb, const Point& pc) const
811   {
812     return geom_traits().orientation_2_object()(pa,pb,pc) != RIGHT_TURN;
813   }
814 
815   // COMBINATORIAL TESTS //
816 
817   // (a,b) is cyclic if (a,b,c) and (a,c,b) exist
is_edge_cyclic(const Edge & edge)818   bool is_edge_cyclic(const Edge& edge) const {
819     Vertex_handle f = opposite_vertex(edge);
820     Vertex_handle b = opposite_vertex(twin_edge(edge));
821     return (f == b);
822   }
823 
824   // b from (a,b) is cyclic if (a,b,c) and (b,a,c) exist
is_target_cyclic(const Edge & edge)825   bool is_target_cyclic(const Edge& edge) const {
826     if (!is_edge_cyclic(edge))
827       return false;
828 
829     Edge twin = twin_edge(edge);
830     Edge prev = prev_edge(twin);
831     Face_handle fp = prev.first->neighbor(prev.second);
832     Face_handle ft = twin.first->neighbor(twin.second);
833     return (fp == ft);
834   }
835 
is_flippable(const Edge & edge)836   bool is_flippable(const Edge& edge) const {
837     Edge twin = twin_edge(edge);
838     if (Base::is_infinite(twin.first))
839       return false;
840     if (Base::is_infinite(edge.first))
841       return false;
842 
843     Vertex_handle vs = source_vertex(edge);
844     Vertex_handle vt = target_vertex(edge);
845     Vertex_handle vf = opposite_vertex(edge);
846     Vertex_handle vb = opposite_vertex(twin);
847 
848     return is_triangle_ccw(vs, vb, vf) && is_triangle_ccw(vt, vf, vb);
849   }
850 
is_collapsible(const Edge & edge)851   bool is_collapsible(const Edge& edge) const {
852     return check_link_test(edge) && check_kernel_test(edge);
853   }
854 
check_link_test(const Edge & edge)855   bool check_link_test(const Edge& edge) const {
856     Vertex_handle s = source_vertex(edge);
857     Vertex_handle t = target_vertex(edge);
858 
859     if (s == t)
860       return false;
861     typename Vertex_handle_set::const_iterator it;
862 
863     Vertex_handle_set svertices;
864     get_vertices_from_vertex_link(s, svertices);
865 
866     Vertex_handle_set tvertices;
867     get_vertices_from_vertex_link(t, tvertices);
868 
869     // link(s) inter link(t)
870     Vertex_handle_set ivertices;
871     for (it = svertices.begin(); it != svertices.end(); ++it) {
872       Vertex_handle v = *it;
873       if (tvertices.find(v) != tvertices.end())
874         ivertices.insert(v);
875     }
876 
877     Vertex_handle_set evertices;
878     get_vertices_from_edge_link(edge, evertices);
879 
880     // link(edge) =? link(s) inter link(t)
881     if (evertices.size() != ivertices.size())
882       return false;
883 
884     for (it = evertices.begin(); it != evertices.end(); ++it) {
885       Vertex_handle v = *it;
886       if (ivertices.find(v) == ivertices.end())
887         return false;
888     }
889     return true;
890   }
891 
check_kernel_test(const Edge & edge)892   bool check_kernel_test(const Edge& edge) const {
893     Vertex_handle s = source_vertex(edge);
894     Vertex_handle t = target_vertex(edge);
895 
896     Edge_vector hull;
897     hull.reserve(16);
898     get_edges_from_star_minus_link(s, hull);
899     return is_in_kernel(t->point(), hull.begin(), hull.end());
900   }
901 
902   template<class Iterator> // value_type = Edge
is_in_kernel(const Point & query,Iterator begin,Iterator end)903   bool is_in_kernel(const Point& query, Iterator begin, Iterator end) const {
904     for (Iterator it = begin; it != end; ++it) {
905       Edge edge = *it;
906       const Point& pa = source_vertex(edge)->point();
907       const Point& pb = target_vertex(edge)->point();
908       if (!compute_triangle_ccw(pa, pb, query))
909         return false;
910     }
911     return true;
912   }
913 
check_validity_test()914   bool check_validity_test () const
915   {
916     for(Finite_faces_iterator it = Base::finite_faces_begin();
917         it != Base::finite_faces_end(); it++)
918     {
919       typename Traits_::Orientation s
920         = orientation(it->vertex(0)->point(),
921                       it->vertex(1)->point(),
922                       it->vertex(2)->point());
923       if (s != LEFT_TURN)
924         return false;
925     }
926 
927     return true;
928   }
929 
930   // COLLAPSE //
931 
932   // (s,a,b) + (s,b,c) -> (s,a,c) + (a,b,c)
933   // st = (source,target) from 'make_collapsible'
934   // return (a,c)
935   Edge flip(const Edge& sb, Edge& st, int /*verbose*/ = 0) {
936     Vertex_handle t = target_vertex(st);
937 
938     Edge sc = twin_edge(prev_edge(sb));
939     Base::tds().flip(sb.first, sb.second);
940     Edge ac = prev_edge(twin_edge(sc));
941 
942     Vertex_handle a = source_vertex(ac);
943     if (a == t)
944       st = prev_edge(ac);
945 
946     return ac;
947   }
948 
949   void collapse(const Edge& edge, int /*verbose*/ = 0) {
950     if (is_edge_cyclic(edge)) {
951       collapse_cyclic_edge(edge);
952       return;
953     }
954 
955     Edge twin = twin_edge(edge);
956     Base::tds().join_vertices(twin);
957   }
958 
959   // (a,b,c) + (c,b,a) + (a,c,i) + (c,a,j) ->
960   // (a,c,i) + (c,a,j)
961   void collapse_cyclic_edge(const Edge& bc, int verbose = 0) {
962     if (verbose > 1)
963       std::cout << "collapse_cyclic_edge ... ";
964 
965     Edge cb = twin_edge(bc);
966     Face_handle abc = bc.first;
967     Face_handle cba = cb.first;
968 
969     Vertex_handle b = source_vertex(bc);
970     Vertex_handle c = target_vertex(bc);
971     Vertex_handle a = opposite_vertex(bc);
972 
973     Edge ac = twin_edge(next_edge(bc));
974     Edge ca = twin_edge(prev_edge(cb));
975 
976     a->set_face(ac.first);
977     c->set_face(ca.first);
978     ac.first->set_neighbor(ac.second, ca.first);
979     ca.first->set_neighbor(ca.second, ac.first);
980 
981     this->delete_face(abc);
982     this->delete_face(cba);
983     this->delete_vertex(b);
984 
985     if (verbose > 1)
986       std::cout << "done" << std::endl;
987   }
988 
print_edge(Rec_edge_2 edge)989   void print_edge(Rec_edge_2 edge) const {
990     int i = ((edge).edge()).second;
991     Point a = ((edge).edge()).first->vertex((i+1)%3)->point();
992     Point b = ((edge).edge()).first->vertex((i+2)%3)->point();
993     std::cout <<"( " << (edge).priority()  <<  ") ( " << a << " , " << b << " )" << std::endl;
994   }
995 
is_p_infinity(const std::pair<bool,boost::optional<FT>> & p)996   bool is_p_infinity(const std::pair<bool,boost::optional<FT> >& p) const
997   {
998     return p.first && p.second==boost::none;
999   }
1000 
is_m_infinity(const std::pair<bool,boost::optional<FT>> & p)1001   bool is_m_infinity(const std::pair<bool,boost::optional<FT> >& p) const
1002   {
1003     return !p.first && p.second==boost::none;
1004   }
1005 
is_infinity(const std::pair<bool,boost::optional<FT>> & p)1006   bool is_infinity(const std::pair<bool,boost::optional<FT> >& p) const
1007   {
1008     return p.second==boost::none;
1009   }
1010 
m_infinity()1011   std::pair<bool,boost::optional<FT> > m_infinity() const
1012   {
1013     return std::pair<bool,boost::optional<FT> >(false,boost::optional<FT>());
1014   }
1015 
1016   template <class Iterator> // value_type = Edge
1017   bool make_collapsible(Edge& edge, Iterator begin, Iterator end, int verbose = 0)
1018   {
1019     Vertex_handle source = source_vertex(edge);
1020     Vertex_handle target = target_vertex(edge);
1021 
1022     MultiIndex multi_ind;
1023     for (Iterator it = begin; it != end; ++it)
1024     {
1025       Edge ab = twin_edge(*it);
1026       Vertex_handle a = source_vertex(ab);
1027       Vertex_handle b = target_vertex(ab);
1028       std::pair<bool,boost::optional<FT> > D = signed_distance_from_intersection(a, b, target, source);
1029       if (!D.first ) {
1030         CGAL_assertion(D.second!=boost::none);
1031         multi_ind.insert(Rec_edge_2(ab, *D.second));
1032       }
1033     }
1034 
1035     int nb_flips = 0;
1036     while (!multi_ind.empty())
1037     {
1038       Rec_edge_2 pedge = *(multi_ind.template get<1>()).begin();
1039       FT Dbc = pedge.priority();
1040       Edge bc = pedge.edge();
1041       (multi_ind.template get<0>()).erase(pedge);
1042 
1043       Edge sb = prev_edge(bc);
1044       Edge ab = prev_edge(twin_edge(sb));
1045       Edge sc = twin_edge(next_edge(bc));
1046       Edge cd = next_edge(sc);
1047 
1048       Vertex_handle a = source_vertex(ab);
1049       Vertex_handle b = source_vertex(bc);
1050       Vertex_handle c = target_vertex(bc);
1051       Vertex_handle d = target_vertex(cd);
1052 
1053       std::pair<bool,boost::optional<FT> > Dac=m_infinity();
1054       if (a != c && is_triangle_ccw(a, b, c))
1055         Dac = signed_distance_from_intersection(a, c, target, source);
1056 
1057       std::pair<bool,boost::optional<FT> > Dbd=m_infinity();
1058       if (b != d && is_triangle_ccw(b, c, d))
1059         Dbd = signed_distance_from_intersection(b, d, target, source);
1060 
1061       if ( is_m_infinity(Dac) && is_m_infinity(Dbd) )
1062       {
1063         if (verbose > 1)
1064           std::cerr << "--- No flips available ---"  << std::endl;
1065         return false;
1066       }
1067 
1068       FT value = Dbc <= 0 ? FT(1) : 2*Dbc; // value used if Dbd or Dac are +infinity
1069       if ( !is_infinity(Dac) )
1070       {
1071         if ( !is_infinity(Dbd))
1072           value = (std::max)(*Dac.second * (Dac.first?1:-1),
1073                              *Dbd.second * (Dbd.first?1:-1) );
1074         else
1075           if ( !is_p_infinity(Dbd) )
1076             value = *Dac.second * (Dac.first?1:-1);
1077       }
1078       else
1079         if ( !is_infinity(Dbd) && !is_p_infinity(Dac))
1080           value = *Dbd.second * (Dbd.first?1:-1);
1081 
1082       // if ( max(Dac,Dbd)+CGAL_EPS < Dbc )
1083       if (value + CGAL_EPS < Dbc)
1084       {
1085                         /*
1086         std::cerr.precision(10);
1087         std::cerr << "--- Flip makes kernel worse ---" << std::endl;
1088         std::cerr << Dac << " or " << Dbd << " vs " << Dbc << std::endl;
1089         std::cerr << "a: " << a->point() << std::endl;
1090         std::cerr << "b: " << b->point() << std::endl;
1091         std::cerr << "c: " << c->point() << std::endl;
1092         std::cerr << "d: " << d->point() << std::endl;
1093         std::cerr << "t: " << target->point() << std::endl;
1094         std::cerr << "diff = " << Dbc - (std::max)(Dac, Dbd) << std::endl;
1095                                 */
1096         return false;
1097       }
1098 
1099       // if (Dac > Dbd)
1100       if (is_p_infinity(Dac) || is_m_infinity(Dbd) ||
1101           (!is_p_infinity(Dbd) && !is_m_infinity(Dac)
1102            && *Dac.second * (Dac.first?1:-1) > *Dbd.second * (Dbd.first?1:-1)))
1103       {
1104         (multi_ind.template get<0>()).erase(Rec_edge_2(ab));
1105 
1106         Edge ac = flip(sb, edge, verbose);
1107         if (!Dac.first) {
1108           multi_ind.insert(Rec_edge_2(ac, - *Dac.second));
1109         }
1110       }
1111       else
1112       {
1113         (multi_ind.template get<0>()).erase(Rec_edge_2(cd));
1114         Edge bd = flip(sc, edge, verbose);
1115         if (!Dbd.first) {
1116           multi_ind.insert(Rec_edge_2(bd, - *Dbd.second));
1117         }
1118       }
1119       nb_flips++;
1120     }
1121 
1122     if (verbose > 1)
1123       std::cerr  << "Nb flips: "  << nb_flips << std::endl;
1124 
1125     return true;
1126   }
1127 };
1128 
1129 } } //namespace CGAL
1130 
1131 #undef CGAL_EPS
1132 
1133 #endif // CGAL_RECONSTRUCTION_TRIANGULATION_2_H
1134