BWAPI
|
00001 // Copyright (c) 2005, 2009 Tel-Aviv University (Israel). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_traits_adaptor_2.h $ 00015 // $Id: Arr_traits_adaptor_2.h 49772 2009-06-03 21:25:53Z eric $ 00016 // $Date: 2009-06-03 23:25:53 +0200 (Wed, 03 Jun 2009) $ 00017 // 00018 // 00019 // Author(s) : Ron Wein <wein@post.tau.ac.il>s 00020 // Efi Fogel <efif@post.tau.ac.il> 00021 // Eric Berberich <ericb@post.tau.ac.il> 00022 // (based on old version by Iddo Hanniel 00023 // Eyal Flato 00024 // Oren Nechushtan 00025 // Efi Fogel 00026 // Ron Wein 00027 // Idit Haran) 00028 #ifndef CGAL_ARR_TRAITS_ADAPTOR_2_H 00029 #define CGAL_ARR_TRAITS_ADAPTOR_2_H 00030 00034 #include <CGAL/config.h> 00035 #include <CGAL/tags.h> 00036 #include <CGAL/Arr_enums.h> 00037 #include <CGAL/Arr_tags.h> 00038 #include <CGAL/Arrangement_2/Arr_traits_adaptor_2_dispatching.h> 00039 00040 CGAL_BEGIN_NAMESPACE 00041 00045 template <class ArrangementBasicTraits_> 00046 class Arr_traits_basic_adaptor_2 : public ArrangementBasicTraits_ 00047 { 00048 public: 00049 00050 // Traits-class geometric types. 00051 typedef ArrangementBasicTraits_ Base; 00052 typedef Arr_traits_basic_adaptor_2<Base> Self; 00053 typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; 00054 typedef typename Base::Point_2 Point_2; 00055 00056 // Tags. 00057 typedef typename Base::Has_left_category Has_left_category; 00058 00059 typedef typename CGALi::Arr_complete_left_side_tag< Base >::Tag 00060 Arr_left_side_tag; 00061 typedef typename CGALi::Arr_complete_bottom_side_tag< Base >::Tag 00062 Arr_bottom_side_tag; 00063 typedef typename CGALi::Arr_complete_top_side_tag< Base >::Tag 00064 Arr_top_side_tag; 00065 typedef typename CGALi::Arr_complete_right_side_tag< Base >::Tag 00066 Arr_right_side_tag; 00067 00068 protected: 00069 00070 // left-right dispatch 00071 00072 typedef CGAL::CGALi::Arr_left_right_implementation_dispatch< 00073 Arr_left_side_tag, Arr_right_side_tag > LR; 00074 00075 typedef typename LR::Parameter_space_in_x_2_curve_end_tag 00076 Psx_2_curve_end_tag; 00077 typedef typename LR::Parameter_space_in_x_2_curve_tag Psx_2_curve_tag; 00078 typedef typename LR::Parameter_space_in_x_2_point_tag Psx_2_point_tag; 00079 typedef typename LR::Compare_y_near_boundary_2_curve_ends_tag 00080 Cmp_y_nb_2_curve_ends_tag; 00081 typedef typename LR::Compare_y_on_boundary_2_points_tag 00082 Cmp_y_ob_2_points_tag; 00083 typedef typename LR::Is_on_y_identification_2_curve_tag Ioyi_2_curve_tag; 00084 typedef typename LR::Is_on_y_identification_2_point_tag Ioyi_2_point_tag; 00085 00086 00087 // bottom-top dispatch 00088 typedef CGAL::CGALi::Arr_bottom_top_implementation_dispatch< 00089 Arr_bottom_side_tag, Arr_top_side_tag > BT; 00090 00091 typedef typename BT::Parameter_space_in_y_2_curve_end_tag 00092 Psy_2_curve_end_tag; 00093 typedef typename BT::Parameter_space_in_y_2_curve_tag Psy_2_curve_tag; 00094 typedef typename BT::Parameter_space_in_y_2_point_tag Psy_2_point_tag; 00095 typedef typename BT::Compare_x_near_boundary_2_point_curve_end_tag 00096 Cmp_x_nb_2_point_curve_end_tag; 00097 typedef typename BT::Compare_x_near_boundary_2_curve_ends_tag 00098 Cmp_x_nb_2_curve_ends_tag; 00099 typedef typename BT::Compare_x_on_boundary_2_points_tag 00100 Cmp_x_ob_2_points_tag; 00101 typedef typename BT::Is_on_x_identification_2_curve_tag Ioxi_2_curve_tag; 00102 typedef typename BT::Is_on_x_identification_2_point_tag Ioxi_2_point_tag; 00103 00104 public: 00105 00107 00108 00109 Arr_traits_basic_adaptor_2 () : 00110 Base() 00111 {} 00112 00114 Arr_traits_basic_adaptor_2 (const Base& traits) : 00115 Base (traits) 00116 {} 00118 00119 // Inherited functors: 00120 typedef typename Base::Compare_x_2 Compare_x_2; 00121 typedef typename Base::Compare_xy_2 Compare_xy_2; 00122 typedef typename Base::Compare_y_at_x_2 Compare_y_at_x_2; 00123 typedef typename Base::Construct_min_vertex_2 Construct_min_vertex_2; 00124 typedef typename Base::Construct_max_vertex_2 Construct_max_vertex_2; 00125 typedef typename Base::Is_vertical_2 Is_vertical_2; 00126 typedef typename Base::Compare_y_at_x_right_2 Compare_y_at_x_right_2; 00127 typedef typename Base::Equal_2 Equal_2; 00128 00130 00131 00135 class Compare_y_at_x_left_2 { 00136 public: 00147 Comparison_result operator() (const X_monotone_curve_2& xcv1, 00148 const X_monotone_curve_2& xcv2, 00149 const Point_2& p) const 00150 { 00151 // The function is implemented based on the Has_left category. If the 00152 // category indicates that the "left" version is available, it calls the 00153 // function with same name defined in the base class. Otherwise, it 00154 // uses other predicates to provide this comparison. 00155 return _compare_y_at_x_left_imp (xcv1, xcv2, p, Has_left_category()); 00156 } 00157 00158 protected: 00160 const Self *m_self; 00161 00169 Compare_y_at_x_left_2 (const Self * self) : m_self (self) {} 00170 00172 friend class Arr_traits_basic_adaptor_2<Base>; 00173 00177 Comparison_result _compare_y_at_x_left_imp (const X_monotone_curve_2& xcv1, 00178 const X_monotone_curve_2& xcv2, 00179 const Point_2& p, 00180 Tag_true) const 00181 { 00182 const Base *base = m_self; 00183 return (base->compare_y_at_x_left_2_object() (xcv1, xcv2, p)); 00184 } 00185 00189 Comparison_result _compare_y_at_x_left_imp (const X_monotone_curve_2& xcv1, 00190 const X_monotone_curve_2& xcv2, 00191 const Point_2& p, 00192 Tag_false) const 00193 { 00194 Parameter_space_in_x_2 ps_x = m_self->parameter_space_in_x_2_object(); 00195 Parameter_space_in_y_2 ps_y = m_self->parameter_space_in_y_2_object(); 00196 Construct_min_vertex_2 min_vertex = 00197 m_self->construct_min_vertex_2_object(); 00198 Equal_2 equal = m_self->equal_2_object(); 00199 00200 // Check if the left ends of the curves are bounded endpoints. 00201 const Arr_parameter_space ps_x1 = ps_x (xcv1, ARR_MIN_END); 00202 const Arr_parameter_space ps_y1 = 00203 (ps_x1 != ARR_INTERIOR ? ARR_INTERIOR : ps_y (xcv1, ARR_MIN_END)); 00204 const bool has_left1 = (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR); 00205 00206 const Arr_parameter_space ps_x2 = ps_x (xcv2, ARR_MIN_END); 00207 const Arr_parameter_space ps_y2 = 00208 (ps_x2 != ARR_INTERIOR ? ARR_INTERIOR : ps_y (xcv2, ARR_MIN_END)); 00209 const bool has_left2 = (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR); 00210 00211 CGAL_assertion (ps_x1 != ARR_RIGHT_BOUNDARY && 00212 ps_x2 != ARR_RIGHT_BOUNDARY); 00213 00214 // Make sure that p lies on both curves, and that both are defined to its 00215 // right (so their right endpoint is lexicographically larger than p). 00216 CGAL_precondition_code ( 00217 Compare_xy_2 compare_xy = m_self->compare_xy_2_object(); 00218 Compare_y_at_x_2 compare_y_at_x = m_self->compare_y_at_x_2_object(); 00219 ); 00220 00221 CGAL_precondition (compare_y_at_x (p, xcv1) == EQUAL && 00222 compare_y_at_x (p, xcv2) == EQUAL); 00223 00224 CGAL_precondition ((! has_left1 || 00225 compare_xy(min_vertex (xcv1), p) == SMALLER) && 00226 (! has_left2 || 00227 compare_xy(min_vertex (xcv2), p) == SMALLER)); 00228 00229 // If one of the curves is vertical, it is below the other one. 00230 Is_vertical_2 is_vertical = m_self->is_vertical_2_object(); 00231 00232 if (is_vertical(xcv1)) 00233 { 00234 return (is_vertical (xcv2)) ? EQUAL : SMALLER; 00235 } 00236 else if (is_vertical (xcv2)) 00237 { 00238 return (LARGER); 00239 } 00240 00241 // Perform the comparison based on the existance of bounded left 00242 // endpoints. 00243 if (has_left1 && has_left2) 00244 { 00245 // Get the left endpoints of xcv1 and xcv2. 00246 Point_2 left1 = min_vertex(xcv1); 00247 Point_2 left2 = min_vertex(xcv2); 00248 00249 if (equal (left1, left2)) 00250 { 00251 // The two curves have a common left endpoint: 00252 // Compare them to the right of this point. 00253 return (m_self->compare_y_at_x_right_2_object() (xcv1, xcv2, left1)); 00254 } 00255 } 00256 00257 // We now that the curves do not share a common endpoint, and we can 00258 // compare their relative y-position (which does not change to the left 00259 // of the given point p). 00260 return (m_self->compare_y_position_2_object() (xcv1, xcv2)); 00261 } 00262 }; 00263 00265 Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const 00266 { 00267 return Compare_y_at_x_left_2(this); 00268 } 00269 00271 00273 00274 00278 class Parameter_space_in_x_2 { 00279 public: 00280 00288 Arr_parameter_space operator() (const X_monotone_curve_2& xcv, 00289 Arr_curve_end ind) const 00290 { 00291 // The function is implemented based on the tag dispatching 00292 // If the traits class does not support special boundaries, we just 00293 // return ARR_INTERIOR. 00294 return parameter_space_in_x (xcv, ind, Psx_2_curve_end_tag()); 00295 } 00296 00302 Arr_parameter_space operator() (const X_monotone_curve_2& xcv) const 00303 { 00304 // The function is implemented based on the tag dispatching. 00305 // If the traits class does not support special boundaries, we just 00306 // return ARR_INTERIOR. 00307 return parameter_space_in_x (xcv, Psx_2_curve_tag()); 00308 } 00309 00315 Arr_parameter_space operator() (const Point_2 & p) const 00316 { 00317 // The function is implemented based on the tag dispatching 00318 // If the traits class does not support special boundaries, we just 00319 // return ARR_INTERIOR. 00320 return parameter_space_in_x (p, Psx_2_point_tag()); 00321 } 00322 00323 00324 protected: 00326 const Base * m_base; 00327 00335 Parameter_space_in_x_2 (const Base * base) : m_base (base) {} 00336 00338 friend class Arr_traits_basic_adaptor_2<Base>; 00339 00343 Arr_parameter_space parameter_space_in_x ( 00344 const X_monotone_curve_2& xcv, 00345 Arr_curve_end ind, 00346 Arr_use_traits_tag) const 00347 { 00348 return (m_base->parameter_space_in_x_2_object() (xcv, ind)); 00349 } 00350 00354 Arr_parameter_space parameter_space_in_x ( 00355 const X_monotone_curve_2&, 00356 Arr_curve_end, 00357 Arr_use_dummy_tag) const 00358 { 00359 return ARR_INTERIOR; 00360 } 00361 00365 Arr_parameter_space parameter_space_in_x ( 00366 const X_monotone_curve_2& xcv, 00367 Arr_use_traits_tag) const 00368 { 00369 return (m_base->parameter_space_in_x_2_object() (xcv)); 00370 } 00371 00375 Arr_parameter_space parameter_space_in_x ( 00376 const X_monotone_curve_2&, 00377 Arr_use_dummy_tag) const 00378 { 00379 return ARR_INTERIOR; 00380 } 00381 00385 Arr_parameter_space parameter_space_in_x (const Point_2 & p, 00386 Arr_use_traits_tag) const 00387 { 00388 return m_base->parameter_space_in_x_2_object() (p); 00389 } 00390 00394 Arr_parameter_space parameter_space_in_x (const Point_2 &, 00395 Arr_use_dummy_tag) const 00396 { 00397 return ARR_INTERIOR; 00398 } 00399 }; 00400 00402 Parameter_space_in_x_2 parameter_space_in_x_2_object () const 00403 { 00404 return Parameter_space_in_x_2(this); 00405 } 00406 00407 00408 00412 class Parameter_space_in_y_2 { 00413 public: 00421 Arr_parameter_space operator() (const X_monotone_curve_2& xcv, 00422 Arr_curve_end ind) const 00423 { 00424 // The function is implemented based on the tag dispatching. 00425 // If the traits class does not support special boundaries, we just 00426 // return ARR_INTERIOR. 00427 return parameter_space_in_y(xcv, ind, Psy_2_curve_end_tag()); 00428 } 00429 00435 Arr_parameter_space operator() (const X_monotone_curve_2& xcv) const 00436 { 00437 // The function is implemented based on the tag dispatching. 00438 // If the traits class does not support special boundaries, we just 00439 // return ARR_INTERIOR. 00440 return parameter_space_in_y (xcv, Psy_2_curve_tag()); 00441 } 00442 00448 Arr_parameter_space operator()(const Point_2 & p) const 00449 { 00450 return parameter_space_in_y(p, Psy_2_point_tag()); 00451 } 00452 00453 protected: 00455 const Base * m_base; 00456 00464 Parameter_space_in_y_2 (const Base * base) : m_base (base) {} 00465 00467 friend class Arr_traits_basic_adaptor_2<Base>; 00468 00472 Arr_parameter_space parameter_space_in_y ( 00473 const X_monotone_curve_2& xcv, 00474 Arr_curve_end ind, 00475 Arr_use_traits_tag) const 00476 { 00477 return m_base->parameter_space_in_y_2_object() (xcv, ind); 00478 } 00479 00483 Arr_parameter_space parameter_space_in_y ( 00484 const X_monotone_curve_2 &, 00485 Arr_curve_end, 00486 Arr_use_dummy_tag) const 00487 { 00488 return ARR_INTERIOR; 00489 } 00490 00494 Arr_parameter_space parameter_space_in_y ( 00495 const X_monotone_curve_2& xcv, 00496 Arr_use_traits_tag) const 00497 { 00498 return (m_base->parameter_space_in_x_2_object() (xcv)); 00499 } 00500 00504 Arr_parameter_space parameter_space_in_y ( 00505 const X_monotone_curve_2&, 00506 Arr_use_dummy_tag) const 00507 { 00508 return ARR_INTERIOR; 00509 } 00510 00514 Arr_parameter_space parameter_space_in_y (const Point_2 & p, 00515 Arr_use_traits_tag) const 00516 { 00517 return m_base->parameter_space_in_y_2_object()(p); 00518 } 00519 00523 Arr_parameter_space parameter_space_in_y (const Point_2 &, 00524 Arr_use_dummy_tag) const 00525 { 00526 return ARR_INTERIOR; 00527 } 00528 }; 00529 00531 Parameter_space_in_y_2 parameter_space_in_y_2_object() const 00532 { 00533 return Parameter_space_in_y_2(this); 00534 } 00535 00539 class Compare_x_near_boundary_2 { 00540 protected: 00542 const Base * m_base; 00543 00551 Compare_x_near_boundary_2(const Base * base) : m_base(base) {} 00552 00554 friend class Arr_traits_basic_adaptor_2<Base>; 00555 00559 Comparison_result _compare_point_curve ( 00560 const Point_2 & p, 00561 const X_monotone_curve_2 & xcv, 00562 Arr_curve_end ce, 00563 Arr_use_traits_tag) const 00564 { 00565 return (m_base->compare_x_near_boundary_2_object()(p, xcv, ce)); 00566 } 00567 00571 Comparison_result _compare_point_curve(const Point_2 &, 00572 const X_monotone_curve_2 &, 00573 Arr_curve_end, 00574 Arr_use_dummy_tag) const 00575 { 00576 CGAL_error(); 00577 return EQUAL; 00578 } 00579 00583 Comparison_result _compare_curves (const X_monotone_curve_2 & xcv1, 00584 Arr_curve_end ce1, 00585 const X_monotone_curve_2 & xcv2, 00586 Arr_curve_end ce2, 00587 Arr_use_traits_tag) const 00588 { 00589 return m_base->compare_x_near_boundary_2_object()(xcv1, ce1, xcv2, ce2); 00590 } 00591 00595 Comparison_result _compare_curves (const X_monotone_curve_2 &, 00596 Arr_curve_end, 00597 const X_monotone_curve_2 &, 00598 Arr_curve_end, 00599 Arr_use_dummy_tag) const 00600 { 00601 CGAL_error(); 00602 return EQUAL; 00603 } 00604 00605 public: 00617 Comparison_result operator() (const Point_2 & p, 00618 const X_monotone_curve_2 & xcv, 00619 Arr_curve_end ce) const 00620 { 00621 return _compare_point_curve(p, xcv, ce, 00622 Cmp_x_nb_2_point_curve_end_tag()); 00623 } 00624 00637 Comparison_result operator() (const X_monotone_curve_2 & xcv1, 00638 Arr_curve_end ce1, 00639 const X_monotone_curve_2 & xcv2, 00640 Arr_curve_end ce2) const 00641 { 00642 return _compare_curves(xcv1, ce1, xcv2, ce2, 00643 Cmp_x_nb_2_curve_ends_tag()); 00644 } 00645 }; 00646 00648 Compare_x_near_boundary_2 compare_x_near_boundary_2_object () const 00649 { 00650 return Compare_x_near_boundary_2(this); 00651 } 00652 00656 class Compare_y_near_boundary_2 { 00657 protected: 00659 const Base * m_base; 00660 00668 Compare_y_near_boundary_2(const Base * base) : m_base(base) {} 00669 00671 friend class Arr_traits_basic_adaptor_2<Base>; 00672 00676 Comparison_result comp_y_near_bnd (const X_monotone_curve_2 & xcv1, 00677 const X_monotone_curve_2 & xcv2, 00678 Arr_curve_end ce, 00679 Arr_use_traits_tag) const 00680 { 00681 return m_base->compare_y_near_boundary_2_object()(xcv1, xcv2, ce); 00682 } 00683 00687 Comparison_result comp_y_near_bnd (const X_monotone_curve_2 &, 00688 const X_monotone_curve_2 &, 00689 Arr_curve_end, 00690 Arr_use_dummy_tag) const 00691 { 00692 CGAL_error(); 00693 return EQUAL; 00694 } 00695 00696 public: 00707 Comparison_result operator() (const X_monotone_curve_2 & xcv1, 00708 const X_monotone_curve_2 & xcv2, 00709 Arr_curve_end ce) const 00710 { 00711 // The function is implemented based on the tag disatching 00712 // If the traits class does not support open curves, we just 00713 // return EQUAL, as this comparison will not be invoked anyway. 00714 return comp_y_near_bnd (xcv1, xcv2, ce, Cmp_y_nb_2_curve_ends_tag()); 00715 } 00716 }; 00717 00719 Compare_y_near_boundary_2 compare_y_near_boundary_2_object () const 00720 { 00721 return Compare_y_near_boundary_2(this); 00722 } 00723 00727 class Compare_x_on_boundary_2 { 00728 protected: 00730 const Base * m_base; 00731 00739 Compare_x_on_boundary_2(const Base * base) : m_base(base) {} 00740 00742 friend class Arr_traits_basic_adaptor_2<Base>; 00743 00744 public: 00750 Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const 00751 { 00752 return comp_x_on_bnd (p1, p2, Cmp_x_ob_2_points_tag()); 00753 } 00754 00755 private: 00756 Comparison_result comp_x_on_bnd (const Point_2 & p1, const Point_2 & p2, 00757 Arr_use_traits_tag) const 00758 { 00759 return m_base->compare_x_on_boundary_2_object ()(p1, p2); 00760 } 00761 00762 Comparison_result comp_x_on_bnd (const Point_2 &, const Point_2 &, 00763 Arr_use_dummy_tag) const 00764 { 00765 CGAL_error(); 00766 return SMALLER; 00767 } 00768 }; 00769 00771 Compare_x_on_boundary_2 compare_x_on_boundary_2_object () const 00772 { 00773 return Compare_x_on_boundary_2(this); 00774 } 00775 00779 class Compare_y_on_boundary_2 { 00780 protected: 00782 const Base * m_base; 00783 00791 Compare_y_on_boundary_2(const Base * base) : m_base(base) {} 00792 00794 friend class Arr_traits_basic_adaptor_2<Base>; 00795 00799 Comparison_result comp_y_on_bnd (const Point_2 & p1, const Point_2 & p2, 00800 Arr_use_traits_tag) const 00801 { 00802 return m_base->compare_y_on_boundary_2_object()(p1, p2); 00803 } 00804 00808 Comparison_result comp_y_on_bnd (const Point_2 &, const Point_2 &, 00809 Arr_use_dummy_tag) const 00810 { 00811 CGAL_error(); 00812 return SMALLER; 00813 } 00814 00815 public: 00824 Comparison_result operator() (const Point_2 & p1, const Point_2 & p2) const 00825 { 00826 // The function is implemented based on the tag dispatching. 00827 // If the traits class does not support open curves, we just 00828 // return EQUAL, as this comparison will not be invoked anyway. 00829 return comp_y_on_bnd (p1, p2, Cmp_y_ob_2_points_tag()); 00830 } 00831 }; 00832 00834 Compare_y_on_boundary_2 compare_y_on_boundary_2_object() const 00835 { 00836 return Compare_y_on_boundary_2(this); 00837 } 00838 00842 class Is_on_x_identification_2 { 00843 protected: 00845 const Base * m_base; 00846 00854 Is_on_x_identification_2 (const Base * base) : m_base(base) {} 00855 00857 friend class Arr_traits_basic_adaptor_2<Base>; 00858 00859 public: 00865 bool operator() (const Point_2 & p) const 00866 { 00867 return is_on_idn (p, Ioxi_2_point_tag()); 00868 } 00869 00876 bool operator()(const X_monotone_curve_2 & xcv) const 00877 { 00878 return is_on_idn (xcv, Ioxi_2_curve_tag()); 00879 } 00880 00881 private: 00882 bool is_on_x_idn (const Point_2 & p, Arr_use_traits_tag) const 00883 { 00884 return m_base->is_on_x_identification_2_object ()(p); 00885 } 00886 00887 bool is_on_x_idn (const Point_2 &, Arr_use_dummy_tag) const 00888 { 00889 CGAL_error(); 00890 return SMALLER; 00891 } 00892 00893 bool is_on_x_idn (const X_monotone_curve_2 & xcv, 00894 Arr_use_traits_tag) const 00895 { 00896 return m_base->is_on_x_identification_2_object ()(xcv); 00897 } 00898 00899 bool is_on_x_idn (const X_monotone_curve_2 &, 00900 Arr_use_dummy_tag) const 00901 { 00902 CGAL_error(); 00903 return SMALLER; 00904 } 00905 }; 00906 00908 Is_on_x_identification_2 is_on_x_identification_2_object() const 00909 { 00910 return Is_on_x_identification_2(this); 00911 } 00912 00916 class Is_on_y_identification_2 { 00917 protected: 00919 const Base * m_base; 00920 00928 Is_on_y_identification_2 (const Base * base) : m_base(base) {} 00929 00931 friend class Arr_traits_basic_adaptor_2<Base>; 00932 00933 public: 00939 bool operator() (const Point_2 & p) const 00940 { 00941 return is_on_y_idn (p, Ioyi_2_point_tag()); 00942 } 00943 00950 bool operator()(const X_monotone_curve_2 & xcv) const 00951 { 00952 return is_on_y_idn (xcv, Ioyi_2_curve_tag()); 00953 } 00954 00955 private: 00956 bool is_on_y_idn (const Point_2 & p, Arr_use_traits_tag) const 00957 { 00958 return m_base->is_on_identification_2_object ()(p); 00959 } 00960 00961 bool is_on_y_idn (const Point_2 &, Arr_use_dummy_tag) const 00962 { 00963 CGAL_error(); 00964 return SMALLER; 00965 } 00966 00967 bool is_on_y_idn (const X_monotone_curve_2 & xcv, 00968 Arr_use_traits_tag) const 00969 { 00970 return m_base->is_on_identification_2_object ()(xcv); 00971 } 00972 00973 bool is_on_y_idn (const X_monotone_curve_2 &, 00974 Arr_use_dummy_tag) const 00975 { 00976 CGAL_error(); 00977 return SMALLER; 00978 } 00979 }; 00980 00982 Is_on_y_identification_2 is_on_y_identification_2_object() const 00983 { 00984 return Is_on_y_identification_2(this); 00985 } 00986 00988 class Is_closed_2 { 00989 protected: 00991 const Self * m_self; 00992 01000 Is_closed_2(const Self * self) : m_self(self) {} 01001 01003 friend class Arr_traits_basic_adaptor_2<Base>; 01004 01005 bool _is_closed(Arr_boundary_side_tag) const 01006 { 01007 return true; 01008 } 01009 01010 bool _is_closed(Arr_open_side_tag) const 01011 { 01012 return false; 01013 } 01014 01015 bool _is_closed(const X_monotone_curve_2 & xcv, Arr_curve_end ce) const 01016 { 01017 Arr_parameter_space ps = 01018 m_self->parameter_space_in_x_2_object()(xcv, ce); 01019 if (ARR_INTERIOR == ps) { 01020 ps = m_self->parameter_space_in_y_2_object()(xcv, ce); 01021 } 01022 01023 switch (ps) { 01024 01025 case ARR_LEFT_BOUNDARY: 01026 return _is_closed(Arr_left_side_tag()); 01027 01028 case ARR_BOTTOM_BOUNDARY: 01029 return _is_closed(Arr_bottom_side_tag()); 01030 01031 case ARR_TOP_BOUNDARY: 01032 return _is_closed(Arr_top_side_tag()); 01033 01034 case ARR_RIGHT_BOUNDARY: 01035 return _is_closed(Arr_right_side_tag()); 01036 01037 case ARR_INTERIOR: 01038 // fall-through 01039 default: 01040 return true; 01041 } 01042 } 01043 01044 public: 01050 bool operator() (const X_monotone_curve_2 & xcv, Arr_curve_end ce) const 01051 { 01052 return _is_closed(xcv, ce); 01053 } 01054 }; 01055 01057 Is_closed_2 is_closed_2_object() const 01058 { 01059 return Is_closed_2(this); 01060 } 01061 01063 01065 01066 class Is_in_x_range_2 { 01067 public: 01075 bool operator() (const X_monotone_curve_2& xcv, const Point_2& p) const 01076 { 01077 Parameter_space_in_x_2 ps_x = m_self->parameter_space_in_x_2_object(); 01078 Parameter_space_in_y_2 ps_y = m_self->parameter_space_in_y_2_object(); 01079 Compare_x_2 compare_x = m_self->compare_x_2_object(); 01080 Compare_x_near_boundary_2 01081 compare_x_near_bnd = m_self->compare_x_near_boundary_2_object(); 01082 01083 // Compare p to the position of the left end of the curve. 01084 // Note that if the left end of xcv lies at x boundary, p is obviously to 01085 // its right. 01086 Arr_parameter_space bx, by; 01087 Comparison_result res; 01088 01089 bx = ps_x (xcv, ARR_MIN_END); 01090 01091 if (bx == ARR_INTERIOR) { 01092 by = ps_y (xcv, ARR_MIN_END); 01093 01094 res = (by == ARR_INTERIOR) ? 01095 // The left endpoint of xcv is a normal point. 01096 compare_x (p, m_self->construct_min_vertex_2_object() (xcv)) : 01097 // The left end of xcv lies at y boundary. 01098 compare_x_near_bnd (p, xcv, ARR_MIN_END); 01099 01100 if (res == SMALLER) 01101 return (false); // p is to the left of the x-range. 01102 else if (res == EQUAL) 01103 return (true); 01104 } 01105 01106 // If necessary, compare p to the right end of the curve. 01107 // Note that if this end lies at x boundary, p is obviously to its left. 01108 bx = ps_x (xcv, ARR_MAX_END); 01109 01110 if (bx != ARR_INTERIOR) 01111 return (true); 01112 01113 by = ps_y (xcv, ARR_MAX_END); 01114 01115 res = (by == ARR_INTERIOR) ? 01116 // The right endpoint of xcv is a normal point. 01117 compare_x (p, m_self->construct_max_vertex_2_object() (xcv)) : 01118 // The right end of xcv lies at y boundary: 01119 compare_x_near_bnd (p, xcv, ARR_MAX_END); 01120 01121 return (res != LARGER); 01122 } 01123 01131 bool operator() (const X_monotone_curve_2& xcv1, 01132 const X_monotone_curve_2& xcv2) const 01133 { 01134 Parameter_space_in_x_2 ps_x = m_self->parameter_space_in_x_2_object(); 01135 Parameter_space_in_y_2 ps_y = m_self->parameter_space_in_y_2_object(); 01136 Compare_x_2 compare_x = m_self->compare_x_2_object(); 01137 Construct_min_vertex_2 min_vertex = 01138 m_self->construct_min_vertex_2_object(); 01139 Construct_max_vertex_2 max_vertex = 01140 m_self->construct_max_vertex_2_object(); 01141 Compare_x_near_boundary_2 compare_x_near_bnd = 01142 m_self->compare_x_near_boundary_2_object(); 01143 01144 // Locate the rightmost of the two left endpoints of the two curves. 01145 // Note that we guard for curve ends with special boundary. 01146 Arr_parameter_space ps_x1, ps_y1; 01147 Arr_parameter_space ps_x2, ps_y2; 01148 const X_monotone_curve_2 *xcv_left; 01149 Arr_parameter_space by_left; 01150 Comparison_result res; 01151 01152 ps_x1 = ps_x (xcv1, ARR_MIN_END); 01153 ps_x2 = ps_x (xcv2, ARR_MIN_END); 01154 01155 if (ps_x1 != ARR_INTERIOR) { 01156 // If both curves are defined at x boundary, they obviously overlap in 01157 // their x-ranges. 01158 if (ps_x2 != ARR_INTERIOR) 01159 return (true); 01160 01161 // As xcv2 is not defined at x boundary, take its left end as the 01162 // rightmost of the two left curve ends. 01163 xcv_left = &xcv2; 01164 by_left = ps_y (xcv2, ARR_MIN_END); 01165 } 01166 else if (ps_x2 != ARR_INTERIOR) { 01167 // As xcv1 is not defined at x boundary, take its left end as the 01168 // rightmost of the two left curve ends. 01169 xcv_left = &xcv1; 01170 by_left = ps_y (xcv1, ARR_MIN_END); 01171 } 01172 else { 01173 // Compare the (finite) x-coordinates of the two left ends. 01174 // We take special care of the case of boundaries in y. 01175 ps_y1 = ps_y (xcv1, ARR_MIN_END); 01176 ps_y2 = ps_y (xcv2, ARR_MIN_END); 01177 01178 if (ps_y1 == ARR_INTERIOR) { 01179 res = (ps_y2 == ARR_INTERIOR) ? 01180 compare_x (min_vertex (xcv1), min_vertex (xcv2)) : 01181 compare_x_near_bnd (min_vertex (xcv1), xcv2, ARR_MIN_END); 01182 } 01183 else { 01184 res = (ps_y2 == ARR_INTERIOR) ? 01185 opposite(compare_x_near_bnd (min_vertex (xcv2), xcv1, ARR_MIN_END)): 01186 compare_x_near_bnd (xcv1, ARR_MIN_END, xcv2, ARR_MIN_END); 01187 } 01188 01189 if (res == LARGER) { 01190 xcv_left = &xcv1; 01191 by_left = ps_y1; 01192 } 01193 else { 01194 xcv_left = &xcv2; 01195 by_left = ps_y2; 01196 } 01197 } 01198 01199 // Locate the leftmost of the two right endpoints of the two curves. 01200 // Note that we guard for curve ends with special boundary. 01201 const X_monotone_curve_2 *xcv_right; 01202 Arr_parameter_space by_right; 01203 01204 ps_x1 = ps_x (xcv1, ARR_MAX_END); 01205 ps_x2 = ps_x (xcv2, ARR_MAX_END); 01206 01207 if (ps_x1 != ARR_INTERIOR) { 01208 // If both curves are defined at x boundary, they obviously overlap in 01209 // their x-ranges. 01210 if (ps_x2 != ARR_INTERIOR) 01211 return (true); 01212 01213 // As xcv2 is not defined at x boundary, take its right end as the 01214 // leftmost of the two right curve ends. 01215 xcv_right = &xcv2; 01216 by_right = ps_y (xcv2, ARR_MAX_END); 01217 } 01218 else if (ps_x2 != ARR_INTERIOR) { 01219 // As xcv1 is not defined at x boundary, take its right end as the 01220 // leftmost of the two right curve ends. 01221 xcv_right = &xcv1; 01222 by_right = ps_y (xcv1, ARR_MAX_END); 01223 } 01224 else { 01225 // Compare the (finite) x-coordinates of the two right ends. 01226 // We take special care of the case of boundaries in y. 01227 ps_y1 = ps_y (xcv1, ARR_MAX_END); 01228 ps_y2 = ps_y (xcv2, ARR_MAX_END); 01229 01230 if (ps_y1 == ARR_INTERIOR) { 01231 res = (ps_y2 == ARR_INTERIOR) ? 01232 compare_x (max_vertex (xcv1), max_vertex (xcv2)) : 01233 compare_x_near_bnd (max_vertex (xcv1), xcv2, ARR_MAX_END); 01234 } 01235 else { 01236 res = (ps_y2 == ARR_INTERIOR) ? 01237 opposite(compare_x_near_bnd (max_vertex (xcv2), xcv1, ARR_MAX_END)): 01238 compare_x_near_bnd (xcv1, ARR_MAX_END, xcv2, ARR_MAX_END); 01239 } 01240 01241 if (res == SMALLER) { 01242 xcv_right = &xcv1; 01243 by_right = ps_y1; 01244 } 01245 else { 01246 xcv_right = &xcv2; 01247 by_right = ps_y2; 01248 } 01249 } 01250 01251 // Now compare the (finite) x-coordiates of the left end of xcv_left and 01252 // the right end of xcv_right. 01253 if (by_left == ARR_INTERIOR) { 01254 res = (by_right == ARR_INTERIOR) ? 01255 compare_x (min_vertex (*xcv_left), max_vertex (*xcv_right)) : 01256 compare_x_near_bnd (min_vertex (*xcv_left), *xcv_right, ARR_MAX_END); 01257 } 01258 else { 01259 res = (by_right == ARR_INTERIOR) ? 01260 opposite(compare_x_near_bnd (max_vertex (*xcv_right), 01261 *xcv_left, ARR_MIN_END)) : 01262 compare_x_near_bnd (*xcv_left, ARR_MIN_END, *xcv_right, ARR_MAX_END); 01263 } 01264 01265 // The two curves overlap in their x-range if and only if the left end 01266 // of xcv_left is not to the right if the right end of xcv_right. 01267 return (res != LARGER); 01268 } 01269 01270 protected: 01272 const Self *m_self; 01273 01281 Is_in_x_range_2(const Self * self) : m_self (self) {} 01282 01284 friend class Arr_traits_basic_adaptor_2<Base>; 01285 }; 01286 01288 Is_in_x_range_2 is_in_x_range_2_object () const 01289 { 01290 return Is_in_x_range_2(this); 01291 } 01292 01293 class Compare_y_position_2 { 01294 public: 01305 Comparison_result operator() (const X_monotone_curve_2& xcv1, 01306 const X_monotone_curve_2& xcv2) const 01307 { 01308 CGAL_precondition_code ( 01309 Is_in_x_range_2 is_in_x_range = m_self->is_in_x_range_2_object(); 01310 ); 01311 CGAL_precondition (is_in_x_range (xcv1, xcv2)); 01312 01313 /* The traits class which the basic traits adaptor accepts as a template 01314 * parameter is a model of the ArrangementBasicTraits_2 concept so it 01315 * needs not to support intersections at all, therefor it is complicated 01316 * to check if the x-curves are disjoint in their interiors. Moreover, 01317 * compare_y_position functor is called only from the arrangement class 01318 * itself (and some related point-location algorithms), and used only 01319 * for two curves associated with two arrangement halfedges. These curves 01320 * are guaranteed to be interior-disjoint. So, it seems that there is no 01321 * gain in checking the precondition, and it is left unimplemented. 01322 */ 01323 01324 Parameter_space_in_x_2 ps_x = m_self->parameter_space_in_x_2_object(); 01325 Parameter_space_in_y_2 ps_y = m_self->parameter_space_in_y_2_object(); 01326 Compare_y_at_x_2 compare_y_at_x = m_self->compare_y_at_x_2_object(); 01327 Construct_min_vertex_2 min_vertex = 01328 m_self->construct_min_vertex_2_object(); 01329 Compare_x_near_boundary_2 01330 compare_x_near_bnd = m_self->compare_x_near_boundary_2_object(); 01331 Compare_y_near_boundary_2 01332 compare_y_near_bnd = m_self->compare_y_near_boundary_2_object(); 01333 01334 // First check whether any of the curves is defined at x boundary. 01335 const Arr_parameter_space ps_x1 = ps_x (xcv1, ARR_MIN_END); 01336 const Arr_parameter_space ps_x2 = ps_x (xcv2, ARR_MIN_END); 01337 Comparison_result res; 01338 01339 CGAL_assertion (ps_x1 != ARR_RIGHT_BOUNDARY && 01340 ps_x2 != ARR_RIGHT_BOUNDARY); 01341 01342 if (ps_x1 != ARR_INTERIOR) 01343 { 01344 if (ps_x2 != ARR_INTERIOR) 01345 { 01346 // Compare the relative position of the curves at x boundary. 01347 return (compare_y_near_bnd(xcv1, xcv2, ARR_MIN_END)); 01348 } 01349 01350 // Check if the left end of xcv2 lies at y boundary. 01351 const Arr_parameter_space ps_y2 = ps_y (xcv2, ARR_MIN_END); 01352 01353 if (ps_y2 == ARR_BOTTOM_BOUNDARY) 01354 return (LARGER); // xcv2 is obviously below xcv1. 01355 else if (ps_y2 == ARR_TOP_BOUNDARY) 01356 return (SMALLER); // xcv2 is obviously above xcv1. 01357 01358 // Compare the position of the left end of xcv2 (which is a normal 01359 // point) to xcv1. 01360 res = compare_y_at_x (min_vertex (xcv2), xcv1); 01361 01362 // Swap the result. 01363 if (res == EQUAL) 01364 return (EQUAL); 01365 01366 return ((res == SMALLER) ? LARGER : SMALLER); 01367 } 01368 else if (ps_x2 != ARR_INTERIOR) { 01369 // Check if the left end of xcv1 lies at y boundary. 01370 const Arr_parameter_space ps_y1 = ps_y (xcv1, ARR_MIN_END); 01371 01372 if (ps_y1 == ARR_BOTTOM_BOUNDARY) 01373 return (SMALLER); // xcv1 is obviously below xcv2. 01374 else if (ps_y1 == ARR_TOP_BOUNDARY) 01375 return (LARGER); // xcv1 is obviously above xcv2. 01376 01377 // Compare the position of the left end of xcv1 (which is a normal 01378 // point) to xcv2. 01379 res = compare_y_at_x (min_vertex (xcv1), xcv2); 01380 01381 return (res); 01382 } 01383 01384 // Check if the left curve end lies at y = +/- oo. 01385 const Arr_parameter_space ps_y1 = ps_y (xcv1, ARR_MIN_END); 01386 const Arr_parameter_space ps_y2 = ps_y (xcv2, ARR_MIN_END); 01387 Comparison_result l_res; 01388 01389 if (ps_y1 != ARR_INTERIOR) 01390 { 01391 if (ps_y2 != ARR_INTERIOR) 01392 { 01393 // The curve ends have special boundary with oposite signs in y, 01394 // we readily know their relative position (recall that they do not 01395 // instersect). 01396 if (ps_y1 == ARR_BOTTOM_BOUNDARY && ps_y2 == ARR_TOP_BOUNDARY) 01397 return (SMALLER); 01398 else if (ps_y1 == ARR_TOP_BOUNDARY && ps_y2 == ARR_BOTTOM_BOUNDARY) 01399 return (LARGER); 01400 01401 // Both curves have vertical asymptotes with the same sign in y. 01402 // Check which asymptote is the rightmost. Note that in this case 01403 // the vertical asymptotes cannot be equal. 01404 l_res = compare_x_near_bnd(xcv1, ARR_MIN_END, xcv2, ARR_MIN_END); 01405 CGAL_assertion (l_res != EQUAL); 01406 01407 if (ps_y1 == ARR_TOP_BOUNDARY) 01408 return (l_res); 01409 else 01410 return ((l_res == SMALLER) ? LARGER : SMALLER); 01411 } 01412 01413 // xcv1 has a vertical asymptote and xcv2 has a normal left endpoint. 01414 // Compare the x-positions of this endpoint and the asymptote. 01415 const Point_2& left2 = min_vertex(xcv2); 01416 01417 l_res = compare_x_near_bnd(left2, xcv1, ARR_MIN_END); 01418 01419 if (l_res == LARGER) 01420 { 01421 // left2 lies in the x-range of xcv1, so it is safe to compare: 01422 res = compare_y_at_x (left2, xcv1); 01423 01424 // Swap the result. 01425 if (res == EQUAL) 01426 return (EQUAL); 01427 01428 return ((res == SMALLER) ? LARGER : SMALLER); 01429 } 01430 else 01431 { 01432 if (ps_y1 == ARR_BOTTOM_BOUNDARY) 01433 return (SMALLER); // xcv1 is obviously below xcv2. 01434 else 01435 return (LARGER); // xcv2 is obviously above xcv1. 01436 } 01437 } 01438 else if (ps_y2 != ARR_INTERIOR) 01439 { 01440 // xcv2 has a vertical asymptote and xcv1 has a normal left endpoint. 01441 // Compare the x-positions of this endpoint and the asymptote. 01442 const Point_2& left1 = min_vertex(xcv1); 01443 01444 l_res = compare_x_near_bnd(left1, xcv2, ARR_MIN_END); 01445 01446 if (l_res == LARGER) 01447 { 01448 // left1 lies in the x-range of xcv2, so it is safe to compare: 01449 return (compare_y_at_x (left1, xcv2)); 01450 } 01451 else 01452 { 01453 return (ps_y2 == ARR_BOTTOM_BOUNDARY) ? LARGER : SMALLER; 01454 } 01455 } 01456 01457 // In this case we compare two normal points. 01458 Compare_xy_2 compare_xy = m_self->compare_xy_2_object(); 01459 Compare_y_at_x_right_2 compare_y_at_x_right = 01460 m_self->compare_y_at_x_right_2_object(); 01461 01462 // Get the left endpoints of xcv1 and xcv2. 01463 const Point_2& left1 = min_vertex(xcv1); 01464 const Point_2& left2 = min_vertex(xcv2); 01465 01466 // Locate the rightmost point of left1 and left2 and compare its position 01467 // to the other curve. 01468 l_res = compare_xy (left1, left2); 01469 01470 if (l_res != SMALLER) 01471 { 01472 // left1 is in the x-range of xcv2: 01473 res = compare_y_at_x (left1, xcv2); 01474 01475 if (res == EQUAL) 01476 { 01477 // The two curves intersect at left1. If both curves are defined to 01478 // the right of the reference point, we can compare them to its 01479 // right. Otherwise, their share a common endpoint (which is the only 01480 // overlap in their x-ranges) and are really equal. 01481 if (l_res == EQUAL) 01482 res = compare_y_at_x_right (xcv1, xcv2, left1); 01483 } 01484 01485 return (res); 01486 } 01487 else 01488 { 01489 // left2 is in the x-range of xcv1: 01490 res = compare_y_at_x (left2, xcv1); 01491 01492 if (res == EQUAL) 01493 { 01494 // The two curves share a common endpoint (which is the only overlap 01495 // in their x-ranges) and are really equal. 01496 return (EQUAL); 01497 } 01498 01499 // Swap the result: 01500 return ((res == SMALLER) ? LARGER : SMALLER); 01501 } 01502 } 01503 01504 protected: 01506 const Self *m_self; 01507 01515 Compare_y_position_2 (const Self *self) : m_self (self) {} 01516 01518 friend class Arr_traits_basic_adaptor_2<Base>; 01519 }; 01520 01522 Compare_y_position_2 compare_y_position_2_object () const 01523 { 01524 return Compare_y_position_2(this); 01525 } 01526 01527 class Is_between_cw_2 { 01528 public: 01549 bool operator() (const X_monotone_curve_2& xcv, bool xcv_to_right, 01550 const X_monotone_curve_2& xcv1, bool xcv1_to_right, 01551 const X_monotone_curve_2& xcv2, bool xcv2_to_right, 01552 const Point_2& p, 01553 bool& xcv_equal_xcv1, 01554 bool& xcv_equal_xcv2) const 01555 { 01556 Compare_y_at_x_left_2 compare_y_at_x_left = 01557 m_self->compare_y_at_x_left_2_object(); 01558 Compare_y_at_x_right_2 compare_y_at_x_right = 01559 m_self->compare_y_at_x_right_2_object(); 01560 01561 // Initialize output flags. 01562 xcv_equal_xcv1 = false; 01563 xcv_equal_xcv2 = false; 01564 01565 // Take care of the general 4 cases: 01566 Comparison_result l_res, r_res; 01567 Comparison_result res1, res2; 01568 01569 if (!xcv1_to_right && !xcv2_to_right) 01570 { 01571 // Case 1: Both xcv1 and xcv2 are defined to the left of p. 01572 l_res = compare_y_at_x_left (xcv1, xcv2, p); 01573 01574 if (l_res == LARGER) 01575 { 01576 // Case 1(a) : xcv1 is above xcv2. 01577 if (!xcv_to_right) 01578 { 01579 res1 = compare_y_at_x_left (xcv1, xcv, p); 01580 res2 = compare_y_at_x_left (xcv2, xcv, p); 01581 01582 if (res1 == EQUAL) 01583 xcv_equal_xcv1 = true; 01584 if (res2 == EQUAL) 01585 xcv_equal_xcv2 = true; 01586 01587 return (res1 == SMALLER || res2 == LARGER); 01588 } 01589 return (true); 01590 } 01591 else if (l_res == SMALLER) 01592 { 01593 // Case 1(b): xcv1 is below xcv2. 01594 if (!xcv_to_right) 01595 { 01596 res1 = compare_y_at_x_left (xcv1, xcv, p); 01597 res2 = compare_y_at_x_left (xcv2, xcv, p); 01598 01599 if (res1 == EQUAL) 01600 xcv_equal_xcv1 = true; 01601 if (res2 == EQUAL) 01602 xcv_equal_xcv2 = true; 01603 01604 return (res1 == SMALLER && res2 == LARGER); 01605 } 01606 return (false); 01607 } 01608 else 01609 { 01610 // Overlapping segments. 01611 if (!xcv_to_right) 01612 { 01613 res1 = compare_y_at_x_left (xcv1, xcv, p); 01614 if (res1 == EQUAL) 01615 { 01616 xcv_equal_xcv1 = true; 01617 xcv_equal_xcv2 = true; 01618 return (false); 01619 } 01620 return (true); 01621 } 01622 return (true); 01623 } 01624 } 01625 01626 if (xcv1_to_right && xcv2_to_right) 01627 { 01628 // Case 2: Both xcv1 and xcv2 are defined to the right of p. 01629 r_res = compare_y_at_x_right (xcv1, xcv2, p); 01630 01631 if (r_res == LARGER) 01632 { 01633 // Case 2(a) : xcv1 is above xcv2. 01634 if (xcv_to_right) 01635 { 01636 res1 = compare_y_at_x_right (xcv1, xcv, p); 01637 res2 = compare_y_at_x_right (xcv2, xcv, p); 01638 01639 if (res1 == EQUAL) 01640 xcv_equal_xcv1 = true; 01641 if (res2 == EQUAL) 01642 xcv_equal_xcv2 = true; 01643 01644 return (res1 == LARGER && res2 == SMALLER); 01645 } 01646 return (false); 01647 } 01648 else if (r_res == SMALLER) 01649 { 01650 // Case 2(b): xcv1 is below xcv2. 01651 if (xcv_to_right) 01652 { 01653 res1 = compare_y_at_x_right (xcv1, xcv, p); 01654 res2 = compare_y_at_x_right (xcv2, xcv, p); 01655 01656 if (res1 == EQUAL) 01657 xcv_equal_xcv1 = true; 01658 if (res2 == EQUAL) 01659 xcv_equal_xcv2 = true; 01660 01661 return (res1 == LARGER || res2 == SMALLER); 01662 } 01663 return (true); 01664 } 01665 else 01666 { 01667 // Overlapping segments. 01668 if (xcv_to_right) 01669 { 01670 res1 = compare_y_at_x_right (xcv1, xcv, p); 01671 01672 if (res1 == EQUAL) 01673 { 01674 xcv_equal_xcv1 = true; 01675 xcv_equal_xcv2 = true; 01676 return (false); 01677 } 01678 return (true); 01679 } 01680 return (true); 01681 } 01682 } 01683 01684 if (!xcv1_to_right && xcv2_to_right) 01685 { 01686 // Case 3: xcv1 is defined to the left of p, and xcv2 to its right. 01687 if (!xcv_to_right) 01688 { 01689 res1 = compare_y_at_x_left (xcv1, xcv, p); 01690 01691 if (res1 == EQUAL) 01692 xcv_equal_xcv1 = true; 01693 01694 return (res1 == SMALLER); 01695 } 01696 else 01697 { 01698 res2 = compare_y_at_x_right (xcv2, xcv, p); 01699 01700 if (res2 == EQUAL) 01701 xcv_equal_xcv2 = true; 01702 01703 return (res2 == SMALLER); 01704 } 01705 } 01706 01707 CGAL_assertion (xcv1_to_right && !xcv2_to_right); 01708 01709 // Case 4: xcv1 is defined to the right of p, and xcv2 to its left. 01710 if (xcv_to_right) 01711 { 01712 res1 = compare_y_at_x_right (xcv1, xcv, p); 01713 01714 if (res1 == EQUAL) 01715 xcv_equal_xcv1 = true; 01716 01717 return (res1 == LARGER); 01718 } 01719 else 01720 { 01721 res2 = compare_y_at_x_left (xcv2, xcv, p); 01722 01723 if (res2 == EQUAL) 01724 xcv_equal_xcv2 = true; 01725 01726 return (res2 == LARGER); 01727 } 01728 } 01729 01730 protected: 01732 const Self *m_self; 01733 01741 Is_between_cw_2 (const Self *self) : m_self (self) {} 01742 01744 friend class Arr_traits_basic_adaptor_2<Base>; 01745 }; 01746 01748 Is_between_cw_2 is_between_cw_2_object () const 01749 { 01750 return Is_between_cw_2(this); 01751 } 01752 01753 class Compare_cw_around_point_2 { 01754 public: 01770 Comparison_result operator() (const X_monotone_curve_2& xcv1, 01771 bool xcv1_to_right, 01772 const X_monotone_curve_2& xcv2, 01773 bool xcv2_to_right, 01774 const Point_2& p, 01775 bool from_top = true) const 01776 { 01777 // Act according to where xcv1 and xcv2 lie. 01778 if (!xcv1_to_right && !xcv2_to_right) 01779 { 01780 // Both are defined to the left of p, and we encounter xcv1 before 01781 // xcv2 if it is below xcv2: 01782 return (m_self->compare_y_at_x_left_2_object() (xcv1, xcv2, p)); 01783 } 01784 01785 if (xcv1_to_right && xcv2_to_right) 01786 { 01787 // Both are defined to the right of p, and we encounter xcv1 before 01788 // xcv2 if it is above xcv2. We therefore reverse the order of the 01789 // curves when we invoke compare_y_at_x_right: 01790 return (m_self->compare_y_at_x_right_2_object() (xcv2, xcv1, p)); 01791 } 01792 01793 if (!xcv1_to_right && xcv2_to_right) 01794 { 01795 // If we start from the top, we encounter the right curve (which 01796 // is xcv2) first. If we start from the bottom, we encounter xcv1 first. 01797 return (from_top ? LARGER : SMALLER); 01798 } 01799 01800 CGAL_assertion (xcv1_to_right && !xcv2_to_right); 01801 01802 // If we start from the top, we encounter the right curve (which 01803 // is xcv1) first. If we start from the bottom, we encounter xcv2 first. 01804 return (from_top ? SMALLER : LARGER); 01805 } 01806 01807 protected: 01809 const Self *m_self; 01810 01818 Compare_cw_around_point_2 (const Self *self) : m_self (self) {} 01819 01821 friend class Arr_traits_basic_adaptor_2<Base>; 01822 }; 01823 01825 Compare_cw_around_point_2 compare_cw_around_point_2_object () const 01826 { 01827 return Compare_cw_around_point_2(this); 01828 } 01830 }; 01831 01835 template <class ArrangementTraits_> 01836 class Arr_traits_adaptor_2 : 01837 public Arr_traits_basic_adaptor_2<ArrangementTraits_> 01838 { 01839 public: 01840 01841 // Traits-class geometric types. 01842 typedef ArrangementTraits_ Base_traits_2; 01843 typedef Arr_traits_basic_adaptor_2<ArrangementTraits_> Base; 01844 01845 typedef typename Base_traits_2::Curve_2 Curve_2; 01846 typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; 01847 typedef typename Base::Point_2 Point_2; 01848 01849 // Tags. 01850 typedef typename Base::Has_left_category Has_left_category; 01851 typedef typename Base::Has_merge_category Has_merge_category; 01852 01853 typedef typename CGALi::Arr_complete_left_side_tag< Base >::Tag 01854 Arr_left_side_tag; 01855 typedef typename CGALi::Arr_complete_bottom_side_tag< Base >::Tag 01856 Arr_bottom_side_tag; 01857 typedef typename CGALi::Arr_complete_top_side_tag< Base >::Tag 01858 Arr_top_side_tag; 01859 typedef typename CGALi::Arr_complete_right_side_tag< Base >::Tag 01860 Arr_right_side_tag; 01861 01863 01864 01865 Arr_traits_adaptor_2 () : 01866 Base() 01867 {} 01868 01870 Arr_traits_adaptor_2 (const Base_traits_2& traits) : 01871 Base (traits) 01872 {} 01874 01875 // Inherited functors: 01876 typedef typename Base::Compare_x_2 Compare_x_2; 01877 typedef typename Base::Compare_xy_2 Compare_xy_2; 01878 typedef typename Base::Construct_min_vertex_2 Construct_min_vertex_2; 01879 typedef typename Base::Construct_max_vertex_2 Construct_max_vertex_2; 01880 typedef typename Base::Is_vertical_2 Is_vertical_2; 01881 typedef typename Base::Compare_y_at_x_2 Compare_y_at_x_2; 01882 typedef typename Base::Compare_y_at_x_right_2 Compare_y_at_x_right_2; 01883 typedef typename Base::Compare_y_at_x_left_2 Compare_y_at_x_left_2; 01884 typedef typename Base::Equal_2 Equal_2; 01885 01886 // Note that the basic adaptor does not have to support these functors: 01887 typedef typename Base_traits_2::Make_x_monotone_2 Make_x_monotone_2; 01888 typedef typename Base_traits_2::Split_2 Split_2; 01889 typedef typename Base_traits_2::Intersect_2 Intersect_2; 01890 01892 01893 01895 class Are_mergeable_2 { 01896 public: 01904 bool operator() (const X_monotone_curve_2& xcv1, 01905 const X_monotone_curve_2& xcv2) const 01906 { 01907 // The function is implemented based on the Has_merge category. 01908 return (_are_mergeable_imp (xcv1, xcv2, Has_merge_category())); 01909 } 01910 01911 protected: 01913 const Base *m_base; 01914 01922 Are_mergeable_2 (const Base *base) : m_base (base) {} 01923 01925 friend class Arr_traits_adaptor_2<Base_traits_2>; 01926 01930 bool _are_mergeable_imp (const X_monotone_curve_2& xcv1, 01931 const X_monotone_curve_2& xcv2, 01932 Tag_true) const 01933 { 01934 return (m_base->are_mergeable_2_object() (xcv1, xcv2)); 01935 } 01936 01940 bool _are_mergeable_imp (const X_monotone_curve_2& , 01941 const X_monotone_curve_2& , 01942 Tag_false) const 01943 { 01944 // Curve merging is not supported: 01945 return (false); 01946 } 01947 }; 01948 01950 Are_mergeable_2 are_mergeable_2_object () const 01951 { 01952 return Are_mergeable_2(this); 01953 } 01954 01956 class Merge_2 { 01957 public: 01966 void operator() (const X_monotone_curve_2& xcv1, 01967 const X_monotone_curve_2& xcv2, 01968 X_monotone_curve_2& c) const 01969 { 01970 // The function is implemented based on the Has_merge category. 01971 _merge_imp (xcv1, xcv2, c, Has_merge_category()); 01972 } 01973 01974 protected: 01976 const Base *m_base; 01977 01985 Merge_2 (const Base *base) : m_base (base) {} 01986 01988 friend class Arr_traits_adaptor_2<Base_traits_2>; 01989 01993 void _merge_imp (const X_monotone_curve_2& xcv1, 01994 const X_monotone_curve_2& xcv2, 01995 X_monotone_curve_2& c, 01996 Tag_true) const 01997 { 01998 return (m_base->merge_2_object() (xcv1, xcv2, c)); 01999 } 02000 02004 void _merge_imp (const X_monotone_curve_2& , 02005 const X_monotone_curve_2& , 02006 X_monotone_curve_2& , 02007 Tag_false) const 02008 { 02009 // This function should never be called! 02010 CGAL_error_msg( "Merging curves is not supported."); 02011 return; 02012 } 02013 }; 02014 02016 Merge_2 merge_2_object () const 02017 { 02018 return Merge_2(this); 02019 } 02021 }; 02022 02023 CGAL_END_NAMESPACE 02024 02025 #endif