1 // Copyright (c) 2005,2006,2007,2009,2010,2011 Tel-Aviv University (Israel). 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/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h $ 7 // $Id: Arr_circle_segment_traits_2.h 59a0da4 2021-05-19T17:23:53+02:00 Laurent Rineau 8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial 9 // 10 // Author(s): Ron Wein <wein@post.tau.ac.il> 11 // Baruch Zukerman <baruchzu@post.tau.ac.il> 12 // Waqar Khan <wkhan@mpi-inf.mpg.de> 13 // Efi Fogel <efifogel@gmail.com> 14 15 #ifndef CGAL_ARR_CIRCLE_SEGMENT_TRAITS_2_H 16 #define CGAL_ARR_CIRCLE_SEGMENT_TRAITS_2_H 17 18 #include <CGAL/license/Arrangement_on_surface_2.h> 19 20 #include <CGAL/disable_warnings.h> 21 22 /*! \file 23 * The header file for the Arr_circle_segment_traits_2<Kenrel> class. 24 */ 25 26 #include <CGAL/tags.h> 27 #include <CGAL/Arr_tags.h> 28 #include <CGAL/Arr_geometry_traits/Circle_segment_2.h> 29 30 #include <fstream> 31 #include <atomic> 32 33 namespace CGAL { 34 35 /*! \class 36 * A traits class for maintaining an arrangement of circles. 37 */ 38 template <typename Kernel_, bool Filter = true> 39 class Arr_circle_segment_traits_2 { 40 public: 41 typedef Kernel_ Kernel; 42 typedef typename Kernel::FT NT; 43 typedef typename Kernel::Point_2 Rational_point_2; 44 typedef typename Kernel::Segment_2 Rational_segment_2; 45 typedef typename Kernel::Circle_2 Rational_circle_2; 46 typedef _One_root_point_2<NT, Filter> Point_2; 47 typedef typename Point_2::CoordNT CoordNT; 48 typedef _Circle_segment_2<Kernel, Filter> Curve_2; 49 typedef _X_monotone_circle_segment_2<Kernel, Filter> X_monotone_curve_2; 50 typedef unsigned int Multiplicity; 51 typedef Arr_circle_segment_traits_2<Kernel, Filter> Self; 52 53 // Category tags: 54 typedef Tag_true Has_left_category; 55 typedef Tag_true Has_merge_category; 56 typedef Tag_false Has_do_intersect_category; 57 58 typedef Arr_oblivious_side_tag Left_side_category; 59 typedef Arr_oblivious_side_tag Bottom_side_category; 60 typedef Arr_oblivious_side_tag Top_side_category; 61 typedef Arr_oblivious_side_tag Right_side_category; 62 63 protected: 64 // Type definition for the intersection points mapping. 65 typedef typename X_monotone_curve_2::Intersection_map Intersection_map; 66 67 mutable Intersection_map inter_map; // Mapping pairs of curve IDs to their 68 // intersection points. 69 bool m_use_cache; 70 71 public: 72 /*! Default constructor. */ 73 Arr_circle_segment_traits_2 (bool use_intersection_caching = false) : m_use_cache(use_intersection_caching)74 m_use_cache(use_intersection_caching) 75 {} 76 77 /*! Get the next curve index. */ get_index()78 static unsigned int get_index () 79 { 80 #ifdef CGAL_NO_ATOMIC 81 static unsigned int index; 82 #else 83 static std::atomic<unsigned int> index; 84 #endif 85 return (++index); 86 } 87 88 /// \name Basic functor definitions. 89 //@{ 90 91 class Compare_x_2 92 { 93 public: 94 /*! 95 * Compare the x-coordinates of two points. 96 * \param p1 The first point. 97 * \param p2 The second point. 98 * \return LARGER if x(p1) > x(p2); 99 * SMALLER if x(p1) < x(p2); 100 * EQUAL if x(p1) = x(p2). 101 */ operator()102 Comparison_result operator() (const Point_2& p1, const Point_2& p2) const 103 { 104 if (p1.identical (p2)) 105 return (EQUAL); 106 107 return (CGAL::compare (p1.x(), p2.x())); 108 } 109 }; 110 111 /*! Get a Compare_x_2 functor object. */ compare_x_2_object()112 Compare_x_2 compare_x_2_object () const 113 { 114 return Compare_x_2(); 115 } 116 117 class Compare_xy_2 118 { 119 public: 120 /*! 121 * Compares two points lexigoraphically: by x, then by y. 122 * \param p1 The first point. 123 * \param p2 The second point. 124 * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); 125 * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); 126 * EQUAL if the two points are equal. 127 */ operator()128 Comparison_result operator() (const Point_2& p1, const Point_2& p2) const 129 { 130 if (p1.identical (p2)) 131 return (EQUAL); 132 133 Comparison_result res = CGAL::compare (p1.x(), p2.x()); 134 135 if (res != EQUAL) 136 return (res); 137 138 return (CGAL::compare (p1.y(), p2.y())); 139 } 140 }; 141 142 /*! Get a Compare_xy_2 functor object. */ compare_xy_2_object()143 Compare_xy_2 compare_xy_2_object () const 144 { 145 return Compare_xy_2(); 146 } 147 148 class Construct_min_vertex_2 149 { 150 public: 151 /*! 152 * Get the left endpoint of the x-monotone curve (segment). 153 * \param cv The curve. 154 * \return The left endpoint. 155 */ operator()156 const Point_2& operator() (const X_monotone_curve_2 & cv) const 157 { 158 return (cv.left()); 159 } 160 }; 161 162 /*! Get a Construct_min_vertex_2 functor object. */ construct_min_vertex_2_object()163 Construct_min_vertex_2 construct_min_vertex_2_object () const 164 { 165 return Construct_min_vertex_2(); 166 } 167 168 class Construct_max_vertex_2 169 { 170 public: 171 /*! 172 * Get the right endpoint of the x-monotone curve (segment). 173 * \param cv The curve. 174 * \return The right endpoint. 175 */ operator()176 const Point_2& operator() (const X_monotone_curve_2 & cv) const 177 { 178 return (cv.right()); 179 } 180 }; 181 182 /*! Get a Construct_max_vertex_2 functor object. */ construct_max_vertex_2_object()183 Construct_max_vertex_2 construct_max_vertex_2_object () const 184 { 185 return Construct_max_vertex_2(); 186 } 187 188 class Is_vertical_2 189 { 190 public: 191 /*! 192 * Check whether the given x-monotone curve is a vertical segment. 193 * \param cv The curve. 194 * \return (true) if the curve is a vertical segment; (false) otherwise. 195 */ operator()196 bool operator() (const X_monotone_curve_2& cv) const 197 { 198 return (cv.is_vertical()); 199 } 200 }; 201 202 /*! Get an Is_vertical_2 functor object. */ is_vertical_2_object()203 Is_vertical_2 is_vertical_2_object () const 204 { 205 return Is_vertical_2(); 206 } 207 208 class Compare_y_at_x_2 209 { 210 public: 211 /*! 212 * Return the location of the given point with respect to the input curve. 213 * \param cv The curve. 214 * \param p The point. 215 * \pre p is in the x-range of cv. 216 * \return SMALLER if y(p) < cv(x(p)), i.e. the point is below the curve; 217 * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; 218 * EQUAL if p lies on the curve. 219 */ operator()220 Comparison_result operator() (const Point_2& p, 221 const X_monotone_curve_2& cv) const 222 { 223 CGAL_precondition (cv.is_in_x_range (p)); 224 225 return (cv.point_position (p)); 226 } 227 }; 228 229 /*! Get a Compare_y_at_x_2 functor object. */ compare_y_at_x_2_object()230 Compare_y_at_x_2 compare_y_at_x_2_object () const 231 { 232 return Compare_y_at_x_2(); 233 } 234 235 class Compare_y_at_x_right_2 236 { 237 public: 238 /*! 239 * Compares the y value of two x-monotone curves immediately to the right 240 * of their intersection point. 241 * \param cv1 The first curve. 242 * \param cv2 The second curve. 243 * \param p The intersection point. 244 * \pre The point p lies on both curves, and both of them must be also be 245 * defined (lexicographically) to its right. 246 * \return The relative position of cv1 with respect to cv2 immdiately to 247 * the right of p: SMALLER, LARGER or EQUAL. 248 */ operator()249 Comparison_result operator() (const X_monotone_curve_2& cv1, 250 const X_monotone_curve_2& cv2, 251 const Point_2& p) const 252 { 253 // Make sure that p lies on both curves, and that both are defined to its 254 // right (so their right endpoint is lexicographically larger than p). 255 CGAL_precondition (cv1.point_position (p) == EQUAL && 256 cv2.point_position (p) == EQUAL); 257 258 if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) && 259 (CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) 260 { //both cv1 and cv2 are vertical 261 CGAL_precondition (!(cv1.right()).equals(p) && !(cv2.right()).equals(p)); 262 } 263 else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) != EQUAL) && 264 (CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) 265 { //only cv1 is vertical 266 CGAL_precondition (!(cv1.right()).equals(p)); 267 } 268 else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) && 269 (CGAL::compare (cv2.left().x(),cv2.right().x()) != EQUAL)) 270 { //only cv2 is vertical 271 CGAL_precondition (!(cv2.right()).equals(p)); 272 } 273 else 274 { //both cv1 and cv2 are non vertical 275 CGAL_precondition (CGAL::compare (cv1.right().x(),p.x()) == LARGER && 276 CGAL::compare (cv2.right().x(),p.x()) == LARGER); 277 } 278 // Compare the two curves immediately to the right of p: 279 return (cv1.compare_to_right (cv2, p)); 280 } 281 }; 282 283 /*! Get a Compare_y_at_x_right_2 functor object. */ compare_y_at_x_right_2_object()284 Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const 285 { 286 return Compare_y_at_x_right_2(); 287 } 288 289 class Compare_y_at_x_left_2 290 { 291 public: 292 /*! 293 * Compares the y value of two x-monotone curves immediately to the left 294 * of their intersection point. 295 * \param cv1 The first curve. 296 * \param cv2 The second curve. 297 * \param p The intersection point. 298 * \pre The point p lies on both curves, and both of them must be also be 299 * defined (lexicographically) to its left. 300 * \return The relative position of cv1 with respect to cv2 immdiately to 301 * the left of p: SMALLER, LARGER or EQUAL. 302 */ operator()303 Comparison_result operator() (const X_monotone_curve_2& cv1, 304 const X_monotone_curve_2& cv2, 305 const Point_2& p) const 306 { 307 // Make sure that p lies on both curves, and that both are defined to its 308 // left (so their left endpoint is lexicographically smaller than p). 309 310 CGAL_precondition (cv1.point_position (p) == EQUAL && 311 cv2.point_position (p) == EQUAL); 312 313 if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) && 314 (CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) 315 { //both cv1 and cv2 are vertical 316 CGAL_precondition (!(cv1.left()).equals(p) && !(cv2.left()).equals(p)); 317 } 318 else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) != EQUAL) && 319 (CGAL::compare (cv2.left().x(),cv2.right().x()) == EQUAL)) 320 { //only cv1 is vertical 321 CGAL_precondition (!(cv1.left()).equals(p)); 322 } 323 else if ((CGAL::compare (cv1.left().x(),cv1.right().x()) == EQUAL) && 324 (CGAL::compare (cv2.left().x(),cv2.right().x()) != EQUAL)) 325 { //only cv2 is vertical 326 CGAL_precondition (!(cv2.left()).equals(p)); 327 } 328 else 329 { //both cv1 and cv2 are non vertical 330 CGAL_precondition (CGAL::compare (cv1.left().x(),p.x()) == SMALLER && 331 CGAL::compare (cv2.left().x(),p.x()) == SMALLER); 332 } 333 // Compare the two curves immediately to the left of p: 334 return (cv1.compare_to_left (cv2, p)); 335 } 336 }; 337 338 /*! Get a Compare_y_at_x_left_2 functor object. */ compare_y_at_x_left_2_object()339 Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const 340 { 341 return Compare_y_at_x_left_2(); 342 } 343 344 class Equal_2 345 { 346 public: 347 /*! 348 * Check if the two x-monotone curves are the same (have the same graph). 349 * \param cv1 The first curve. 350 * \param cv2 The second curve. 351 * \return (true) if the two curves are the same; (false) otherwise. 352 */ operator()353 bool operator() (const X_monotone_curve_2& cv1, 354 const X_monotone_curve_2& cv2) const 355 { 356 if (&cv1 == &cv2) 357 return (true); 358 359 return (cv1.equals (cv2)); 360 } 361 362 /*! 363 * Check if the two points are the same. 364 * \param p1 The first point. 365 * \param p2 The second point. 366 * \return (true) if the two point are the same; (false) otherwise. 367 */ operator()368 bool operator() (const Point_2& p1, const Point_2& p2) const 369 { 370 return (p1.equals (p2)); 371 } 372 }; 373 374 /*! Get an Equal_2 functor object. */ equal_2_object()375 Equal_2 equal_2_object () const 376 { 377 return Equal_2(); 378 } 379 //@} 380 381 /// \name Intersections, subdivisions, and mergings 382 //@{ 383 384 /*! \class 385 * A functor for subdividing a curve into x-monotone curves. 386 */ 387 class Make_x_monotone_2 { 388 private: 389 typedef Arr_circle_segment_traits_2<Kernel_, Filter> Self; 390 391 bool m_use_cache; 392 393 public: m_use_cache(use_cache)394 Make_x_monotone_2(bool use_cache = false) : m_use_cache(use_cache) {} 395 396 /*! Subdivide a given circular arc or line segment into x-monotone subcurves 397 * and insert them to a given output iterator. 398 * \param cv the curve. 399 * \param oi the output iterator for the result. Its dereference type is a 400 * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 401 * objects. 402 * \return the past-the-end iterator. 403 */ 404 template <typename OutputIterator> operator()405 OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const 406 { 407 typedef boost::variant<Point_2, X_monotone_curve_2> 408 Make_x_monotone_result; 409 410 // Increment the serial number of the curve cv, which will serve as its 411 // unique identifier. 412 unsigned int index = 0; 413 if (m_use_cache) index = Self::get_index(); 414 415 if (cv.orientation() == COLLINEAR) { 416 // The curve is a line segment. 417 *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv.supporting_line(), 418 cv.source(), 419 cv.target(), 420 index)); 421 return oi; 422 } 423 424 // Check the case of a degenrate circle (a point). 425 const typename Kernel::Circle_2& circ = cv.supporting_circle(); 426 CGAL::Sign sign_rad = CGAL::sign (circ.squared_radius()); 427 CGAL_precondition (sign_rad != NEGATIVE); 428 429 if (sign_rad == ZERO) { 430 // Create an isolated point. 431 *oi++ = Make_x_monotone_result(Point_2(circ.center().x(), 432 circ.center().y())); 433 return oi; 434 } 435 436 // The curve is circular: compute the to vertical tangency points 437 // of the supporting circle. 438 Point_2 vpts[2]; 439 unsigned int n_vpts = cv.vertical_tangency_points (vpts); 440 441 if (cv.is_full()) { 442 CGAL_assertion (n_vpts == 2); 443 444 // Subdivide the circle into two arcs (an upper and a lower half). 445 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 446 vpts[0], vpts[1], 447 cv.orientation(), 448 index)); 449 450 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 451 vpts[1], vpts[0], 452 cv.orientation(), 453 index)); 454 } 455 else { 456 // Act according to the number of vertical tangency points. 457 if (n_vpts == 2) { 458 // Subdivide the circular arc into three x-monotone arcs. 459 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 460 cv.source(), vpts[0], 461 cv.orientation(), 462 index)); 463 464 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 465 vpts[0], vpts[1], 466 cv.orientation(), 467 index)); 468 469 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 470 vpts[1], 471 cv.target(), 472 cv.orientation(), 473 index)); 474 } 475 else if (n_vpts == 1) { 476 // Subdivide the circular arc into two x-monotone arcs. 477 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 478 cv.source(), 479 vpts[0], 480 cv.orientation(), 481 index)); 482 483 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 484 vpts[0], 485 cv.target(), 486 cv.orientation(), 487 index)); 488 } 489 else { 490 CGAL_assertion(n_vpts == 0); 491 492 // The arc is already x-monotone: 493 *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, 494 cv.source(), 495 cv.target(), 496 cv.orientation(), 497 index)); 498 } 499 } 500 501 return oi; 502 } 503 }; 504 505 /*! Get a Make_x_monotone_2 functor object. */ make_x_monotone_2_object()506 Make_x_monotone_2 make_x_monotone_2_object() const 507 { return Make_x_monotone_2(m_use_cache); } 508 509 class Split_2 510 { 511 public: 512 513 /*! 514 * Split a given x-monotone curve at a given point into two sub-curves. 515 * \param cv The curve to split 516 * \param p The split point. 517 * \param c1 Output: The left resulting subcurve (p is its right endpoint). 518 * \param c2 Output: The right resulting subcurve (p is its left endpoint). 519 * \pre p lies on cv but is not one of its end-points. 520 */ operator()521 void operator() (const X_monotone_curve_2& cv, const Point_2& p, 522 X_monotone_curve_2& c1, X_monotone_curve_2& c2) const 523 { 524 CGAL_precondition (cv.point_position(p)==EQUAL && 525 ! p.equals (cv.source()) && 526 ! p.equals (cv.target())); 527 528 cv.split (p, c1, c2); 529 return; 530 } 531 }; 532 533 /*! Get a Split_2 functor object. */ split_2_object()534 Split_2 split_2_object () const 535 { 536 return Split_2(); 537 } 538 539 class Intersect_2 { 540 private: 541 Intersection_map& _inter_map; // The map of intersection points. 542 543 public: 544 /*! Constructor. */ Intersect_2(Intersection_map & map)545 Intersect_2(Intersection_map& map) : _inter_map(map) {} 546 547 /*! Find the intersections of the two given curves and insert them to the 548 * given output iterator. As two segments may itersect only once, only a 549 * single will be contained in the iterator. 550 * \param cv1 The first curve. 551 * \param cv2 The second curve. 552 * \param oi The output iterator. 553 * \return The past-the-end iterator. 554 */ 555 template <typename OutputIterator> operator()556 OutputIterator operator()(const X_monotone_curve_2& cv1, 557 const X_monotone_curve_2& cv2, 558 OutputIterator oi) const 559 { return (cv1.intersect(cv2, oi, &_inter_map)); } 560 }; 561 562 /*! Get an Intersect_2 functor object. */ intersect_2_object()563 Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); } 564 565 class Are_mergeable_2 566 { 567 public: 568 /*! 569 * Check whether it is possible to merge two given x-monotone curves. 570 * \param cv1 The first curve. 571 * \param cv2 The second curve. 572 * \return (true) if the two curves are mergeable - if they are supported 573 * by the same line and share a common endpoint; (false) otherwise. 574 */ operator()575 bool operator() (const X_monotone_curve_2& cv1, 576 const X_monotone_curve_2& cv2) const 577 { 578 return (cv1.can_merge_with (cv2)); 579 } 580 }; 581 582 /*! Get an Are_mergeable_2 functor object. */ are_mergeable_2_object()583 Are_mergeable_2 are_mergeable_2_object () const 584 { 585 return Are_mergeable_2(); 586 } 587 588 /*! \class Merge_2 589 * A functor that merges two x-monotone arcs into one. 590 */ 591 class Merge_2 592 { 593 protected: 594 typedef Arr_circle_segment_traits_2<Kernel, Filter> Traits; 595 596 /*! The traits (in case it has state) */ 597 const Traits* m_traits; 598 599 /*! Constructor 600 * \param traits the traits (in case it has state) 601 */ Merge_2(const Traits * traits)602 Merge_2(const Traits* traits) : m_traits(traits) {} 603 604 friend class Arr_circle_segment_traits_2<Kernel, Filter>; 605 606 public: 607 /*! 608 * Merge two given x-monotone curves into a single curve. 609 * \param cv1 The first curve. 610 * \param cv2 The second curve. 611 * \param c Output: The merged curve. 612 * \pre The two curves are mergeable. 613 */ operator()614 void operator() (const X_monotone_curve_2& cv1, 615 const X_monotone_curve_2& cv2, 616 X_monotone_curve_2& c) const 617 { 618 CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); 619 620 c = cv1; 621 c.merge (cv2); 622 } 623 }; 624 625 /*! Get a Merge_2 functor object. */ merge_2_object()626 Merge_2 merge_2_object () const 627 { 628 return Merge_2(this); 629 } 630 631 class Compare_endpoints_xy_2 632 { 633 public: 634 /*! 635 * compare lexicogrphic the endpoints of a x-monotone curve. 636 * \param cv the curve 637 * \return SMALLER if the curve is directed right, else return SMALLER 638 */ operator()639 Comparison_result operator()(const X_monotone_curve_2& cv) const 640 { 641 if(cv.is_directed_right()) 642 return(SMALLER); 643 return (LARGER); 644 } 645 }; 646 647 /*! Get a Compare_endpoints_xy_2 functor object. */ compare_endpoints_xy_2_object()648 Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const 649 { 650 return Compare_endpoints_xy_2(); 651 } 652 653 class Construct_opposite_2 654 { 655 public: 656 /*! 657 * construct an opposite x-monotone curve. 658 * \param cv the curve 659 * \return an opposite x-monotone curve. 660 */ operator()661 X_monotone_curve_2 operator()(const X_monotone_curve_2& cv) const 662 { 663 return cv.construct_opposite(); 664 } 665 }; 666 667 /*! Get a Construct_opposite_2 functor object. */ construct_opposite_2_object()668 Construct_opposite_2 construct_opposite_2_object() const 669 { 670 return Construct_opposite_2(); 671 } 672 673 class Trim_2 { 674 protected: 675 typedef Arr_circle_segment_traits_2<Kernel, Filter> Traits; 676 677 /*! The traits (in case it has state) */ 678 const Traits& m_traits; 679 680 /*! Constructor 681 * \param traits the traits (in case it has state) 682 */ Trim_2(const Traits & traits)683 Trim_2(const Traits& traits) : m_traits(traits) {} 684 685 friend class Arr_circle_segment_traits_2<Kernel, Filter>; 686 687 public: 688 /*! Obtain a trimmed version of an arc 689 * \param xcv The arc 690 * \param src the new first endpoint 691 * \param tgt the new second endpoint 692 * \return The trimmed arc 693 * \pre src != tgt 694 * \pre both points must be interior and must lie on \c cv 695 */ operator()696 X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv, 697 const Point_2& src, 698 const Point_2& tgt)const 699 { 700 // make functor objects 701 CGAL_precondition_code(Compare_y_at_x_2 compare_y_at_x_2 = 702 m_traits.compare_y_at_x_2_object()); 703 CGAL_precondition_code(Equal_2 equal_2 = m_traits.equal_2_object()); 704 Compare_x_2 compare_x_2 = m_traits.compare_x_2_object(); 705 // Check whether source and taget are two distinct points and they lie 706 // on the line. 707 CGAL_precondition(compare_y_at_x_2(src, xcv) == EQUAL); 708 CGAL_precondition(compare_y_at_x_2(tgt, xcv) == EQUAL); 709 CGAL_precondition(! equal_2(src, tgt)); 710 711 //check if the orientation conforms to the src and tgt. 712 if( (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) || 713 (! xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER) ) 714 return (xcv.trim(tgt, src) ); 715 else return (xcv.trim(src, tgt)); 716 } 717 }; 718 719 /*! Obtain a Trim_2 functor object. */ trim_2_object()720 Trim_2 trim_2_object() const { return Trim_2(*this); } 721 722 // @} 723 724 }; 725 726 } //namespace CGAL 727 728 #include <CGAL/enable_warnings.h> 729 730 #endif 731