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