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