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