1 // Copyright (c) 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_segment_traits_2.h $
7 // $Id: Arr_segment_traits_2.h c596073 2020-11-05T10:43:47+02:00 Efi Fogel
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s): Ron Wein          <wein@post.tau.ac.il>
11 //            Efi Fogel         <efif@gmail.com>
12 //            Waqar Khan        <wkhan@mpi-inf.mpg.de>
13 //            Simon Giraudot    <simon.giraudot@geometryfactory.com>
14 
15 #ifndef CGAL_ARR_SEGMENT_TRAITS_2_H
16 #define CGAL_ARR_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 segment traits-class for the arrangement package.
24  */
25 
26 #include <fstream>
27 
28 #include <boost/variant.hpp>
29 
30 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
31 #include <CGAL/tags.h>
32 #include <CGAL/intersections.h>
33 #include <CGAL/Arr_tags.h>
34 #include <CGAL/Arr_enums.h>
35 #include <CGAL/Arr_geometry_traits/Segment_assertions.h>
36 
37 namespace CGAL {
38 
39 template <typename Kernel_ = Exact_predicates_exact_constructions_kernel>
40 class Arr_segment_2;
41 
42 /*! \class A traits class for maintaining an arrangement of segments, avoiding
43  * cascading of computations as much as possible.
44  *
45  * The class is derived from the parameterized kernel to extend the traits
46  * with all the types and operations supported by the kernel. This makes it
47  * possible to use the traits class for data structures that extend the
48  * Arrangement_2 type and require objects and operations supported by the
49  * kernel, but not defined in this derived class.
50  */
51 template <typename Kernel_ = Exact_predicates_exact_constructions_kernel>
52 class Arr_segment_traits_2 : public Kernel_ {
53   friend class Arr_segment_2<Kernel_>;
54 
55 public:
56   typedef Kernel_                         Kernel;
57   typedef typename Kernel::FT             FT;
58 
59   typedef typename Algebraic_structure_traits<FT>::Is_exact
60                                           Has_exact_division;
61 
62   // Category tags:
63   typedef Tag_true                        Has_left_category;
64   typedef Tag_true                        Has_merge_category;
65   typedef Tag_false                       Has_do_intersect_category;
66 
67   typedef Arr_oblivious_side_tag          Left_side_category;
68   typedef Arr_oblivious_side_tag          Bottom_side_category;
69   typedef Arr_oblivious_side_tag          Top_side_category;
70   typedef Arr_oblivious_side_tag          Right_side_category;
71 
72   typedef typename Kernel::Line_2         Line_2;
73   typedef CGAL::Segment_assertions<Arr_segment_traits_2<Kernel> >
74                                           Segment_assertions;
75 
76   /*! \class Representation of a segment with cached data.
77    */
78   class _Segment_cached_2 {
79   public:
80     typedef typename Kernel::Line_2                Line_2;
81     typedef typename Kernel::Segment_2             Segment_2;
82     typedef typename Kernel::Point_2               Point_2;
83 
84   protected:
85     mutable Line_2 m_l;         // the line that supports the segment.
86     Point_2 m_ps;               // the source point of the segment.
87     Point_2 m_pt;               // the target point of the segment.
88     bool m_is_directed_right;   // is (lexicographically) directed left to right.
89     mutable bool m_is_vert;     // is this a vertical segment.
90     mutable bool m_is_computed; // is the support line computed.
91     bool m_is_degen;            // is the segment degenerate (a single point).
92 
93   public:
94 
95     /// \name Creation
96     //@{
97 
98     /*! Construct default. */
99     _Segment_cached_2();
100 
101     /*! Construct a segment from a Kernel segment.
102      * \param seg the segment.
103      * \pre the segment is not degenerate.
104      */
105     _Segment_cached_2(const Segment_2& seg);
106 
107     /*! Construct a segment from two endpoints.
108      * \param source the source point.
109      * \param target the target point.
110      * \param `source` and `target` are not equal.
111      */
112     _Segment_cached_2(const Point_2& source, const Point_2& target);
113 
114     /*! Construct a segment from two endpoints on a supporting line.
115      * \param line the supporting line.
116      * \param source the source point.
117      * \param target the target point.
118      * \pre `source` and `target` are not equal and both lie on `line`.
119      */
120     _Segment_cached_2(const Line_2& line,
121                       const Point_2& source, const Point_2& target);
122 
123     /*! Construct a segment from all fields.
124      * \param line the supporting line.
125      * \param source the source point.
126      * \param target the target point.
127      * \param is_directed_right is (lexicographically) directed left to right.
128      * \param is_vert is the segment vertical.
129      * \param is_degen is the segment degenerate (a single point).
130      */
131     _Segment_cached_2(const Line_2& line,
132                       const Point_2& source, const Point_2& target,
133                       bool is_directed_right, bool is_vert, bool is_degen);
134 
135     /*! Assign.
136      * \param seg the source segment to copy from
137      * \pre the segment is not degenerate.
138      */
139     const _Segment_cached_2& operator=(const Segment_2& seg);
140 
141     //@}
142 
143     /// \name Accessors
144     //@{
145 
146     /*! Obtain the supporting line.
147      * \return the supporting line.
148      */
149     const Line_2& line() const;
150 
151     /*! Obtain the segment source.
152      * \return the segment source.
153      */
154     const Point_2& source() const;
155 
156     /*! Obtain the segment target.
157      * \return the segment target.
158      */
159     const Point_2& target() const;
160 
161     /*! Determine whether the curve is vertical.
162      * \return a Boolean flag indicating whether the curve is vertical.
163      */
164     bool is_vertical() const;
165 
166     /*! Determine whether the curve is degenerate.
167      * return a Boolean flag indicating whether the curve is degenerate.
168      */
169     bool is_degenerate() const;
170 
171     /*! Determine whether the curve is lexicographically directed from left to
172      * right.
173      * \return a Boolean flag indicating whether the curve is lexicographically
174      *         directed from left to right.
175      */
176     bool is_directed_right() const;
177 
178     /*! Obtain the (lexicographically) left endpoint.
179      * \return the (lexicographically) left endpoint.
180      */
181     const Point_2& left() const;
182 
183     /*! Obtain the (lexicographically) right endpoint.
184      * \return the (lexicographically) right endpoint.
185      */
186     const Point_2& right() const;
187 
188     //@}
189 
190     /// \name Modifiers
191     //@{
192 
193     /*! Set the (lexicographically) left endpoint.
194      * \param p the point to set.
195      * \pre p lies on the supporting line to the left of the right endpoint.
196      */
197     void set_left(const Point_2& p);
198 
199     /*! Set the (lexicographically) right endpoint.
200      * \param p the point to set.
201      * \pre p lies on the supporting line to the right of the left endpoint.
202      */
203     void set_right(const Point_2& p);
204 
205     //@}
206 
207     /// \name Deprecated
208     //@{
209 
210     /*! Determine whether the given point is in the x-range of the segment.
211      * \param p the query point.
212      * \return (true) is in the x-range of the segment; (false) if it is not.
213      */
214     CGAL_DEPRECATED bool is_in_x_range(const Point_2& p) const;
215 
216     /*! Determine whether the given point is in the y-range of the segment.
217      * \param p the query point.
218      * \return (true) is in the y-range of the segment; (false) if it is not.
219      */
220     CGAL_DEPRECATED bool is_in_y_range(const Point_2& p) const;
221 
222     //@}
223   };
224 
225 public:
226   // Traits objects
227   typedef typename Kernel::Point_2        Point_2;
228   typedef Arr_segment_2<Kernel>           X_monotone_curve_2;
229   typedef Arr_segment_2<Kernel>           Curve_2;
230   typedef unsigned int                    Multiplicity;
231 
232 public:
233   /*! Construct default. */
Arr_segment_traits_2()234   Arr_segment_traits_2() {}
235 
236   /// \name Basic functor definitions.
237   //@{
238 
239   class Compare_x_2 {
240   protected:
241     typedef Arr_segment_traits_2<Kernel>        Traits;
242 
243     //! The traits (in case it has state).
244     const Traits& m_traits;
245 
246     /*! Constructor
247      * \param traits the traits (in case it has state)
248      */
Compare_x_2(const Traits & traits)249     Compare_x_2(const Traits& traits) : m_traits(traits) {}
250 
251     friend class Arr_segment_traits_2<Kernel>;
252 
253   public:
254     /*! Compare the x-coordinates of two points.
255      * \param p1 the first point.
256      * \param p2 the second point.
257      * \return LARGER if x(p1) > x(p2);
258      *         SMALLER if x(p1) < x(p2);
259      *         EQUAL if x(p1) = x(p2).
260      */
operator()261     Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
262     {
263       const Kernel& kernel = m_traits;
264       return (kernel.compare_x_2_object()(p1, p2));
265     }
266   };
267 
268   /*! Obtain a Compare_x_2 functor object. */
compare_x_2_object()269   Compare_x_2 compare_x_2_object() const { return Compare_x_2(*this); }
270 
271   class Compare_xy_2 {
272   protected:
273     typedef Arr_segment_traits_2<Kernel>        Traits;
274 
275     /*! The traits (in case it has state) */
276     const Traits& m_traits;
277 
278     /*! Constructor
279      * \param traits the traits (in case it has state)
280      */
Compare_xy_2(const Traits & traits)281     Compare_xy_2(const Traits& traits) : m_traits(traits) {}
282 
283     friend class Arr_segment_traits_2<Kernel>;
284 
285   public:
286     /*! Compare two points lexicographically: by x, then by y.
287      * \param p1 the first point.
288      * \param p2 the second point.
289      * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2);
290      *         SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2);
291      *         EQUAL if the two points are equal.
292      */
operator()293     Comparison_result operator()(const Point_2& p1, const Point_2& p2) const
294     {
295       const Kernel& kernel = m_traits;
296       return (kernel.compare_xy_2_object()(p1, p2));
297     }
298   };
299 
300   /*! Obtain a Compare_xy_2 functor object. */
compare_xy_2_object()301   Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); }
302 
303   class Construct_min_vertex_2 {
304   public:
305     /*! Obtain the left endpoint of the x-monotone curve (segment).
306      * \param cv the curve.
307      * \return the left endpoint.
308      */
operator()309     const Point_2& operator()(const X_monotone_curve_2& cv) const
310     { return (cv.left()); }
311   };
312 
313   /*! Obtain a Construct_min_vertex_2 functor object. */
construct_min_vertex_2_object()314   Construct_min_vertex_2 construct_min_vertex_2_object() const
315   { return Construct_min_vertex_2(); }
316 
317   class Construct_max_vertex_2 {
318   public:
319     /*! Obtain the right endpoint of the x-monotone curve (segment).
320      * \param cv the curve.
321      * \return the right endpoint.
322      */
operator()323     const Point_2& operator()(const X_monotone_curve_2& cv) const
324     { return (cv.right()); }
325   };
326 
327   /*! Obtain a Construct_max_vertex_2 functor object. */
construct_max_vertex_2_object()328   Construct_max_vertex_2 construct_max_vertex_2_object() const
329   { return Construct_max_vertex_2(); }
330 
331   class Is_vertical_2 {
332   public:
333     /*! Check whether the given x-monotone curve is a vertical segment.
334      * \param cv the curve.
335      * \return (true) if the curve is a vertical segment; (false) otherwise.
336      */
operator()337     bool operator()(const X_monotone_curve_2& cv) const
338     { return (cv.is_vertical()); }
339   };
340 
341   /*! Obtain an Is_vertical_2 functor object. */
is_vertical_2_object()342   Is_vertical_2 is_vertical_2_object () const { return Is_vertical_2(); }
343 
344   class Compare_y_at_x_2 {
345   protected:
346     typedef Arr_segment_traits_2<Kernel>        Traits;
347 
348     /*! the traits (in case it has state) */
349     const Traits& m_traits;
350 
351     /*! Constructor
352      * \param traits the traits (in case it has state)
353      */
Compare_y_at_x_2(const Traits & traits)354     Compare_y_at_x_2(const Traits& traits) : m_traits(traits) {}
355 
356     friend class Arr_segment_traits_2<Kernel>;
357 
358   public:
359     /*! Return the location of the given point with respect to the input curve.
360      * \param cv the curve.
361      * \param p the point.
362      * \pre p is in the x-range of cv.
363      * \return SMALLER if y(p) < cv(x(p)), i.e. the point is below the curve;
364      *         LARGER if y(p) > cv(x(p)), i.e. the point is above the curve;
365      *         EQUAL if p lies on the curve.
366      */
operator()367     Comparison_result operator()(const Point_2& p,
368                                  const X_monotone_curve_2& cv) const
369     {
370       CGAL_precondition(m_traits.is_in_x_range_2_object()(cv, p));
371 
372       const Kernel& kernel = m_traits;
373 
374       if (! cv.is_vertical()) {
375         // Compare p with the segment supporting line.
376         CGAL_assertion_code(auto cmp_x = kernel.compare_x_2_object());
377         CGAL_assertion(cmp_x(cv.left(), cv.right()) == SMALLER);
378         return kernel.orientation_2_object()(cv.left(), cv.right(), p);
379       }
380 
381       // Compare with the vertical segment endpoints.
382       auto compare_y = kernel.compare_y_2_object();
383       Comparison_result res1 = compare_y(p, cv.left());
384       Comparison_result res2 = compare_y(p, cv.right());
385       return (res1 == res2) ? res1 : EQUAL;
386     }
387   };
388 
389   /*! Obtain a Compare_y_at_x_2 functor object. */
compare_y_at_x_2_object()390   Compare_y_at_x_2 compare_y_at_x_2_object() const
391   { return Compare_y_at_x_2(*this); }
392 
393   class Compare_y_at_x_left_2 {
394   protected:
395     typedef Arr_segment_traits_2<Kernel>        Traits;
396 
397     /*! The traits (in case it has state) */
398     const Traits& m_traits;
399 
400     /*! Constructor
401      * \param traits the traits (in case it has state)
402      */
Compare_y_at_x_left_2(const Traits & traits)403     Compare_y_at_x_left_2(const Traits& traits) : m_traits(traits) {}
404 
405     friend class Arr_segment_traits_2<Kernel>;
406 
407   public:
408     /*! Compare the y value of two x-monotone curves immediately to the left
409      * of their intersection point.
410      * \param cv1 the first curve.
411      * \param cv2 the second curve.
412      * \param p the intersection point.
413      * \pre the point p lies on both curves, and both of them must be also be
414      *      defined (lexicographically) to its left.
415      * \return the relative position of cv1 with respect to cv2 immediately to
416      *         the left of p: SMALLER, LARGER or EQUAL.
417      */
operator()418     Comparison_result operator()(const X_monotone_curve_2& cv1,
419                                  const X_monotone_curve_2& cv2,
420                                  const Point_2& CGAL_assertion_code(p)) const
421     {
422       const Kernel& kernel = m_traits;
423 
424       // Make sure that p lies on both curves, and that both are defined to its
425       // left (so their left endpoint is lexicographically smaller than p).
426       CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object());
427 
428       CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) &&
429                         (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL));
430 
431       CGAL_precondition(compare_xy(cv1.left(), p) == SMALLER &&
432                         compare_xy(cv2.left(), p) == SMALLER);
433 
434       // Compare the slopes of the two segments to determine their relative
435       // position immediately to the left of q.
436       // Notice we use the supporting lines in order to compare the slopes,
437       // and that we swap the order of the curves in order to obtain the
438       // correct result to the left of p.
439       return (kernel.compare_slope_2_object()(cv2.line(), cv1.line()));
440     }
441   };
442 
443   /*! Obtain a Compare_y_at_x_left_2 functor object. */
compare_y_at_x_left_2_object()444   Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const
445   { return Compare_y_at_x_left_2(*this); }
446 
447   class Compare_y_at_x_right_2 {
448   protected:
449     typedef Arr_segment_traits_2<Kernel>        Traits;
450 
451     /*! The traits (in case it has state) */
452     const Traits& m_traits;
453 
454     /*! Constructor
455      * \param traits the traits (in case it has state)
456      */
Compare_y_at_x_right_2(const Traits & traits)457     Compare_y_at_x_right_2(const Traits& traits) : m_traits(traits) {}
458 
459     friend class Arr_segment_traits_2<Kernel>;
460 
461   public:
462     /*! Compare the y value of two x-monotone curves immediately to the right
463      * of their intersection point.
464      * \param cv1 the first curve.
465      * \param cv2 the second curve.
466      * \param p the intersection point.
467      * \pre the point p lies on both curves, and both of them must be also be
468      *      defined (lexicographically) to its right.
469      * \return the relative position of cv1 with respect to cv2 immediately to
470      *         the right of p: SMALLER, LARGER or EQUAL.
471      */
operator()472     Comparison_result operator()(const X_monotone_curve_2& cv1,
473                                  const X_monotone_curve_2& cv2,
474                                  const Point_2& CGAL_assertion_code(p)) const
475     {
476       const Kernel& kernel = m_traits;
477 
478       // Make sure that p lies on both curves, and that both are defined to its
479       // right (so their right endpoint is lexicographically larger than p).
480       CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object());
481 
482       CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) &&
483                         (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL));
484 
485       CGAL_precondition(compare_xy(cv1.right(), p) == LARGER &&
486                         compare_xy(cv2.right(), p) == LARGER);
487 
488       // Compare the slopes of the two segments to determine their relative
489       // position immediately to the left of q.
490       // Notice we use the supporting lines in order to compare the slopes.
491       return (kernel.compare_slope_2_object()(cv1.line(), cv2.line()));
492     }
493   };
494 
495   /*! Obtain a Compare_y_at_x_right_2 functor object. */
compare_y_at_x_right_2_object()496   Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const
497   { return Compare_y_at_x_right_2(*this); }
498 
499   class Equal_2 {
500   protected:
501     typedef Arr_segment_traits_2<Kernel>        Traits;
502 
503     /*! The traits (in case it has state) */
504     const Traits& m_traits;
505 
506     /*! Constructor
507      * \param traits the traits (in case it has state)
508      */
Equal_2(const Traits & traits)509     Equal_2(const Traits& traits) : m_traits(traits) {}
510 
511     friend class Arr_segment_traits_2<Kernel>;
512 
513   public:
514     /*! Check whether the two x-monotone curves are the same (have the same
515      * graph).
516      * \param cv1 the first curve.
517      * \param cv2 the second curve.
518      * \return (true) if the two curves are the same; (false) otherwise.
519      */
operator()520     bool operator()(const X_monotone_curve_2& cv1,
521                     const X_monotone_curve_2& cv2) const
522     {
523       const Kernel& kernel = m_traits;
524       typename Kernel::Equal_2  equal = kernel.equal_2_object();
525 
526       return (equal(cv1.left(), cv2.left()) &&
527               equal(cv1.right(), cv2.right()));
528     }
529 
530     /*! Determine whether the two points are the same.
531      * \param p1 the first point.
532      * \param p2 the second point.
533      * \return (true) if the two point are the same; (false) otherwise.
534      */
operator()535     bool operator()(const Point_2& p1, const Point_2& p2) const
536     {
537       const Kernel& kernel = m_traits;
538       return (kernel.equal_2_object()(p1, p2));
539     }
540   };
541 
542   /*! Obtain an Equal_2 functor object. */
equal_2_object()543   Equal_2 equal_2_object() const { return Equal_2(*this); }
544 
545   //@}
546 
547   //! \name Intersections, subdivisions, and mergings
548   //@{
549 
550   /*! \class Make_x_monotone_2
551    * A functor for subdividing a curve into x-monotone curves.
552    */
553   class Make_x_monotone_2 {
554   public:
555     /*! Subdivide a given curve into x-monotone subcurves and insert them into
556      * a given output iterator. As segments are always x_monotone a single
557      * object is inserted.
558      * \param cv the curve.
559      * \param oi the output iterator for the result. Its dereference type is a
560      *           variant that wraps a \c Point_2 or an \c X_monotone_curve_2
561      *           objects.
562      * \return the past-the-end output iterator.
563      */
564     template <typename OutputIterator>
operator()565     OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const
566     {
567       // Wrap the segment with a variant.
568       typedef boost::variant<Point_2, X_monotone_curve_2>
569         Make_x_monotone_result;
570       *oi++ = Make_x_monotone_result(cv);
571       return oi;
572     }
573   };
574 
575   /*! Obtain a Make_x_monotone_2 functor object. */
make_x_monotone_2_object()576   Make_x_monotone_2 make_x_monotone_2_object() const
577   { return Make_x_monotone_2(); }
578 
579   class Split_2 {
580   protected:
581     typedef Arr_segment_traits_2<Kernel>        Traits;
582 
583     /*! The traits (in case it has state) */
584     const Traits& m_traits;
585 
586     /*! Constructor
587      * \param traits the traits (in case it has state)
588      */
Split_2(const Traits & traits)589     Split_2(const Traits& traits) : m_traits(traits) {}
590 
591     friend class Arr_segment_traits_2<Kernel>;
592 
593   public:
594     /*! Split a given x-monotone curve at a given point into two sub-curves.
595      * \param cv the curve to split
596      * \param p the split point.
597      * \param c1 Output: the left resulting subcurve (p is its right endpoint).
598      * \param c2 Output: the right resulting subcurve (p is its left endpoint).
599      * \pre p lies on cv but is not one of its endpoints.
600      */
operator()601     void operator()(const X_monotone_curve_2& cv, const Point_2& p,
602                     X_monotone_curve_2& c1, X_monotone_curve_2& c2) const
603     {
604       // Make sure that p lies on the interior of the curve.
605       CGAL_precondition_code(const Kernel& kernel = m_traits;
606                              auto compare_xy = kernel.compare_xy_2_object());
607 
608       CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv) == EQUAL) &&
609                         compare_xy(cv.left(), p) == SMALLER &&
610                         compare_xy(cv.right(), p) == LARGER);
611 
612       // Perform the split.
613       c1 = cv;
614       c1.set_right(p);
615 
616       c2 = cv;
617       c2.set_left(p);
618     }
619   };
620 
621   /*! Obtain a Split_2 functor object. */
split_2_object()622   Split_2 split_2_object() const { return Split_2(*this); }
623 
624   class Intersect_2 {
625   protected:
626     typedef Arr_segment_traits_2<Kernel>        Traits;
627 
628     /*! The traits (in case it has state) */
629     const Traits& m_traits;
630 
631     /*! Construct
632      * \param traits the traits (in case it has state)
633      */
Intersect_2(const Traits & traits)634     Intersect_2(const Traits& traits) : m_traits(traits) {}
635 
636     friend class Arr_segment_traits_2<Kernel>;
637 
638     // Specialized do_intersect with many tests skipped because at
639     // this point, we already know which point is left / right for
640     // both segments
do_intersect(const Point_2 & A1,const Point_2 & A2,const Point_2 & B1,const Point_2 & B2)641     bool do_intersect(const Point_2& A1, const Point_2& A2,
642                       const Point_2& B1, const Point_2& B2) const
643     {
644       const Kernel& kernel = m_traits;
645       auto compare_xy = kernel.compare_xy_2_object();
646       namespace interx = CGAL::Intersections::internal;
647 
648       switch(make_certain(compare_xy(A1,B1))) {
649        case SMALLER:
650         switch(make_certain(compare_xy(A2,B1))) {
651          case SMALLER: return false;
652          case EQUAL: return true;
653          default: // LARGER
654           switch(make_certain(compare_xy(A2,B2))) {
655            case SMALLER:
656             return interx::seg_seg_do_intersect_crossing(A1,A2,B1,B2, kernel);
657            case EQUAL: return true;
658            default: // LARGER
659             return interx::seg_seg_do_intersect_contained(A1,A2,B1,B2, kernel);
660           }
661         }
662        case EQUAL: return true;
663        default: // LARGER
664         switch(make_certain(compare_xy(B2,A1))) {
665          case SMALLER: return false;
666          case EQUAL: return true;
667          default: // LARGER
668           switch(make_certain(compare_xy(B2,A2))) {
669            case SMALLER:
670             return interx::seg_seg_do_intersect_crossing(B1,B2,A1,A2, kernel);
671            case EQUAL: return true;
672            default: // LARGER
673             return interx::seg_seg_do_intersect_contained(B1,B2,A1,A2, kernel);
674           }
675         }
676       }
677       CGAL_error();     // never reached
678       return false;
679     }
680 
681     /*! Determine whether the bounding boxes of two segments overlap
682      */
do_bboxes_overlap(const X_monotone_curve_2 & cv1,const X_monotone_curve_2 & cv2)683     bool do_bboxes_overlap(const X_monotone_curve_2& cv1,
684                            const X_monotone_curve_2& cv2) const
685     {
686       const Kernel& kernel = m_traits;
687       auto construct_bbox = kernel.construct_bbox_2_object();
688       auto bbox1 = construct_bbox(cv1.source()) + construct_bbox(cv1.target());
689       auto bbox2 = construct_bbox(cv2.source()) + construct_bbox(cv2.target());
690       return CGAL::do_overlap(bbox1, bbox2);
691     }
692 
693   public:
694     /*! Find the intersections of the two given curves and insert them into the
695      * given output iterator. As two segments may intersect only once, only a
696      * single intersection will be contained in the iterator.
697      * \param cv1 the first curve.
698      * \param cv2 the second curve.
699      * \param oi the output iterator.
700      * \return the past-the-end iterator.
701      */
702     template <typename OutputIterator>
operator()703     OutputIterator operator()(const X_monotone_curve_2& cv1,
704                               const X_monotone_curve_2& cv2,
705                               OutputIterator oi) const
706     {
707       typedef std::pair<Point_2, Multiplicity>          Intersection_point;
708       typedef boost::variant<Intersection_point, X_monotone_curve_2>
709                                                         Intersection_result;
710 
711       // Early ending with Bbox overlapping test
712       if (! do_bboxes_overlap(cv1, cv2)) return oi;
713 
714       // Early ending with specialized do_intersect
715       const Kernel& kernel = m_traits;
716       if (! do_intersect(cv1.left(), cv1.right(), cv2.left(), cv2.right()))
717         return oi;
718 
719       // An intersection is guaranteed.
720 
721       // Intersect the two supporting lines.
722       auto res = kernel.intersect_2_object()(cv1.line(), cv2.line());
723       CGAL_assertion(bool(res));
724 
725       // Check if we have a single intersection point.
726       const Point_2* ip = boost::get<Point_2>(&*res);
727       if (ip != nullptr) {
728         CGAL_assertion(cv1.is_vertical() ?
729                        m_traits.is_in_y_range_2_object()(cv1, *ip) :
730                        m_traits.is_in_x_range_2_object()(cv1, *ip));
731         CGAL_assertion(cv2.is_vertical() ?
732                        m_traits.is_in_y_range_2_object()(cv2, *ip) :
733                        m_traits.is_in_x_range_2_object()(cv2, *ip));
734         Intersection_point ip_mult(*ip, 1);
735         *oi++ = Intersection_result(ip_mult);
736         return oi;
737       }
738 
739       // In this case, the two supporting lines overlap.
740       // The overlapping segment is therefore [p_l,p_r], where p_l is the
741       // rightmost of the two left endpoints and p_r is the leftmost of the
742       // two right endpoints.
743       auto compare_xy = kernel.compare_xy_2_object();
744       const Point_2& p_l = (compare_xy(cv1.left(), cv2.left()) == SMALLER) ?
745         cv2.left() : cv1.left();
746       const Point_2& p_r = (compare_xy(cv1.right(), cv2.right()) == SMALLER) ?
747         cv1.right() : cv2.right();
748 
749       // Examine the resulting segment.
750       const Comparison_result cmp_res = compare_xy(p_l, p_r);
751       if (cmp_res == EQUAL) {
752         // The two segment have the same supporting line, but they just share
753         // a common endpoint. Thus we have an intersection point, but we leave
754         // the multiplicity of this point undefined.
755         Intersection_point ip_mult(p_r, 0);
756         *oi++ = Intersection_result(ip_mult);
757         return oi;
758       }
759 
760       CGAL_assertion(cmp_res == SMALLER);
761       // We have discovered an overlapping segment:
762       if (cv1.is_directed_right() == cv2.is_directed_right()) {
763         // cv1 and cv2 have the same directions, maintain this direction
764         // in the overlap segment
765         if (cv1.is_directed_right()) {
766           X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r);
767           *oi++ = Intersection_result(overlap_seg);
768           return oi;
769         }
770         X_monotone_curve_2 overlap_seg(cv1.line(), p_r, p_l);
771         *oi++ = Intersection_result(overlap_seg);
772         return oi;
773       }
774       // cv1 and cv2 have opposite directions, the overlap segment
775       // will be directed from left to right
776       X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r);
777       *oi++ = Intersection_result(overlap_seg);
778       return oi;
779     }
780   };
781 
782   /*! Obtain an Intersect_2 functor object. */
intersect_2_object()783   Intersect_2 intersect_2_object() const { return Intersect_2(*this); }
784 
785   class Are_mergeable_2 {
786   protected:
787     typedef Arr_segment_traits_2<Kernel>        Traits;
788 
789     /*! The traits (in case it has state) */
790     const Traits& m_traits;
791 
792     /*! Constructor
793      * \param traits the traits (in case it has state)
794      */
Are_mergeable_2(const Traits & traits)795     Are_mergeable_2(const Traits& traits) : m_traits(traits) {}
796 
797     friend class Arr_segment_traits_2<Kernel>;
798 
799   public:
800     /*! Check whether it is possible to merge two given x-monotone curves.
801      * \param cv1 the first curve.
802      * \param cv2 the second curve.
803      * \return (true) if the two curves are mergeable, that is, if they are
804      *         supported by the same line; (false) otherwise.
805      * \pre cv1 and cv2 share a common endpoint.
806      */
operator()807     bool operator()(const X_monotone_curve_2& cv1,
808                     const X_monotone_curve_2& cv2) const
809     {
810       const Kernel& kernel = m_traits;
811       typename Kernel::Equal_2 equal = kernel.equal_2_object();
812       if (! equal(cv1.right(), cv2.left()) &&
813           ! equal(cv2.right(), cv1.left()))
814         return false;
815 
816       // Check whether the two curves have the same supporting line.
817       return (equal(cv1.line(), cv2.line()) ||
818               equal(cv1.line(),
819                     kernel.construct_opposite_line_2_object()(cv2.line())));
820     }
821   };
822 
823   /*! Obtain an Are_mergeable_2 functor object. */
are_mergeable_2_object()824   Are_mergeable_2 are_mergeable_2_object() const
825   { return Are_mergeable_2(*this); }
826 
827   /*! \class Merge_2
828    * A functor that merges two x-monotone arcs into one.
829    */
830   class Merge_2 {
831   protected:
832     typedef Arr_segment_traits_2<Kernel>        Traits;
833 
834     /*! The traits (in case it has state) */
835     const Traits& m_traits;
836 
837     /*! Constructor
838      * \param traits the traits (in case it has state)
839      */
Merge_2(const Traits & traits)840     Merge_2(const Traits& traits) : m_traits(traits) {}
841 
842     friend class Arr_segment_traits_2<Kernel>;
843 
844   public:
845     /*! Merge two given x-monotone curves into a single curve (segment).
846      * \param cv1 the first curve.
847      * \param cv2 the second curve.
848      * \param c Output: the merged curve.
849      * \pre the two curves are mergeable.
850      */
operator()851     void operator()(const X_monotone_curve_2& cv1,
852                     const X_monotone_curve_2& cv2,
853                     X_monotone_curve_2& c) const
854     {
855       CGAL_precondition(m_traits.are_mergeable_2_object()(cv1, cv2));
856 
857       const Kernel& kernel = m_traits;
858       auto equal = kernel.equal_2_object();
859 
860       // Check which curve extends to the right of the other.
861       if (equal(cv1.right(), cv2.left())) {
862         // cv2 extends cv1 to the right.
863         c = cv1;
864         c.set_right(cv2.right());
865         return;
866       }
867 
868       CGAL_precondition(equal(cv2.right(), cv1.left()));
869 
870       // cv1 extends cv2 to the right.
871       c = cv2;
872       c.set_right(cv1.right());
873     }
874   };
875 
876   /*! Obtain a Merge_2 functor object. */
merge_2_object()877   Merge_2 merge_2_object() const { return Merge_2(*this); }
878   //@}
879 
880   /// \name Functor definitions for the landmarks point-location strategy.
881   //@{
882   typedef double                          Approximate_number_type;
883 
884   class Approximate_2 {
885   public:
886     /*! Obtain an approximation of a point coordinate.
887      * \param p the exact point.
888      * \param i the coordinate index (either 0 or 1).
889      * \pre i is either 0 or 1.
890      * \return An approximation of p's x-coordinate (if i == 0), or an
891      *         approximation of p's y-coordinate (if i == 1).
892      */
operator()893     Approximate_number_type operator()(const Point_2& p, int i) const
894     {
895       CGAL_precondition((i == 0) || (i == 1));
896       return (i == 0) ? (CGAL::to_double(p.x())) : (CGAL::to_double(p.y()));
897     }
898   };
899 
900   /*! Obtain an Approximate_2 functor object. */
approximate_2_object()901   Approximate_2 approximate_2_object() const { return Approximate_2(); }
902 
903   class Construct_x_monotone_curve_2 {
904   protected:
905     typedef Arr_segment_traits_2<Kernel>        Traits;
906 
907     //! The traits (in case it has state).
908     const Traits& m_traits;
909 
910     /*! Constructor
911      * \param traits the traits (in case it has state)
912      */
Construct_x_monotone_curve_2(const Traits & traits)913     Construct_x_monotone_curve_2(const Traits& traits) : m_traits(traits) {}
914 
915     friend class Arr_segment_traits_2<Kernel>;
916 
917   public:
918     typedef typename Kernel::Segment_2          Segment_2;
919 
920     /*! Obtain an x-monotone curve connecting two given endpoints.
921      * \param source the first point.
922      * \param target the second point.
923      * \pre `source` and `target` must not be equal.
924      * \return a segment connecting `source` and `target`.
925      */
operator()926     X_monotone_curve_2 operator()(const Point_2& source,
927                                   const Point_2& target) const
928     {
929       const Kernel& kernel = m_traits;
930       auto line = kernel.construct_line_2_object()(source, target);
931       Comparison_result res = kernel.compare_xy_2_object()(source, target);
932       auto is_degen = (res == EQUAL);
933       auto is_directed_right = (res == SMALLER);
934       CGAL_precondition_msg(! is_degen,
935                             "Cannot construct a degenerate segment.");
936       auto is_vert = kernel.is_vertical_2_object()(line);
937       return X_monotone_curve_2(line, source, target,
938                                 is_directed_right, is_vert, is_degen);
939     }
940 
941     /*! Obtain an \f$x\f$-monotone curve given a Kernel segment.
942      * \param seg the segment.
943      * \return the \f$x\f$-monotone curve.
944      * \pre the segment is not degenerate.
945      * \return a segment that is the same as `seg`..
946      */
operator()947     X_monotone_curve_2 operator()(const Segment_2& seg) const
948     {
949       const Kernel& kernel = m_traits;
950       auto line = kernel.construct_line_2_object()(seg);
951       auto vertex_ctr = kernel.construct_vertex_2_object();
952       auto source = vertex_ctr(seg, 0);
953       auto target = vertex_ctr(seg, 1);
954       Comparison_result res = kernel.compare_xy_2_object()(source, target);
955       auto is_degen = (res == EQUAL);
956       auto is_directed_right = (res == SMALLER);
957       CGAL_precondition_msg(! is_degen,
958                             "Cannot construct a degenerate segment.");
959       auto is_vert = kernel.is_vertical_2_object()(seg);
960       return X_monotone_curve_2(line, source, target,
961                                 is_directed_right, is_vert, is_degen);
962     }
963 
964     /*! Obtain an \f$x\f$-monotone curve given two endpoints and the supporting
965      * line.
966      * \param line the supporting line.
967      * \param  the source point.
968      * \param  the target point.
969      * \pre `ps` and `pt` are not equal and both lie on `line`.
970      */
operator()971     X_monotone_curve_2 operator()(const Line_2& line,
972                                   const Point_2& source,
973                                   const Point_2& target) const
974     {
975       const Kernel& kernel = m_traits;
976       CGAL_precondition
977         (Segment_assertions::_assert_is_point_on(source, line,
978                                                  Has_exact_division()) &&
979          Segment_assertions::_assert_is_point_on(target, line,
980                                                  Has_exact_division()));
981       auto is_vert = kernel.is_vertical_2_object()(line);
982       Comparison_result res = kernel.compare_xy_2_object()(source, target);
983       auto is_degen = (res == EQUAL);
984       auto is_directed_right = (res == SMALLER);
985       CGAL_precondition_msg(! is_degen,
986                             "Cannot construct a degenerate segment.");
987       return X_monotone_curve_2(line, source, target,
988                                 is_directed_right, is_vert, is_degen);
989     }
990   };
991 
992   /*! Obtain a Construct_x_monotone_curve_2 functor object. */
construct_x_monotone_curve_2_object()993   Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const
994   { return Construct_x_monotone_curve_2(*this); }
995   //@}
996 
997   /// \name Functor definitions for the Boolean set-operation traits.
998   //@{
999 
1000   class Trim_2 {
1001    protected:
1002     typedef Arr_segment_traits_2<Kernel>        Traits;
1003 
1004     /*! The traits (in case it has state). */
1005     const Traits& m_traits;
1006 
1007     /*! Constructor
1008      * \param traits the traits (in case it has state)
1009      */
Trim_2(const Traits & traits)1010     Trim_2(const Traits& traits) : m_traits(traits) {}
1011 
1012     friend class Arr_segment_traits_2<Kernel>;
1013 
1014     /*! Obtain a trimmed version of a line.
1015      * \param xseg the x-monotone segment.
1016      * \param src the new start endpoint.
1017      * \param tgt the new end endpoint.
1018      * \return the trimmed x-monotone segment.
1019      * \pre src != tgt
1020      * \pre both points must lie on segment
1021      */
1022   public:
operator()1023     X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv,
1024                                   const Point_2& src,
1025                                   const Point_2& tgt)const
1026     {
1027       CGAL_precondition_code(Equal_2 equal = m_traits.equal_2_object());
1028       CGAL_precondition_code(Compare_y_at_x_2 compare_y_at_x =
1029                              m_traits.compare_y_at_x_2_object());
1030       Compare_x_2 compare_x_2 = m_traits.compare_x_2_object();
1031 
1032       // check whether source and taget are two distinct points and they lie
1033       // on the line.
1034       CGAL_precondition(!equal(src, tgt));
1035       CGAL_precondition(compare_y_at_x(src, xcv) == EQUAL);
1036       CGAL_precondition(compare_y_at_x(tgt, xcv) == EQUAL);
1037 
1038       // exchange src and tgt IF they do not conform with the direction
1039       X_monotone_curve_2 trimmed_segment;
1040       if (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER)
1041         trimmed_segment = X_monotone_curve_2(tgt, src);
1042       else if (! xcv.is_directed_right() && (compare_x_2(src, tgt) == SMALLER))
1043         trimmed_segment = X_monotone_curve_2(tgt, src);
1044       else trimmed_segment = X_monotone_curve_2(src, tgt);
1045       return trimmed_segment;
1046     }
1047   };
1048 
1049   /*! Obtain a Trim_2 functor object */
trim_2_object()1050   Trim_2 trim_2_object() const { return Trim_2(*this); }
1051 
1052   class Compare_endpoints_xy_2 {
1053   public:
1054     /*! Compare the endpoints of an $x$-monotone curve lexicographically.
1055      * (assuming the curve has a designated source and target points).
1056      * \param cv the curve.
1057      * \return SMALLER if the curve is directed right;
1058      *         LARGER if the curve is directed left.
1059      */
operator()1060     Comparison_result operator()(const X_monotone_curve_2& cv) const
1061     { return (cv.is_directed_right()) ? (SMALLER) : (LARGER); }
1062   };
1063 
1064   /*! Obtain a Compare_endpoints_xy_2 functor object. */
compare_endpoints_xy_2_object()1065   Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const
1066   { return Compare_endpoints_xy_2(); }
1067 
1068   class Construct_opposite_2 {
1069   public:
1070     /*! Construct an opposite x-monotone (with swapped source and target).
1071      * \param cv the curve.
1072      * \return the opposite curve.
1073      */
operator()1074     X_monotone_curve_2 operator()(const X_monotone_curve_2& cv) const
1075     { return (cv.flip()); }
1076   };
1077 
1078   /*! Obtain a Construct_opposite_2 functor object. */
construct_opposite_2_object()1079   Construct_opposite_2 construct_opposite_2_object() const
1080   { return Construct_opposite_2(); }
1081   //@}
1082 
1083   /// \name Utilities.
1084   //@{
1085 
1086   class Is_in_x_range_2 {
1087   protected:
1088     typedef Arr_segment_traits_2<Kernel>        Traits;
1089 
1090     //! The traits (in case it has state).
1091     const Traits& m_traits;
1092 
1093     /*! Construct
1094      * \param traits the traits (in case it has state)
1095      */
Is_in_x_range_2(const Traits & traits)1096     Is_in_x_range_2(const Traits& traits) : m_traits(traits) {}
1097 
1098     friend class Arr_segment_traits_2<Kernel>;
1099 
1100   public:
1101     /*! Determine whether a given point is in the \f$x\f$-range of a given
1102      * segment.
1103      * \param cv the segment.
1104      * \param p the point.
1105      * \return true if p is in the \f$x\f$-range of cv; false otherwise.
1106      */
operator()1107     bool operator()(const X_monotone_curve_2& cv, const Point_2& p) const
1108     {
1109       const Kernel& kernel = m_traits;
1110       auto compare_x = kernel.compare_x_2_object();
1111       Comparison_result res1 = compare_x(p, cv.left());
1112 
1113       if (res1 == SMALLER) return false;
1114       else if (res1 == EQUAL) return true;
1115 
1116       Comparison_result res2 = compare_x(p, cv.right());
1117       return (res2 != LARGER);
1118     }
1119   };
1120 
1121   /*! Obtain an Is_in_x_range_2 functor object */
is_in_x_range_2_object()1122   Is_in_x_range_2 is_in_x_range_2_object() const
1123   { return Is_in_x_range_2(*this); }
1124 
1125   class Is_in_y_range_2 {
1126   protected:
1127     typedef Arr_segment_traits_2<Kernel>        Traits;
1128 
1129     //! The traits (in case it has state).
1130     const Traits& m_traits;
1131 
1132     /*! Construct
1133      * \param traits the traits (in case it has state)
1134      */
Is_in_y_range_2(const Traits & traits)1135     Is_in_y_range_2(const Traits& traits) : m_traits(traits) {}
1136 
1137     friend class Arr_segment_traits_2<Kernel>;
1138 
1139   public:
1140     /*! Determine whether a given point is in the \f$y\f$-range of a given
1141      * segment.
1142      * \param cv the segment.
1143      * \param p the point.
1144      * \return true if p is in the \f$y\f$-range of cv; false otherwise.
1145      */
operator()1146     bool operator()(const X_monotone_curve_2& cv, const Point_2& p) const
1147     {
1148       const Kernel& kernel = m_traits;
1149       auto compare_y = kernel.compare_y_2_object();
1150       Comparison_result res1 = compare_y(p, cv.left());
1151 
1152       if (res1 == SMALLER) return false;
1153       else if (res1 == EQUAL) return true;
1154 
1155       Comparison_result res2 = compare_y(p, cv.right());
1156       return (res2 != LARGER);
1157     }
1158   };
1159 
1160   /*! Obtain an Is_in_y_range_2 functor object */
is_in_y_range_2_object()1161   Is_in_y_range_2 is_in_y_range_2_object() const
1162   { return Is_in_y_range_2(*this); }
1163 
1164   //@}
1165 };
1166 
1167 // Creation
1168 
1169 //! \brief constructs default.
1170 template <typename Kernel>
_Segment_cached_2()1171 Arr_segment_traits_2<Kernel>::_Segment_cached_2::_Segment_cached_2() :
1172   m_is_directed_right(false),
1173   m_is_vert(false),
1174   m_is_computed(false),
1175   m_is_degen(true)
1176 {}
1177 
1178 //! \brief constructs a segment from a Kernel segment.
1179 template <typename Kernel>
1180 Arr_segment_traits_2<Kernel>::
_Segment_cached_2(const Segment_2 & seg)1181 _Segment_cached_2::_Segment_cached_2(const Segment_2& seg) :
1182   m_is_vert(false),
1183   m_is_computed(false)
1184 {
1185   Kernel kernel;
1186   auto vertex_ctr = kernel.construct_vertex_2_object();
1187 
1188   m_ps = vertex_ctr(seg, 0);
1189   m_pt = vertex_ctr(seg, 1);
1190 
1191   Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt);
1192   m_is_degen = (res == EQUAL);
1193   m_is_directed_right = (res == SMALLER);
1194 
1195   CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment.");
1196 }
1197 
1198 //! \brief Constructs a segment from two endpoints.
1199 template <typename Kernel>
1200 Arr_segment_traits_2<Kernel>::
_Segment_cached_2(const Point_2 & source,const Point_2 & target)1201 _Segment_cached_2::_Segment_cached_2(const Point_2& source,
1202                                      const Point_2& target) :
1203   m_ps(source),
1204   m_pt(target),
1205   m_is_vert(false),
1206   m_is_computed(false)
1207 {
1208   Kernel kernel;
1209 
1210   Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt);
1211   m_is_degen = (res == EQUAL);
1212   m_is_directed_right = (res == SMALLER);
1213 
1214   CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment.");
1215 }
1216 
1217 //! \brief constructs a segment from two endpoints on a supporting line.
1218 template <typename Kernel>
1219 Arr_segment_traits_2<Kernel>::
_Segment_cached_2(const Line_2 & line,const Point_2 & source,const Point_2 & target)1220 _Segment_cached_2::_Segment_cached_2(const Line_2& line,
1221                                      const Point_2& source,
1222                                      const Point_2& target) :
1223   m_l(line),
1224   m_ps(source),
1225   m_pt(target)
1226 {
1227   Kernel kernel;
1228 
1229   CGAL_precondition
1230     (Segment_assertions::_assert_is_point_on(source, m_l,
1231                                              Has_exact_division()) &&
1232      Segment_assertions::_assert_is_point_on(target, m_l,
1233                                              Has_exact_division()));
1234 
1235   m_is_vert = kernel.is_vertical_2_object()(m_l);
1236   m_is_computed = true;
1237 
1238   Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt);
1239   m_is_degen = (res == EQUAL);
1240   m_is_directed_right = (res == SMALLER);
1241 
1242   CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment.");
1243 }
1244 
1245 //! \brief constructs a segment from all fields.
1246 template <typename Kernel>
1247 Arr_segment_traits_2<Kernel>::_Segment_cached_2::
_Segment_cached_2(const Line_2 & line,const Point_2 & source,const Point_2 & target,bool is_directed_right,bool is_vert,bool is_degen)1248 _Segment_cached_2(const Line_2& line,
1249                   const Point_2& source, const Point_2& target,
1250                   bool is_directed_right, bool is_vert, bool is_degen) :
1251   m_l(line),
1252   m_ps(source),
1253   m_pt(target),
1254   m_is_directed_right(is_directed_right),
1255   m_is_vert(is_vert),
1256   m_is_computed(true),
1257   m_is_degen(is_degen)
1258 {}
1259 
1260 //! \brief assigns.
1261 template <typename Kernel>
1262 const typename Arr_segment_traits_2<Kernel>::_Segment_cached_2&
1263 Arr_segment_traits_2<Kernel>::_Segment_cached_2::operator=(const Segment_2& seg)
1264 {
1265   Kernel kernel;
1266   auto vertex_ctr = kernel.construct_vertex_2_object();
1267 
1268   m_ps = vertex_ctr(seg, 0);
1269   m_pt = vertex_ctr(seg, 1);
1270 
1271   Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt);
1272   m_is_degen = (res == EQUAL);
1273   m_is_directed_right = (res == SMALLER);
1274 
1275   CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment.");
1276 
1277   m_l = kernel.construct_line_2_object()(seg);
1278   m_is_vert = kernel.is_vertical_2_object()(seg);
1279   m_is_computed = true;
1280 
1281   return (*this);
1282 }
1283 
1284 // Accessors
1285 
1286 //! \brief obtains the supporting line.
1287 template <typename Kernel>
1288 const typename Kernel::Line_2&
line()1289 Arr_segment_traits_2<Kernel>::_Segment_cached_2::line() const
1290 {
1291   if (!m_is_computed) {
1292     Kernel kernel;
1293     m_l = kernel.construct_line_2_object()(m_ps, m_pt);
1294     m_is_vert = kernel.is_vertical_2_object()(m_l);
1295     m_is_computed = true;
1296   }
1297   return m_l;
1298 }
1299 
1300 //! \brief determines whether the curve is vertical.
1301 template <typename Kernel>
is_vertical()1302 bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::is_vertical() const
1303 {
1304   // Force computation of line is orientation is still unknown
1305   if (! m_is_computed) line();
1306   CGAL_precondition(!m_is_degen);
1307   return m_is_vert;
1308 }
1309 
1310 //! \brief determines whether the curve is degenerate.
1311 template <typename Kernel>
is_degenerate()1312 bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::is_degenerate() const
1313 { return m_is_degen; }
1314 
1315 /*! \brief determines whether the curve is lexicographically directed from
1316  * left to right
1317  */
1318 template <typename Kernel>
is_directed_right()1319 bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::is_directed_right() const
1320 { return m_is_directed_right; }
1321 
1322 //! \brief obtain the segment source.
1323 template <typename Kernel>
1324 const typename Kernel::Point_2&
source()1325 Arr_segment_traits_2<Kernel>::_Segment_cached_2::source() const { return m_ps; }
1326 
1327 //! \brief obtains the segment target.
1328 template <typename Kernel>
1329 const typename Kernel::Point_2&
target()1330 Arr_segment_traits_2<Kernel>::_Segment_cached_2::target() const { return m_pt; }
1331 
1332 //! \brief obtains the (lexicographically) left endpoint.
1333 template <typename Kernel>
1334 const typename Kernel::Point_2&
left()1335 Arr_segment_traits_2<Kernel>::_Segment_cached_2::left() const
1336 { return (m_is_directed_right ? m_ps : m_pt); }
1337 
1338 //! \brief obtains the (lexicographically) right endpoint.
1339 template <typename Kernel>
1340 const typename Kernel::Point_2&
right()1341 Arr_segment_traits_2<Kernel>::_Segment_cached_2::right() const
1342 { return (m_is_directed_right ? m_pt : m_ps); }
1343 
1344 // Modifiers
1345 
1346 //! \brief sets the (lexicographically) left endpoint.
1347 template <typename Kernel>
set_left(const Point_2 & p)1348 void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_left(const Point_2& p)
1349 {
1350   CGAL_precondition(! m_is_degen);
1351   CGAL_precondition_code(Kernel kernel);
1352   CGAL_precondition
1353     (Segment_assertions::_assert_is_point_on(p, m_l, Has_exact_division()) &&
1354      (kernel.compare_xy_2_object()(p, right()) == SMALLER));
1355 
1356   if (m_is_directed_right) m_ps = p;
1357   else m_pt = p;
1358 }
1359 
1360 //! \brief sets the (lexicographically) right endpoint.
1361 template <typename Kernel>
set_right(const Point_2 & p)1362 void Arr_segment_traits_2<Kernel>::_Segment_cached_2::set_right(const Point_2& p)
1363 {
1364   CGAL_precondition(! m_is_degen);
1365   CGAL_precondition_code(Kernel kernel);
1366   CGAL_precondition
1367     (Segment_assertions::_assert_is_point_on(p, m_l, Has_exact_division()) &&
1368      (kernel.compare_xy_2_object()(p, left()) == LARGER));
1369 
1370   if (m_is_directed_right) m_pt = p;
1371   else m_ps = p;
1372 }
1373 
1374 //! \brief determines whether the given point is in the x-range of the segment.
1375 template <typename Kernel>
1376 bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::
is_in_x_range(const Point_2 & p)1377 is_in_x_range(const Point_2& p) const
1378 {
1379   Kernel kernel;
1380   typename Kernel::Compare_x_2 compare_x = kernel.compare_x_2_object();
1381   const Comparison_result res1 = compare_x(p, left());
1382 
1383   if (res1 == SMALLER) return false;
1384   else if (res1 == EQUAL) return true;
1385 
1386   const Comparison_result res2 = compare_x(p, right());
1387   return (res2 != LARGER);
1388 }
1389 
1390 //! \brief determines whether the given point is in the y-range of the segment.
1391 template <typename Kernel>
1392 bool Arr_segment_traits_2<Kernel>::_Segment_cached_2::
is_in_y_range(const Point_2 & p)1393 is_in_y_range(const Point_2& p) const
1394 {
1395   Kernel kernel;
1396   typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object();
1397   const Comparison_result res1 = compare_y(p, left());
1398 
1399   if (res1 == SMALLER) return false;
1400   else if (res1 == EQUAL) return true;
1401 
1402   const Comparison_result res2 = compare_y(p, right());
1403   return (res2 != LARGER);
1404 }
1405 
1406 /*! \class A representation of a segment, as used by the Arr_segment_traits_2
1407  * traits-class.
1408  */
1409 template <typename Kernel_>
1410 class Arr_segment_2 : public Arr_segment_traits_2<Kernel_>::_Segment_cached_2 {
1411   typedef Kernel_                                                  Kernel;
1412 
1413   typedef typename Arr_segment_traits_2<Kernel>::_Segment_cached_2 Base;
1414   typedef typename Kernel::Segment_2                               Segment_2;
1415   typedef typename Kernel::Point_2                                 Point_2;
1416   typedef typename Kernel::Line_2                                  Line_2;
1417 
1418 public:
1419   /*! Construct default. */
1420   Arr_segment_2();
1421 
1422   /*! Construct a segment from a "kernel" segment.
1423    * \param seg the segment.
1424    * \pre the segment is not degenerate.
1425    */
1426   Arr_segment_2(const Segment_2& seg);
1427 
1428   /*! Construct a segment from two endpoints.
1429    * \param source the source point.
1430    * \param target the target point.
1431    * \pre `source` and `target` are not equal.
1432    */
1433   Arr_segment_2(const Point_2& source, const Point_2& target);
1434 
1435   /*! Construct a segment from a line and two endpoints.
1436    * \param line the supporting line.
1437    * \param source the source point.
1438    * \param target the target point.
1439    * \pre Both `source` and `target` must be on `line`.
1440    * \pre `source` and `target` are not equal.
1441    */
1442   Arr_segment_2(const Line_2& line,
1443                 const Point_2& source, const Point_2& target);
1444 
1445   /*! Construct a segment from all fields.
1446    * \param line the supporting line.
1447    * \param source the source point.
1448    * \param target the target point.
1449    * \param is_directed_right is (lexicographically) directed left to right.
1450    * \param is_vert is the segment vertical.
1451    * \param is_degen is the segment degenerate (a single point).
1452    */
1453   Arr_segment_2(const Line_2& line,
1454                 const Point_2& source, const Point_2& target,
1455                 bool is_directed_right, bool is_vert, bool is_degen);
1456 
1457   /*! Cast to a segment.
1458    */
1459   operator Segment_2() const;
1460 
1461   /*! Flip the segment (swap its source and target).
1462    */
1463   Arr_segment_2 flip() const;
1464 
1465   /*! Create a bounding box for the segment.
1466    */
1467   Bbox_2 bbox() const;
1468 };
1469 
1470 //! \brief constructs default.
1471 template <typename Kernel>
Arr_segment_2()1472 Arr_segment_2<Kernel>::Arr_segment_2() : Base() {}
1473 
1474 //! \brief constructs from a "kernel" segment.
1475 template <typename Kernel>
Arr_segment_2(const Segment_2 & seg)1476 Arr_segment_2<Kernel>::Arr_segment_2(const Segment_2& seg) : Base(seg) {}
1477 
1478 //! \brief constructs a segment from two end-points.
1479 template <typename Kernel>
Arr_segment_2(const Point_2 & source,const Point_2 & target)1480 Arr_segment_2<Kernel>::Arr_segment_2(const Point_2& source,
1481                                      const Point_2& target) :
1482   Base(source, target)
1483 {}
1484 
1485 //! \brief constructs a segment from a line and two end-points.
1486 template <typename Kernel>
Arr_segment_2(const Line_2 & line,const Point_2 & source,const Point_2 & target)1487 Arr_segment_2<Kernel>::Arr_segment_2(const Line_2& line,
1488                                      const Point_2& source,
1489                                      const Point_2& target) :
1490   Base(line,source, target)
1491 {}
1492 
1493 //! \brief constructs a segment from all fields.
1494 template <typename Kernel>
Arr_segment_2(const Line_2 & line,const Point_2 & source,const Point_2 & target,bool is_directed_right,bool is_vert,bool is_degen)1495 Arr_segment_2<Kernel>::Arr_segment_2(const Line_2& line,
1496                                      const Point_2& source,
1497                                      const Point_2& target,
1498                                      bool is_directed_right,
1499                                      bool is_vert, bool is_degen) :
1500   Base(line, source, target, is_directed_right, is_vert, is_degen)
1501 {}
1502 
1503 //! \brief casts to a segment.
1504 template <typename Kernel>
Segment_2()1505 Arr_segment_2<Kernel>::operator typename Kernel::Segment_2() const
1506 {
1507   Kernel kernel;
1508   auto seg_ctr = kernel.construct_segment_2_object();
1509   return seg_ctr(this->source(), this->target());
1510 }
1511 
1512 //! \brief flips the segment (swap its source and target).
1513 template <typename Kernel>
flip()1514 Arr_segment_2<Kernel> Arr_segment_2<Kernel>::flip() const
1515 {
1516   return Arr_segment_2(this->line(), this->target(), this->source(),
1517                        ! (this->is_directed_right()), this->is_vertical(),
1518                        this->is_degenerate());
1519 }
1520 
1521 //! \brief creates a bounding box for the segment.
1522 template <typename Kernel>
bbox()1523 Bbox_2 Arr_segment_2<Kernel>::bbox() const
1524 {
1525   Kernel kernel;
1526   auto construct_bbox = kernel.construct_bbox_2_object();
1527   return construct_bbox(this->m_ps) + construct_bbox(this->m_pt);
1528 }
1529 
1530 /*! Exporter for the segment class used by the traits-class.
1531  */
1532 template <typename Kernel, typename OutputStream>
1533 OutputStream& operator<<(OutputStream& os, const Arr_segment_2<Kernel>& seg)
1534 {
1535   os << static_cast<typename Kernel::Segment_2>(seg);
1536   return (os);
1537 }
1538 
1539 /*! Importer for the segment class used by the traits-class.
1540  */
1541 template <typename Kernel, typename InputStream>
1542 InputStream& operator>>(InputStream& is, Arr_segment_2<Kernel>& seg)
1543 {
1544   typename Kernel::Segment_2   kernel_seg;
1545   is >> kernel_seg;
1546   seg = kernel_seg;
1547   return is;
1548 }
1549 
1550 } //namespace CGAL
1551 
1552 #include <CGAL/enable_warnings.h>
1553 
1554 #endif
1555