BWAPI
|
00001 // Copyright (c) 2005 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: 00015 // $Id: Conic_x_monotone_arc_2.h 46881 2008-11-14 08:29:27Z ophirset $ 00016 // 00017 // 00018 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00019 00020 #ifndef CGAL_CONIC_X_MONOTONE_ARC_2_H 00021 #define CGAL_CONIC_X_MONOTONE_ARC_2_H 00022 00027 #include <CGAL/Arr_geometry_traits/Conic_intersections_2.h> 00028 00029 #include <map> 00030 #include <ostream> 00031 00032 CGAL_BEGIN_NAMESPACE 00033 00039 template <class Conic_arc_> 00040 class _Conic_x_monotone_arc_2 : private Conic_arc_ 00041 { 00042 public: 00043 00044 typedef Conic_arc_ Conic_arc_2; 00045 typedef _Conic_x_monotone_arc_2<Conic_arc_2> Self; 00046 00047 typedef typename Conic_arc_2::Alg_kernel Alg_kernel; 00048 typedef typename Conic_arc_2::Algebraic Algebraic; 00049 00050 typedef typename Conic_arc_2::Point_2 Point_2; 00051 typedef typename Conic_arc_2::Conic_point_2 Conic_point_2; 00052 00053 // Type definition for the intersection points mapping. 00054 typedef typename Conic_point_2::Conic_id Conic_id; 00055 typedef std::pair<Conic_id, Conic_id> Conic_pair; 00056 typedef std::pair<Conic_point_2, unsigned int> Intersection_point_2; 00057 typedef std::list<Intersection_point_2> Intersection_list; 00058 00062 struct Less_conic_pair 00063 { 00064 bool operator() (const Conic_pair& cp1, const Conic_pair& cp2) const 00065 { 00066 // Compare the pairs of IDs lexicographically. 00067 return (cp1.first < cp2.first || 00068 (cp1.first == cp2.first && cp1.second < cp2.second)); 00069 } 00070 }; 00071 00072 typedef std::map<Conic_pair, 00073 Intersection_list, 00074 Less_conic_pair> Intersection_map; 00075 typedef typename Intersection_map::value_type Intersection_map_entry; 00076 typedef typename Intersection_map::iterator Intersection_map_iterator; 00077 00078 protected: 00079 00080 typedef Conic_arc_2 Base; 00081 00082 typedef typename Conic_arc_2::Integer Integer; 00083 typedef typename Conic_arc_2::Nt_traits Nt_traits; 00084 typedef typename Conic_arc_2::Rat_kernel Rat_kernel; 00085 00086 // Bit masks for the _info field (the two least significant bits are already 00087 // used by the base class). 00088 enum 00089 { 00090 IS_VERTICAL_SEGMENT = 4, 00091 IS_DIRECTED_RIGHT = 8, 00092 DEGREE_1 = 16, 00093 DEGREE_2 = 32, 00094 DEGREE_MASK = 16 + 32, 00095 PLUS_SQRT_DISC_ROOT = 64, 00096 FACING_UP = 128, 00097 FACING_DOWN = 256, 00098 FACING_MASK = 128 + 256, 00099 IS_SPECIAL_SEGMENT = 512 00100 }; 00101 00102 Algebraic alg_r; // The coefficients of the supporting conic curve: 00103 Algebraic alg_s; // 00104 Algebraic alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , 00105 Algebraic alg_u; // 00106 Algebraic alg_v; // converted to algebraic numbers. 00107 Algebraic alg_w; // 00108 00109 Conic_id _id; // The ID number of the supporting conic curve. 00110 00111 public: 00112 00114 00115 00119 _Conic_x_monotone_arc_2 () : 00120 Base (), 00121 _id () 00122 {} 00123 00128 _Conic_x_monotone_arc_2 (const Self& arc) : 00129 Base (arc), 00130 alg_r (arc.alg_r), 00131 alg_s (arc.alg_s), 00132 alg_t (arc.alg_t), 00133 alg_u (arc.alg_u), 00134 alg_v (arc.alg_v), 00135 alg_w (arc.alg_w), 00136 _id (arc._id) 00137 {} 00138 00144 _Conic_x_monotone_arc_2 (const Base& arc) : 00145 Base (arc), 00146 _id () 00147 { 00148 CGAL_precondition (arc.is_valid() && arc.is_x_monotone()); 00149 00150 _set (); 00151 } 00152 00158 _Conic_x_monotone_arc_2 (const Base& arc, 00159 const Conic_id& id) : 00160 Base (arc), 00161 _id (id) 00162 { 00163 CGAL_precondition (arc.is_valid() && id.is_valid()); 00164 00165 _set (); 00166 } 00167 00175 _Conic_x_monotone_arc_2 (const Base& arc, 00176 const Point_2& source, const Point_2& target, 00177 const Conic_id& id) : 00178 Base (arc), 00179 _id (id) 00180 { 00181 CGAL_precondition (arc.is_valid() && id.is_valid()); 00182 00183 // Set the two endpoints. 00184 this->_source = source; 00185 this->_target = target; 00186 00187 _set(); 00188 } 00189 00196 _Conic_x_monotone_arc_2 (const Point_2& source, const Point_2& target) : 00197 Base() 00198 { 00199 // Set the basic properties and clear the _info bits. 00200 this->_source = source; 00201 this->_target = target; 00202 this->_orient = COLLINEAR; 00203 this->_info = 0; 00204 00205 // Check if the arc is directed right (the target is lexicographically 00206 // greater than the source point), or to the left. 00207 Alg_kernel ker; 00208 Comparison_result dir_res = ker.compare_xy_2_object() (this->_source, 00209 this->_target); 00210 00211 CGAL_precondition (dir_res != EQUAL); 00212 if (dir_res == EQUAL) 00213 // Invalid arc: 00214 return; 00215 00216 this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); 00217 if (dir_res == SMALLER) 00218 this->_info = (this->_info | IS_DIRECTED_RIGHT); 00219 00220 // Compose the equation of the underlying line. 00221 const Algebraic x1 = source.x(), y1 = source.y(); 00222 const Algebraic x2 = target.x(), y2 = target.y(); 00223 00224 // The supporting line is A*x + B*y + C = 0, where: 00225 // 00226 // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 00227 // 00228 // We use the extra data field to store the equation of this line. 00229 this->_extra_data_P = new typename Base::Extra_data; 00230 this->_extra_data_P->a = y2 - y1; 00231 this->_extra_data_P->b = x1 - x2; 00232 this->_extra_data_P->c = x2*y1 - x1*y2; 00233 this->_extra_data_P->side = ZERO; 00234 00235 // Check if the segment is vertical. 00236 if (CGAL::sign (this->_extra_data_P->b) == ZERO) 00237 this->_info = (this->_info | IS_VERTICAL_SEGMENT); 00238 00239 // Mark that this is a special segment. 00240 this->_info = (this->_info | IS_SPECIAL_SEGMENT); 00241 00242 return; 00243 } 00244 00252 _Conic_x_monotone_arc_2 (const Algebraic& a, 00253 const Algebraic& b, 00254 const Algebraic& c, 00255 const Point_2& source, const Point_2& target) : 00256 Base() 00257 { 00258 // Make sure the two endpoints lie on the supporting line. 00259 CGAL_precondition (CGAL::sign (a * source.x() + 00260 b * source.y() + c) == CGAL::ZERO); 00261 00262 CGAL_precondition (CGAL::sign (a * target.x() + 00263 b * target.y() + c) == CGAL::ZERO); 00264 00265 // Set the basic properties and clear the _info bits. 00266 this->_source = source; 00267 this->_target = target; 00268 this->_orient = COLLINEAR; 00269 this->_info = 0; 00270 00271 // Check if the arc is directed right (the target is lexicographically 00272 // greater than the source point), or to the left. 00273 Alg_kernel ker; 00274 Comparison_result res = ker.compare_x_2_object() (this->_source, 00275 this->_target); 00276 00277 this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); 00278 if (res == EQUAL) 00279 { 00280 // Mark that the segment is vertical. 00281 this->_info = (this->_info | IS_VERTICAL_SEGMENT); 00282 00283 // Compare the endpoints lexicographically. 00284 res = ker.compare_y_2_object() (this->_source, 00285 this->_target); 00286 00287 CGAL_precondition (res != EQUAL); 00288 if (res == EQUAL) 00289 { 00290 // Invalid arc: 00291 this->_info = 0; 00292 return; 00293 } 00294 } 00295 00296 if (res == SMALLER) 00297 this->_info = (this->_info | IS_DIRECTED_RIGHT); 00298 00299 // Store the coefficients of the line. 00300 this->_extra_data_P = new typename Base::Extra_data; 00301 this->_extra_data_P->a = a; 00302 this->_extra_data_P->b = b; 00303 this->_extra_data_P->c = c; 00304 this->_extra_data_P->side = ZERO; 00305 00306 // Mark that this is a special segment. 00307 this->_info = (this->_info | IS_SPECIAL_SEGMENT); 00308 00309 return; 00310 } 00311 00316 const Self& operator= (const Self& arc) 00317 { 00318 CGAL_precondition (arc.is_valid()); 00319 00320 if (this == &arc) 00321 return (*this); 00322 00323 // Copy the base arc. 00324 Base::operator= (arc); 00325 00326 // Set the rest of the properties. 00327 alg_r = arc.alg_r; 00328 alg_s = arc.alg_s; 00329 alg_t = arc.alg_t; 00330 alg_u = arc.alg_u; 00331 alg_v = arc.alg_v; 00332 alg_w = arc.alg_w; 00333 00334 _id = arc._id; 00335 00336 return (*this); 00337 } 00339 00341 00342 00346 const Integer& r () const {return (this->_r);} 00347 const Integer& s () const {return (this->_s);} 00348 const Integer& t () const {return (this->_t);} 00349 const Integer& u () const {return (this->_u);} 00350 const Integer& v () const {return (this->_v);} 00351 const Integer& w () const {return (this->_w);} 00352 00357 const Conic_point_2& source () const 00358 { 00359 return (this->_source); 00360 } 00361 00366 const Conic_point_2& target () const 00367 { 00368 return (this->_target); 00369 } 00370 00375 Orientation orientation () const 00376 { 00377 return (this->_orient); 00378 } 00379 00383 const Conic_point_2& left () const 00384 { 00385 if ((this->_info & IS_DIRECTED_RIGHT) != 0) 00386 return (this->_source); 00387 else 00388 return (this->_target); 00389 } 00390 00394 const Conic_point_2& right () const 00395 { 00396 if ((this->_info & IS_DIRECTED_RIGHT) != 0) 00397 return (this->_target); 00398 else 00399 return (this->_source); 00400 } 00401 00405 bool is_directed_right() const 00406 { 00407 return ((this->_info & IS_DIRECTED_RIGHT) != 0); 00408 } 00409 00414 Bbox_2 bbox () const 00415 { 00416 return (Base::bbox()); 00417 } 00419 00421 00422 00426 bool is_vertical () const 00427 { 00428 return ((this->_info & IS_VERTICAL_SEGMENT) != 0); 00429 } 00430 00436 bool contains_point (const Conic_point_2& p) const 00437 { 00438 // First check if p lies on the supporting conic. We first check whether 00439 // it is one of p's generating conic curves. 00440 bool p_on_conic = false; 00441 00442 if (p.is_generating_conic (_id)) 00443 { 00444 p_on_conic = true; 00445 } 00446 else 00447 { 00448 // Check whether p satisfies the supporting conic equation. 00449 p_on_conic = _is_on_supporting_conic (p.x(), p.y()); 00450 00451 if (p_on_conic) 00452 { 00453 // As p lies on the supporting conic of our arc, add its ID to 00454 // the list of generating conics for p. 00455 Conic_point_2& p_non_const = const_cast<Conic_point_2&> (p); 00456 p_non_const.set_generating_conic (_id); 00457 } 00458 } 00459 00460 if (! p_on_conic) 00461 return (false); 00462 00463 // Check if p is between the endpoints of the arc. 00464 return (_is_between_endpoints (p)); 00465 } 00467 00469 00470 00477 Point_2 point_at_x (const Point_2& p) const 00478 { 00479 // Make sure that p is in the x-range of the arc. 00480 CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0); 00481 00482 CGAL_precondition_code ( 00483 Alg_kernel ker; 00484 ); 00485 00486 CGAL_precondition (ker.compare_x_2_object() (p, left()) != SMALLER && 00487 ker.compare_x_2_object() (p, right()) != LARGER); 00488 00489 if (_is_special_segment()) 00490 { 00491 // In case of a special segment, the equation of the supported line 00492 // (a*x + b*y + c) = 0 is stored with the extra data field, and we 00493 // simply have: 00494 Algebraic _y = -(this->_extra_data_P->a*p.x() + 00495 this->_extra_data_P->c) / 00496 this->_extra_data_P->b; 00497 00498 // Return the computed point. 00499 return (Point_2 (p.x(), _y)); 00500 } 00501 00502 // Compute the y-coordinate according to the degree of the supporting 00503 // conic curve. 00504 Nt_traits nt_traits; 00505 Algebraic y; 00506 00507 if ((this->_info & DEGREE_MASK) == DEGREE_1) 00508 { 00509 // In case of a linear curve, the y-coordinate is a simple linear 00510 // expression of x(p) (note that v is not 0 as the arc is not vertical): 00511 // y = -(u*x(p) + w) / v 00512 y = -(alg_u*p.x() + alg_w) / alg_v; 00513 } 00514 else if (this->_orient == COLLINEAR) 00515 { 00516 CGAL_assertion (this->_extra_data_P != NULL); 00517 00518 // In this case the equation of the supporting line is given by the 00519 // extra data structure. 00520 y = -(this->_extra_data_P->a * p.x() + 00521 this->_extra_data_P->c) / this->_extra_data_P->b; 00522 } 00523 else 00524 { 00525 CGAL_assertion ((this->_info & DEGREE_MASK) == DEGREE_2); 00526 00527 // In this case the y-coordinate is one of solutions to the quadratic 00528 // equation: 00529 // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 00530 Algebraic A = alg_s; 00531 Algebraic B = alg_t*p.x() + alg_v; 00532 Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; 00533 00534 if (CGAL::sign(this->_s) == ZERO) 00535 { 00536 // In this case A is 0 and we have a linear equation. 00537 CGAL_assertion (CGAL::sign (B) != ZERO); 00538 00539 y = -C / B; 00540 } 00541 else 00542 { 00543 // Solve the quadratic equation. 00544 Algebraic disc = B*B - 4*A*C; 00545 00546 CGAL_assertion (CGAL::sign (disc) != NEGATIVE); 00547 00548 // We take either the root involving -sqrt(disc) or +sqrt(disc) 00549 // based on the information flags. 00550 if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) 00551 { 00552 y = (nt_traits.sqrt (disc) - B) / (2*A); 00553 } 00554 else 00555 00556 { 00557 y = -(B + nt_traits.sqrt (disc)) / (2*A); 00558 } 00559 } 00560 } 00561 00562 // Return the computed point. 00563 return (Point_2 (p.x(), y)); 00564 } 00565 00576 template <class OutputIterator> 00577 OutputIterator polyline_approximation (size_t n, 00578 OutputIterator oi) const 00579 { 00580 CGAL_precondition (n != 0); 00581 00582 const double x_left = CGAL::to_double (left().x()); 00583 const double y_left = CGAL::to_double (left().y()); 00584 const double x_right = CGAL::to_double (right().x()); 00585 const double y_right = CGAL::to_double (right().y()); 00586 00587 if (this->_orient == COLLINEAR) 00588 { 00589 // In case of a line segment, return the two endpoints. 00590 *oi = std::pair<double, double> (x_left, y_left); 00591 ++oi; 00592 *oi = std::pair<double, double> (x_right, y_right); 00593 ++oi; 00594 return (oi); 00595 } 00596 00597 // Otherwise, sample (n - 1) equally-spaced points in between. 00598 const double app_r = CGAL::to_double (this->_r); 00599 const double app_s = CGAL::to_double (this->_s); 00600 const double app_t = CGAL::to_double (this->_t); 00601 const double app_u = CGAL::to_double (this->_u); 00602 const double app_v = CGAL::to_double (this->_v); 00603 const double app_w = CGAL::to_double (this->_w); 00604 const double x_jump = (x_right - x_left) / n; 00605 double x, y; 00606 const bool A_is_zero = (CGAL::sign(this->_s) == ZERO); 00607 double A = app_s, B, C; 00608 double disc; 00609 size_t i; 00610 00611 *oi = std::pair<double, double> (x_left, y_left); // The left point. 00612 ++oi; 00613 for (i = 1; i < n; i++) 00614 { 00615 x = x_left + x_jump*i; 00616 00617 // Solve the quadratic equation: A*x^2 + B*x + C = 0: 00618 B = app_t*x + app_v; 00619 C = (app_r*x + app_u)*x + app_w; 00620 00621 if (A_is_zero) 00622 { 00623 y = -C / B; 00624 } 00625 else 00626 { 00627 disc = B*B - 4*A*C; 00628 00629 if (disc < 0) 00630 disc = 0; 00631 00632 // We take either the root involving -sqrt(disc) or +sqrt(disc) 00633 // based on the information flags. 00634 if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) 00635 { 00636 y = (std::sqrt(disc) - B) / (2*A); 00637 } 00638 else 00639 { 00640 y = -(B + std::sqrt (disc)) / (2*A); 00641 } 00642 } 00643 00644 *oi = std::pair<double, double> (x, y); 00645 ++oi; 00646 } 00647 *oi = std::pair<double, double> (x_right, y_right); // The right point. 00648 ++oi; 00649 00650 return (oi); 00651 } 00652 00660 Comparison_result compare_to_right (const Self& arc, 00661 const Conic_point_2& p) const 00662 { 00663 CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 && 00664 (arc._info & IS_VERTICAL_SEGMENT) == 0); 00665 00666 // In case one arc is facing upwards and another facing downwards, it is 00667 // clear that the one facing upward is above the one facing downwards. 00668 if (_has_same_supporting_conic (arc)) 00669 { 00670 if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) 00671 return (LARGER); 00672 else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP) != 0) 00673 return (SMALLER); 00674 00675 // In this case the two arcs overlap. 00676 CGAL_assertion ((this->_info & FACING_MASK) == 00677 (arc._info & FACING_MASK)); 00678 00679 return (EQUAL); 00680 } 00681 00682 // Compare the slopes of the two arcs at p, using their first-order 00683 // partial derivatives. 00684 Algebraic slope1_numer, slope1_denom; 00685 Algebraic slope2_numer, slope2_denom; 00686 00687 _derive_by_x_at (p, 1, slope1_numer, slope1_denom); 00688 arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); 00689 00690 // Check if any of the slopes is vertical. 00691 const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); 00692 const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); 00693 00694 if (!is_vertical_slope1 && !is_vertical_slope2) 00695 { 00696 // The two derivatives at p are well-defined: use them to determine 00697 // which arc is above the other (the one with a larger slope is below). 00698 Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom, 00699 slope2_numer*slope1_denom); 00700 00701 if (slope_res != EQUAL) 00702 return (slope_res); 00703 00704 // Use the second-order derivative. 00705 _derive_by_x_at (p, 2, slope1_numer, slope1_denom); 00706 arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); 00707 00708 slope_res = CGAL::compare (slope1_numer*slope2_denom, 00709 slope2_numer*slope1_denom); 00710 00711 if (slope_res != EQUAL) 00712 return (slope_res); 00713 00714 // Use the third-order derivative. 00715 _derive_by_x_at (p, 3, slope1_numer, slope1_denom); 00716 arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom); 00717 00718 slope_res = CGAL::compare (slope1_numer*slope2_denom, 00719 slope2_numer*slope1_denom); 00720 00721 // \todo Handle higher-order derivatives: 00722 CGAL_assertion (slope_res != EQUAL); 00723 00724 return (slope_res); 00725 } 00726 else if (!is_vertical_slope2) 00727 { 00728 // The first arc has a vertical slope at p: check whether it is 00729 // facing upwards or downwards and decide accordingly. 00730 CGAL_assertion ((this->_info & FACING_MASK) != 0); 00731 00732 if ((this->_info & FACING_UP) != 0) 00733 return (LARGER); 00734 return (SMALLER); 00735 } 00736 else if (!is_vertical_slope1) 00737 { 00738 // The second arc has a vertical slope at p_int: check whether it is 00739 // facing upwards or downwards and decide accordingly. 00740 CGAL_assertion ((arc._info & FACING_MASK) != 0); 00741 00742 if ((arc._info & FACING_UP) != 0) 00743 return (SMALLER); 00744 return (LARGER); 00745 } 00746 00747 // The two arcs have vertical slopes at p_int: 00748 // First check whether one is facing up and one down. In this case the 00749 // comparison result is trivial. 00750 if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) 00751 return (LARGER); 00752 else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) 00753 return (SMALLER); 00754 00755 // Compute the second-order derivative by y and act according to it. 00756 _derive_by_y_at (p, 2, slope1_numer, slope1_denom); 00757 arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); 00758 00759 Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom, 00760 slope2_numer*slope1_denom); 00761 00762 // If necessary, use the third-order derivative by y. 00763 if (slope_res == EQUAL) 00764 { 00765 // \todo Check this! 00766 _derive_by_y_at (p, 3, slope1_numer, slope1_denom); 00767 arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom); 00768 00769 slope_res = CGAL::compare (slope2_numer*slope1_denom, 00770 slope1_numer*slope2_denom); 00771 } 00772 00773 // \todo Handle higher-order derivatives: 00774 CGAL_assertion(slope_res != EQUAL); 00775 00776 if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) 00777 { 00778 // Both are facing up. 00779 return ((slope_res == LARGER) ? SMALLER : LARGER); 00780 } 00781 // Both are facing down. 00782 return (slope_res); 00783 } 00784 00792 Comparison_result compare_to_left (const Self& arc, 00793 const Conic_point_2& p) const 00794 { 00795 CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 && 00796 (arc._info & IS_VERTICAL_SEGMENT) == 0); 00797 00798 // In case one arc is facing upwards and another facing downwards, it is 00799 // clear that the one facing upward is above the one facing downwards. 00800 if (_has_same_supporting_conic (arc)) 00801 { 00802 if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) 00803 return (LARGER); 00804 else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) 00805 return (SMALLER); 00806 00807 // In this case the two arcs overlap. 00808 CGAL_assertion ((this->_info & FACING_MASK) == 00809 (arc._info & FACING_MASK)); 00810 00811 return (EQUAL); 00812 } 00813 00814 // Compare the slopes of the two arcs at p, using their first-order 00815 // partial derivatives. 00816 Algebraic slope1_numer, slope1_denom; 00817 Algebraic slope2_numer, slope2_denom; 00818 00819 _derive_by_x_at (p, 1, slope1_numer, slope1_denom); 00820 arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); 00821 00822 // Check if any of the slopes is vertical. 00823 const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); 00824 00825 const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); 00826 00827 if (!is_vertical_slope1 && !is_vertical_slope2) 00828 { 00829 // The two derivatives at p are well-defined: use them to determine 00830 // which arc is above the other (the one with a larger slope is below). 00831 Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, 00832 slope1_numer*slope2_denom); 00833 00834 if (slope_res != EQUAL) 00835 return (slope_res); 00836 00837 // Use the second-order derivative. 00838 _derive_by_x_at (p, 2, slope1_numer, slope1_denom); 00839 arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); 00840 00841 slope_res = CGAL::compare (slope1_numer*slope2_denom, 00842 slope2_numer*slope1_denom); 00843 00844 if (slope_res != EQUAL) 00845 return (slope_res); 00846 00847 // Use the third-order derivative. 00848 _derive_by_x_at (p, 3, slope1_numer, slope1_denom); 00849 arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom); 00850 00851 slope_res = CGAL::compare (slope2_numer*slope1_denom, 00852 slope1_numer*slope2_denom); 00853 00854 // \todo Handle higher-order derivatives: 00855 CGAL_assertion (slope_res != EQUAL); 00856 00857 return (slope_res); 00858 } 00859 else if (!is_vertical_slope2) 00860 { 00861 // The first arc has a vertical slope at p: check whether it is 00862 // facing upwards or downwards and decide accordingly. 00863 CGAL_assertion ((this->_info & FACING_MASK) != 0); 00864 00865 if ((this->_info & FACING_UP) != 0) 00866 return (LARGER); 00867 return (SMALLER); 00868 } 00869 else if (!is_vertical_slope1) 00870 { 00871 // The second arc has a vertical slope at p_int: check whether it is 00872 // facing upwards or downwards and decide accordingly. 00873 CGAL_assertion ((arc._info & FACING_MASK) != 0); 00874 00875 if ((arc._info & FACING_UP) != 0) 00876 return (SMALLER); 00877 return (LARGER); 00878 } 00879 00880 // The two arcs have vertical slopes at p_int: 00881 // First check whether one is facing up and one down. In this case the 00882 // comparison result is trivial. 00883 if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) 00884 return (LARGER); 00885 else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) 00886 return (SMALLER); 00887 00888 // Compute the second-order derivative by y and act according to it. 00889 _derive_by_y_at (p, 2, slope1_numer, slope1_denom); 00890 arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); 00891 00892 Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, 00893 slope1_numer*slope2_denom); 00894 00895 // If necessary, use the third-order derivative by y. 00896 if (slope_res == EQUAL) 00897 { 00898 // \todo Check this! 00899 _derive_by_y_at (p, 3, slope1_numer, slope1_denom); 00900 arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom); 00901 00902 slope_res = CGAL::compare (slope2_numer*slope1_denom, 00903 slope1_numer*slope2_denom); 00904 } 00905 00906 // \todo Handle higher-order derivatives: 00907 CGAL_assertion(slope_res != EQUAL); 00908 00909 if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) 00910 { 00911 // Both are facing up. 00912 return ((slope_res == LARGER) ? SMALLER : LARGER); 00913 } 00914 // Both are facing down. 00915 return (slope_res); 00916 } 00917 00925 template<class OutputIterator> 00926 OutputIterator intersect (const Self& arc, 00927 Intersection_map& inter_map, 00928 OutputIterator oi) const 00929 { 00930 if (_has_same_supporting_conic (arc)) 00931 { 00932 // Check for overlaps between the two arcs. 00933 Self overlap; 00934 00935 if (_compute_overlap (arc, overlap)) 00936 { 00937 // There can be just a single overlap between two x-monotone arcs: 00938 *oi = make_object (overlap); 00939 oi++; 00940 return (oi); 00941 } 00942 00943 // In case there is not overlap and the supporting conics are the same, 00944 // there cannot be any intersection points, unless the two arcs share 00945 // an end point. 00946 // Note that in this case we do not define the multiplicity of the 00947 // intersection points we report. 00948 Alg_kernel ker; 00949 00950 if (ker.equal_2_object() (left(), arc.left())) 00951 { 00952 Intersection_point_2 ip (left(), 0); 00953 00954 *oi = make_object (ip); 00955 oi++; 00956 } 00957 00958 if (ker.equal_2_object() (right(), arc.right())) 00959 { 00960 Intersection_point_2 ip (right(), 0); 00961 00962 *oi = make_object (ip); 00963 oi++; 00964 } 00965 00966 return (oi); 00967 } 00968 00969 // Search for the pair of supporting conics in the map (the first conic 00970 // ID in the pair should be smaller than the second one, to guarantee 00971 // uniqueness). 00972 Conic_pair conic_pair; 00973 Intersection_map_iterator map_iter; 00974 Intersection_list inter_list; 00975 bool invalid_ids = false; 00976 00977 if (_id.is_valid() && arc._id.is_valid()) 00978 { 00979 if (_id < arc._id) 00980 conic_pair = Conic_pair (_id, arc._id); 00981 else 00982 conic_pair = Conic_pair (arc._id, _id); 00983 00984 map_iter = inter_map.find (conic_pair); 00985 } 00986 else 00987 { 00988 // In case one of the IDs is invalid, we do not look in the map neither 00989 // we cache the results. 00990 map_iter = inter_map.end(); 00991 invalid_ids = true; 00992 } 00993 00994 if (map_iter == inter_map.end()) 00995 { 00996 // In case the intersection points between the supporting conics have 00997 // not been computed before, compute them now and store them in the map. 00998 _intersect_supporting_conics (arc, inter_list); 00999 01000 if (! invalid_ids) 01001 inter_map[conic_pair] = inter_list; 01002 } 01003 else 01004 { 01005 // Obtain the precomputed intersection points from the map. 01006 inter_list = (*map_iter).second; 01007 } 01008 01009 // Go over the list of intersection points and report those that lie on 01010 // both x-monotone arcs. 01011 typename Intersection_list::const_iterator iter; 01012 01013 for (iter = inter_list.begin(); iter != inter_list.end(); ++iter) 01014 { 01015 if (_is_between_endpoints ((*iter).first) && 01016 arc._is_between_endpoints ((*iter).first)) 01017 { 01018 *oi = make_object (*iter); 01019 ++oi; 01020 } 01021 } 01022 01023 return (oi); 01024 } 01026 01028 01029 01037 void split (const Conic_point_2& p, 01038 Self& c1, Self& c2) const 01039 { 01040 // Make sure that p lies on the interior of the arc. 01041 CGAL_precondition_code ( 01042 Alg_kernel ker; 01043 ); 01044 01045 CGAL_precondition (this->contains_point (p) && 01046 ! ker.equal_2_object() (p, this->_source) && 01047 ! ker.equal_2_object() (p, this->_target)); 01048 01049 // Make copies of the current arc. 01050 c1 = *this; 01051 c2 = *this; 01052 01053 // Assign the endpoints of the arc. 01054 if ((this->_info & IS_DIRECTED_RIGHT) != 0) 01055 { 01056 // The arc is directed from left to right, so p becomes c1's target 01057 // and c2's source. 01058 c1._target = p; 01059 c2._source = p; 01060 01061 if (! p.is_generating_conic (_id)) 01062 { 01063 c1._target.set_generating_conic (_id); 01064 c2._source.set_generating_conic (_id); 01065 } 01066 } 01067 else 01068 { 01069 // The arc is directed from right to left, so p becomes c2's target 01070 // and c1's source. 01071 c1._source = p; 01072 c2._target = p; 01073 01074 if (! p.is_generating_conic (_id)) 01075 { 01076 c1._source.set_generating_conic (_id); 01077 c2._target.set_generating_conic (_id); 01078 } 01079 } 01080 01081 return; 01082 } 01083 01088 Self flip () const 01089 { 01090 // Make a copy of the current arc. 01091 Self arc = *this; 01092 01093 // Reverse the orientation. 01094 if (this->_orient == CLOCKWISE) 01095 arc._orient = COUNTERCLOCKWISE; 01096 else if (this->_orient == COUNTERCLOCKWISE) 01097 arc._orient = CLOCKWISE; 01098 01099 // Swap the source and the target. 01100 arc._source = this->_target; 01101 arc._target = this->_source; 01102 01103 // Change the direction bit among the information flags. 01104 arc._info = (this->_info ^ IS_DIRECTED_RIGHT); 01105 01106 return (arc); 01107 } 01108 01117 Self trim (const Conic_point_2& ps, 01118 const Conic_point_2& pt) const 01119 { 01120 // Make sure that both ps and pt lie on the arc. 01121 CGAL_precondition (this->contains_point (ps) && 01122 this->contains_point (pt)); 01123 01124 // Make sure that the endpoints conform with the direction of the arc. 01125 Self arc = *this; 01126 Alg_kernel ker; 01127 01128 if (! ((((this->_info & IS_DIRECTED_RIGHT) != 0) && 01129 ker.compare_xy_2_object() (ps, pt) == SMALLER) || 01130 (((this->_info & IS_DIRECTED_RIGHT) == 0) && 01131 ker.compare_xy_2_object() (ps, pt) == LARGER))) 01132 { 01133 // We are allowed to change the direction only in case of a segment. 01134 CGAL_assertion (this->_orient == COLLINEAR); 01135 arc._info = (this->_info ^ IS_DIRECTED_RIGHT); 01136 } 01137 01138 // Make a copy of the current arc and assign its endpoints. 01139 if (! ker.equal_2_object() (ps, this->_source)) 01140 { 01141 arc._source = ps; 01142 01143 if (! ps.is_generating_conic (_id)) 01144 arc._source.set_generating_conic (_id); 01145 } 01146 01147 if (! ker.equal_2_object() (pt, this->_target)) 01148 { 01149 arc._target = pt; 01150 01151 if (! pt.is_generating_conic (_id)) 01152 arc._target.set_generating_conic (_id); 01153 } 01154 01155 return (arc); 01156 } 01157 01163 bool equals (const Self& arc) const 01164 { 01165 // The two arc must have the same supporting conic curves. 01166 if (! _has_same_supporting_conic (arc)) 01167 return (false); 01168 01169 // Check that the arc endpoints are the same. 01170 Alg_kernel ker; 01171 01172 if(this->_orient == COLLINEAR) 01173 { 01174 CGAL_assertion(arc._orient == COLLINEAR); 01175 return((ker.equal_2_object() (this->_source, arc._source) && 01176 ker.equal_2_object() (this->_target, arc._target)) || 01177 (ker.equal_2_object() (this->_source, arc._target) && 01178 ker.equal_2_object() (this->_target, arc._source))); 01179 } 01180 01181 if (this->_orient == arc._orient) 01182 { 01183 // Same orientation - the source and target points must be the same. 01184 return (ker.equal_2_object() (this->_source, arc._source) && 01185 ker.equal_2_object() (this->_target, arc._target)); 01186 } 01187 else 01188 { 01189 // Reverse orientation - the source and target points must be swapped. 01190 return (ker.equal_2_object() (this->_source, arc._target) && 01191 ker.equal_2_object() (this->_target, arc._source)); 01192 } 01193 } 01194 01201 bool can_merge_with (const Self& arc) const 01202 { 01203 // In order to merge the two arcs, they should have the same supporting 01204 // conic. 01205 if (! _has_same_supporting_conic (arc)) 01206 return (false); 01207 01208 // Check if the left endpoint of one curve is the right endpoint of the 01209 // other. 01210 Alg_kernel ker; 01211 01212 return (ker.equal_2_object() (right(), arc.left()) || 01213 ker.equal_2_object() (left(), arc.right())); 01214 } 01215 01221 void merge (const Self& arc) 01222 { 01223 CGAL_precondition (this->can_merge_with (arc)); 01224 01225 // Check if we should extend the arc to the left or to the right. 01226 Alg_kernel ker; 01227 01228 if (ker.equal_2_object() (right(), arc.left())) 01229 { 01230 // Extend the arc to the right. 01231 if ((this->_info & IS_DIRECTED_RIGHT) != 0) 01232 this->_target = arc.right(); 01233 else 01234 this->_source = arc.right(); 01235 } 01236 else 01237 { 01238 CGAL_precondition (ker.equal_2_object() (left(), arc.right())); 01239 01240 // Extend the arc to the left. 01241 if ((this->_info & IS_DIRECTED_RIGHT) != 0) 01242 this->_source = arc.left(); 01243 else 01244 this->_target = arc.left(); 01245 } 01246 01247 return; 01248 } 01249 01250 bool is_upper() const 01251 { 01252 return ((this->_info & FACING_UP) != 0); 01253 } 01254 01255 bool is_lower() const 01256 { 01257 return ((this->_info & FACING_DOWN) != 0); 01258 } 01260 01261 private: 01262 01264 01265 01270 void _set () 01271 { 01272 // Convert the coefficients of the supporting conic to algebraic numbers. 01273 Nt_traits nt_traits; 01274 01275 alg_r = nt_traits.convert (this->_r); 01276 alg_s = nt_traits.convert (this->_s); 01277 alg_t = nt_traits.convert (this->_t); 01278 alg_u = nt_traits.convert (this->_u); 01279 alg_v = nt_traits.convert (this->_v); 01280 alg_w = nt_traits.convert (this->_w); 01281 01282 // Set the generating conic ID for the source and target points. 01283 this->_source.set_generating_conic (_id); 01284 this->_target.set_generating_conic (_id); 01285 01286 // Clear the _info bits. 01287 this->_info = Conic_arc_2::IS_VALID; 01288 01289 // Check if the arc is directed right (the target is lexicographically 01290 // greater than the source point), or to the left. 01291 Alg_kernel ker; 01292 Comparison_result dir_res = ker.compare_xy_2_object() (this->_source, 01293 this->_target); 01294 01295 CGAL_assertion (dir_res != EQUAL); 01296 01297 if (dir_res == SMALLER) 01298 this->_info = (this->_info | IS_DIRECTED_RIGHT); 01299 01300 // Compute the degree of the underlying conic. 01301 if (CGAL::sign (this->_r) != ZERO || 01302 CGAL::sign (this->_s) != ZERO || 01303 CGAL::sign (this->_t) != ZERO) 01304 { 01305 this->_info = (this->_info | DEGREE_2); 01306 01307 if (this->_orient == COLLINEAR) 01308 { 01309 this->_info = (this->_info | IS_SPECIAL_SEGMENT); 01310 01311 if (ker.compare_x_2_object() (this->_source, this->_target) == EQUAL) 01312 { 01313 // The arc is a vertical segment: 01314 this->_info = (this->_info | IS_VERTICAL_SEGMENT); 01315 } 01316 01317 return; 01318 } 01319 } 01320 else 01321 { 01322 CGAL_assertion (CGAL::sign (this->_u) != ZERO || 01323 CGAL::sign (this->_v) != ZERO); 01324 01325 if (CGAL::sign (this->_v) == ZERO) 01326 { 01327 01328 // The supporting curve is of the form: _u*x + _w = 0 01329 this->_info = (this->_info | IS_VERTICAL_SEGMENT); 01330 } 01331 01332 this->_info = (this->_info | DEGREE_1); 01333 01334 return; 01335 } 01336 01337 if (this->_orient == COLLINEAR) 01338 return; 01339 01340 // Compute a midpoint between the source and the target and get the y-value 01341 // of the arc at its x-coordiante. 01342 Point_2 p_mid = ker.construct_midpoint_2_object() (this->_source, 01343 this->_target); 01344 Algebraic ys[2]; 01345 CGAL_assertion_code(int n_ys = ) 01346 _conic_get_y_coordinates (p_mid.x(), ys); 01347 01348 CGAL_assertion (n_ys != 0); 01349 01350 // Check which solution lies on the x-monotone arc. 01351 Point_2 p_arc_mid (p_mid.x(), ys[0]); 01352 01353 if (_is_strictly_between_endpoints (p_arc_mid)) 01354 { 01355 // Mark that we should use the -sqrt(disc) root for points on this 01356 // x-monotone arc. 01357 this->_info = (this->_info & ~PLUS_SQRT_DISC_ROOT); 01358 } 01359 else 01360 { 01361 CGAL_assertion (n_ys == 2); 01362 p_arc_mid = Point_2 (p_mid.x(), ys[1]); 01363 01364 CGAL_assertion (_is_strictly_between_endpoints (p_arc_mid)); 01365 01366 // Mark that we should use the +sqrt(disc) root for points on this 01367 // x-monotone arc. 01368 this->_info = (this->_info | PLUS_SQRT_DISC_ROOT); 01369 } 01370 01371 // Check whether the conic is facing up or facing down: 01372 // Check whether the arc (which is x-monotone of degree 2) lies above or 01373 // below the segement that contects its two end-points (x1,y1) and (x2,y2). 01374 // To do that, we find the y coordinate of a point on the arc whose x 01375 // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2. 01376 Comparison_result res = ker.compare_y_2_object() (p_arc_mid, p_mid); 01377 01378 if (res == LARGER) 01379 { 01380 // The arc is above the connecting segment, so it is facing upwards. 01381 this->_info = (this->_info | FACING_UP); 01382 } 01383 else if (res == SMALLER) 01384 { 01385 // The arc is below the connecting segment, so it is facing downwards. 01386 this->_info = (this->_info | FACING_DOWN); 01387 } 01388 01389 return; 01390 } 01391 01396 bool _is_special_segment () const 01397 { 01398 return ((this->_info & IS_SPECIAL_SEGMENT) != 0); 01399 } 01400 01407 bool _is_on_supporting_conic (const Algebraic& px, 01408 const Algebraic& py) const 01409 { 01410 CGAL::Sign _sign; 01411 01412 if (! _is_special_segment()) 01413 { 01414 // Check whether p satisfies the conic equation. 01415 // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0. 01416 _sign = CGAL::sign ((alg_r*px + alg_t*py + alg_u) * px + 01417 (alg_s*py + alg_v) * py + 01418 alg_w); 01419 } 01420 else 01421 { 01422 // Check whether p satisfies the equation of the line stored with the 01423 // extra data. 01424 _sign = _sign_of_extra_data (px, py); 01425 } 01426 01427 return (_sign == ZERO); 01428 } 01429 01435 bool _has_same_supporting_conic (const Self& arc) const 01436 { 01437 // Check if the two arcs originate from the same conic: 01438 if (_id == arc._id && _id.is_valid() && arc._id.is_valid()) 01439 return (true); 01440 01441 // In case both arcs are collinear, check if they have the same 01442 // supporting lines. 01443 if (this->_orient == COLLINEAR && arc._orient == COLLINEAR) 01444 { 01445 // Construct the two supporting lines and compare them. 01446 Alg_kernel ker; 01447 typename Alg_kernel::Construct_line_2 construct_line = 01448 ker.construct_line_2_object(); 01449 typename Alg_kernel::Line_2 l1 = construct_line (this->_source, 01450 this->_target); 01451 typename Alg_kernel::Line_2 l2 = construct_line (arc._source, 01452 arc._target); 01453 typename Alg_kernel::Equal_2 equal = ker.equal_2_object(); 01454 01455 if (equal (l1, l2)) 01456 return (true); 01457 01458 // Try to compare l1 with the opposite of l2. 01459 l2 = construct_line (arc._target, arc._source); 01460 01461 return (equal (l1, l2)); 01462 } 01463 else if (this->_orient == COLLINEAR || arc._orient == COLLINEAR) 01464 { 01465 // Only one arc is collinear, so the supporting curves cannot be the 01466 // same: 01467 return (false); 01468 } 01469 01470 // Check whether the coefficients of the two supporting conics are equal 01471 // up to a constant factor. 01472 Integer factor1 = 1; 01473 Integer factor2 = 1; 01474 01475 if (CGAL::sign (this->_r) != ZERO) 01476 factor1 = this->_r; 01477 else if (CGAL::sign (this->_s) != ZERO) 01478 factor1 = this->_s; 01479 else if (CGAL::sign (this->_t) != ZERO) 01480 factor1 = this->_t; 01481 else if (CGAL::sign (this->_u) != ZERO) 01482 factor1 = this->_u; 01483 else if (CGAL::sign (this->_v) != ZERO) 01484 factor1 = this->_v; 01485 else if (CGAL::sign (this->_w) != ZERO) 01486 factor1 = this->_w; 01487 01488 if (CGAL::sign (arc._r) != ZERO) 01489 factor2 = arc._r; 01490 else if (CGAL::sign (arc._s) != ZERO) 01491 factor2 = arc._s; 01492 else if (CGAL::sign (arc._t) != ZERO) 01493 factor2 = arc._t; 01494 else if (CGAL::sign (arc._u) != ZERO) 01495 01496 factor2 = arc._u; 01497 else if (CGAL::sign (arc._v) != ZERO) 01498 factor2 = arc._v; 01499 else if (CGAL::sign (arc._w) != ZERO) 01500 factor2 = arc._w; 01501 01502 return (CGAL::compare (this->_r * factor2, arc._r * factor1) == EQUAL && 01503 CGAL::compare (this->_s * factor2, arc._s * factor1) == EQUAL && 01504 CGAL::compare (this->_t * factor2, arc._t * factor1) == EQUAL && 01505 CGAL::compare (this->_u * factor2, arc._u * factor1) == EQUAL && 01506 CGAL::compare (this->_v * factor2, arc._v * factor1) == EQUAL && 01507 CGAL::compare (this->_w * factor2, arc._w * factor1) == EQUAL); 01508 } 01509 01518 void _derive_by_x_at (const Point_2& p, const unsigned int& i, 01519 Algebraic& slope_numer, Algebraic& slope_denom) const 01520 { 01521 if (_is_special_segment()) 01522 { 01523 // Special treatment for special segments, given by (a*x + b*y + c = 0), 01524 // so their first-order derivative by x is simply -a/b. The higher-order 01525 // derivatives are all 0. 01526 if (i == 1) 01527 { 01528 if (CGAL::sign (this->_extra_data_P->b) != NEGATIVE) 01529 { 01530 slope_numer = - this->_extra_data_P->a; 01531 slope_denom = this->_extra_data_P->b; 01532 } 01533 else 01534 { 01535 slope_numer = this->_extra_data_P->a; 01536 slope_denom = - this->_extra_data_P->b; 01537 } 01538 } 01539 else 01540 { 01541 slope_numer = 0; 01542 slope_denom = 1; 01543 } 01544 01545 return; 01546 } 01547 01548 // The derivative by x of the conic 01549 // C: {r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0} 01550 // at the point p=(x,y) is given by: 01551 // 01552 // 2r*x + t*y + u alpha 01553 // y' = - ---------------- = - ------- 01554 // 2s*y + t*x + v beta 01555 // 01556 const Algebraic _two = 2; 01557 const Algebraic sl_numer = _two*alg_r*p.x() + alg_t*p.y() + alg_u; 01558 const Algebraic sl_denom = _two*alg_s*p.y() + alg_t*p.x() + alg_v; 01559 01560 if (i == 1) 01561 { 01562 // Make sure that the denominator is always positive. 01563 if (CGAL::sign (sl_denom) != NEGATIVE) 01564 { 01565 slope_numer = -sl_numer; 01566 slope_denom = sl_denom; 01567 } 01568 else 01569 { 01570 slope_numer = sl_numer; 01571 slope_denom = -sl_denom; 01572 } 01573 01574 return; 01575 } 01576 01577 // The second-order derivative is given by: 01578 // 01579 // s*alpha^2 - t*alpha*beta + r*beta^2 gamma 01580 // y'' = -2 ------------------------------------- = ------- 01581 // beta^3 delta 01582 // 01583 const Algebraic sl2_numer = alg_s * sl_numer*sl_numer - 01584 alg_t * sl_numer*sl_denom + 01585 alg_r * sl_denom*sl_denom; 01586 const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; 01587 01588 if (i == 2) 01589 { 01590 // Make sure that the denominator is always positive. 01591 if (CGAL::sign (sl_denom) != NEGATIVE) 01592 { 01593 slope_numer = -_two *sl2_numer; 01594 slope_denom = sl2_denom; 01595 } 01596 else 01597 { 01598 slope_numer = _two *sl2_numer; 01599 slope_denom = -sl2_denom; 01600 } 01601 01602 return; 01603 } 01604 01605 // The third-order derivative is given by: 01606 // 01607 // (2s*alpha - t*beta) * gamma 01608 // y''' = -6 ------------------------------ 01609 // beta^2 * delta 01610 // 01611 const Algebraic sl3_numer = (_two * alg_s * sl_numer - 01612 alg_t * sl_denom) * sl2_numer; 01613 const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; 01614 01615 if (i == 3) 01616 { 01617 // Make sure that the denominator is always positive. 01618 if (CGAL::sign (sl_denom) != NEGATIVE) 01619 { 01620 slope_numer = -6 * sl3_numer; 01621 slope_denom = sl3_denom; 01622 } 01623 else 01624 { 01625 slope_numer = 6 * sl3_numer; 01626 slope_denom = -sl2_denom; 01627 } 01628 01629 return; 01630 } 01631 01632 // \todo Handle higher-order derivatives as well. 01633 CGAL_error(); 01634 return; 01635 } 01636 01645 void _derive_by_y_at (const Point_2& p, const int& i, 01646 Algebraic& slope_numer, Algebraic& slope_denom) const 01647 { 01648 if (_is_special_segment()) 01649 { 01650 // Special treatment for special segments, given by (a*x + b*y + c = 0), 01651 // so their first-order derivative by x is simply -b/a. The higher-order 01652 // derivatives are all 0. 01653 if (i == 1) 01654 { 01655 if (CGAL::sign (this->_extra_data_P->a) != NEGATIVE) 01656 { 01657 slope_numer = - this->_extra_data_P->b; 01658 slope_denom = this->_extra_data_P->a; 01659 } 01660 else 01661 { 01662 slope_numer = this->_extra_data_P->b; 01663 slope_denom = - this->_extra_data_P->a; 01664 } 01665 } 01666 else 01667 { 01668 slope_numer = 0; 01669 slope_denom = 1; 01670 } 01671 01672 return; 01673 } 01674 01675 // The derivative by y of the conic 01676 // C: {r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0} 01677 // at the point p=(x,y) is given by: 01678 // 01679 // 2s*y + t*x + v alpha 01680 // x' = - ---------------- = ------- 01681 // 2r*x + t*y + u beta 01682 // 01683 const Algebraic _two = 2; 01684 const Algebraic sl_numer = _two*alg_s*p.y() + alg_t*p.x() + alg_v; 01685 const Algebraic sl_denom = _two*alg_r*p.x() + alg_t*p.y() + alg_u; 01686 01687 if (i == 1) 01688 { 01689 // Make sure that the denominator is always positive. 01690 if (CGAL::sign (sl_denom) != NEGATIVE) 01691 { 01692 slope_numer = -sl_numer; 01693 slope_denom = sl_denom; 01694 } 01695 else 01696 { 01697 slope_numer = sl_numer; 01698 slope_denom = -sl_denom; 01699 } 01700 01701 01702 return; 01703 } 01704 01705 // The second-order derivative is given by: 01706 // 01707 // r*alpha^2 - t*alpha*beta + s*beta^2 01708 // x'' = -2 ------------------------------------- 01709 // beta^3 01710 // 01711 const Algebraic sl2_numer = alg_r * sl_numer*sl_numer - 01712 alg_t * sl_numer*sl_denom + 01713 alg_s * sl_denom*sl_denom; 01714 const Algebraic sl2_denom = sl_denom*sl_denom*sl_denom; 01715 01716 if (i == 2) 01717 { 01718 01719 // Make sure that the denominator is always positive. 01720 if (CGAL::sign (sl_denom) != NEGATIVE) 01721 { 01722 slope_numer = -_two *sl2_numer; 01723 slope_denom = sl2_denom; 01724 } 01725 else 01726 { 01727 slope_numer = _two *sl2_numer; 01728 slope_denom = -sl2_denom; 01729 } 01730 01731 return; 01732 } 01733 01734 // The third-order derivative is given by: 01735 // 01736 // (2t*alpha - t*beta) * gamma 01737 // y''' = -6 ------------------------------ 01738 // beta^2 * delta 01739 // 01740 const Algebraic sl3_numer = (_two * alg_r * sl_numer - 01741 alg_t * sl_denom) * sl2_numer; 01742 const Algebraic sl3_denom = sl_denom*sl_denom * sl2_denom; 01743 01744 if (i == 3) 01745 { 01746 // Make sure that the denominator is always positive. 01747 if (CGAL::sign (sl_denom) != NEGATIVE) 01748 { 01749 slope_numer = -6 * sl3_numer; 01750 slope_denom = sl3_denom; 01751 } 01752 else 01753 { 01754 slope_numer = 6 * sl3_numer; 01755 slope_denom = -sl2_denom; 01756 } 01757 01758 return; 01759 } 01760 01761 // \todo Handle higher-order derivatives as well. 01762 CGAL_error(); 01763 return; 01764 } 01765 01773 bool _compute_overlap (const Self& arc, Self& overlap) const 01774 { 01775 // Check if the two arcs are identical. 01776 if (equals (arc)) 01777 { 01778 overlap = arc; 01779 return (true); 01780 } 01781 01782 if (_is_strictly_between_endpoints (arc.left())) 01783 { 01784 if (_is_strictly_between_endpoints(arc.right())) 01785 { 01786 // Case 1 - *this: +-----------> 01787 // arc: +=====> 01788 overlap = arc; 01789 return (true); 01790 } 01791 else 01792 { 01793 // Case 2 - *this: +-----------> 01794 // arc: +=====> 01795 overlap = *this; 01796 01797 if ((overlap._info & IS_DIRECTED_RIGHT) != 0) 01798 overlap._source = arc.left(); 01799 else 01800 overlap._target = arc.left(); 01801 01802 return (true); 01803 } 01804 } 01805 else if (_is_strictly_between_endpoints (arc.right())) 01806 { 01807 // Case 3 - *this: +-----------> 01808 // arc: +=====> 01809 overlap = *this; 01810 01811 if ((overlap._info & IS_DIRECTED_RIGHT) != 0) 01812 overlap._target = arc.right(); 01813 else 01814 overlap._source = arc.right(); 01815 01816 return (true); 01817 } 01818 else if (arc._is_between_endpoints (this->_source) && 01819 arc._is_between_endpoints (this->_target) && 01820 (arc._is_strictly_between_endpoints(this->_source) || 01821 arc._is_strictly_between_endpoints(this->_target))) 01822 { 01823 // Case 4 - *this: +-----------> 01824 // arc: +================> 01825 overlap = *this; 01826 return (true); 01827 } 01828 01829 // If we reached here, there are no overlaps: 01830 return (false); 01831 } 01832 01838 void _intersect_supporting_conics (const Self& arc, 01839 Intersection_list& inter_list) const 01840 { 01841 if (_is_special_segment() && ! arc._is_special_segment()) 01842 { 01843 // If one of the arcs is a special segment, make sure it is (arc). 01844 arc._intersect_supporting_conics (*this, inter_list); 01845 return; 01846 } 01847 01848 const int deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; 01849 const int deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; 01850 Nt_traits nt_traits; 01851 Algebraic xs[4]; 01852 int n_xs = 0; 01853 Algebraic ys[4]; 01854 int n_ys = 0; 01855 01856 if (arc._is_special_segment()) 01857 { 01858 // The second arc is a special segment (a*x + b*y + c = 0). 01859 if (_is_special_segment()) 01860 { 01861 // Both arc are sepcial segment, so they have at most one intersection 01862 // point. 01863 Algebraic denom = this->_extra_data_P->a * arc._extra_data_P->b - 01864 this->_extra_data_P->b * arc._extra_data_P->a; 01865 01866 if (CGAL::sign (denom) != CGAL::ZERO) 01867 { 01868 xs[0] = (this->_extra_data_P->b * arc._extra_data_P->c - 01869 this->_extra_data_P->c * arc._extra_data_P->b) / denom; 01870 n_xs = 1; 01871 01872 ys[0] = (this->_extra_data_P->c * arc._extra_data_P->a - 01873 this->_extra_data_P->a * arc._extra_data_P->c) / denom; 01874 n_ys = 1; 01875 } 01876 } 01877 else 01878 { 01879 // Compute the x-coordinates of the intersection points. 01880 n_xs = _compute_resultant_roots (nt_traits, 01881 alg_r, alg_s, alg_t, 01882 alg_u, alg_v, alg_w, 01883 deg1, 01884 arc._extra_data_P->a, 01885 arc._extra_data_P->b, 01886 arc._extra_data_P->c, 01887 xs); 01888 CGAL_assertion (n_xs <= 2); 01889 01890 // Compute the y-coordinates of the intersection points. 01891 n_ys = _compute_resultant_roots (nt_traits, 01892 alg_s, alg_r, alg_t, 01893 alg_v, alg_u, alg_w, 01894 deg1, 01895 arc._extra_data_P->b, 01896 arc._extra_data_P->a, 01897 arc._extra_data_P->c, 01898 ys); 01899 CGAL_assertion (n_ys <= 2); 01900 } 01901 } 01902 else 01903 { 01904 // Compute the x-coordinates of the intersection points. 01905 n_xs = _compute_resultant_roots (nt_traits, 01906 this->_r, this->_s, this->_t, 01907 this->_u, this->_v, this->_w, 01908 deg1, 01909 arc._r, arc._s, arc._t, 01910 arc._u, arc._v, arc._w, 01911 deg2, 01912 xs); 01913 CGAL_assertion (n_xs <= 4); 01914 01915 // Compute the y-coordinates of the intersection points. 01916 n_ys = _compute_resultant_roots (nt_traits, 01917 this->_s, this->_r, this->_t, 01918 this->_v, this->_u, this->_w, 01919 deg1, 01920 arc._s, arc._r, arc._t, 01921 arc._v, arc._u, arc._w, 01922 deg2, 01923 ys); 01924 CGAL_assertion (n_ys <= 4); 01925 } 01926 01927 // Pair the coordinates of the intersection points. As the vectors of 01928 // x and y-coordinates are sorted in ascending order, we output the 01929 // intersection points in lexicographically ascending order. 01930 unsigned int mult; 01931 int i, j; 01932 01933 if (arc._is_special_segment()) 01934 { 01935 if (n_xs == 0 || n_ys == 0) 01936 return; 01937 01938 if (n_xs == 1 && n_ys == 1) 01939 { 01940 // Single intersection. 01941 Conic_point_2 ip (xs[0], ys[0]); 01942 01943 ip.set_generating_conic (_id); 01944 ip.set_generating_conic (arc._id); 01945 01946 // In case the other curve is of degree 2, this is a tangency point. 01947 mult = (deg1 == 1 || _is_special_segment()) ? 1 : 2; 01948 inter_list.push_back (Intersection_point_2 (ip, mult)); 01949 } 01950 else if (n_xs == 1 && n_ys == 2) 01951 { 01952 Conic_point_2 ip1 (xs[0], ys[0]); 01953 01954 ip1.set_generating_conic (_id); 01955 ip1.set_generating_conic (arc._id); 01956 01957 inter_list.push_back (Intersection_point_2 (ip1, 1)); 01958 01959 Conic_point_2 ip2 (xs[0], ys[1]); 01960 01961 ip2.set_generating_conic (_id); 01962 ip2.set_generating_conic (arc._id); 01963 01964 inter_list.push_back (Intersection_point_2 (ip2, 1)); 01965 } 01966 else if (n_xs == 2 && n_ys == 1) 01967 { 01968 Conic_point_2 ip1 (xs[0], ys[0]); 01969 01970 ip1.set_generating_conic (_id); 01971 ip1.set_generating_conic (arc._id); 01972 01973 inter_list.push_back (Intersection_point_2 (ip1, 1)); 01974 01975 Conic_point_2 ip2 (xs[1], ys[0]); 01976 01977 ip2.set_generating_conic (_id); 01978 ip2.set_generating_conic (arc._id); 01979 01980 inter_list.push_back (Intersection_point_2 (ip2, 1)); 01981 01982 } 01983 else 01984 { 01985 CGAL_assertion (n_xs == 2 && n_ys == 2); 01986 01987 // The x-coordinates and the y-coordinates are given in ascending 01988 // order. If the slope of the segment is positive, we pair the 01989 // coordinates as is - otherwise, we swap the pairs. 01990 int ind_first_y = 0, ind_second_y = 1; 01991 01992 if (CGAL::sign (arc._extra_data_P->b) == 01993 CGAL::sign(arc._extra_data_P->a)) 01994 { 01995 ind_first_y = 1; 01996 ind_second_y = 0; 01997 } 01998 01999 Conic_point_2 ip1 (xs[0], ys[ind_first_y]); 02000 02001 ip1.set_generating_conic (_id); 02002 ip1.set_generating_conic (arc._id); 02003 02004 inter_list.push_back (Intersection_point_2 (ip1, 1)); 02005 02006 Conic_point_2 ip2 (xs[1], ys[ind_second_y]); 02007 02008 ip2.set_generating_conic (_id); 02009 ip2.set_generating_conic (arc._id); 02010 02011 inter_list.push_back (Intersection_point_2 (ip2, 1)); 02012 } 02013 02014 return; 02015 } 02016 02017 for (i = 0; i < n_xs; i++) 02018 { 02019 for (j = 0; j < n_ys; j++) 02020 { 02021 if (_is_on_supporting_conic (xs[i], ys[j]) && 02022 arc._is_on_supporting_conic (xs[i], ys[j])) 02023 { 02024 // Create the intersection point and set its generating conics. 02025 Conic_point_2 ip (xs[i], ys[j]); 02026 02027 ip.set_generating_conic (_id); 02028 ip.set_generating_conic (arc._id); 02029 02030 // Compute the multiplicity of the intersection point. 02031 if (deg1 == 1 && deg2 == 1) 02032 mult = 1; 02033 else 02034 mult = _multiplicity_of_intersection_point (arc, ip); 02035 02036 // Insert the intersection point to the output list. 02037 inter_list.push_back (Intersection_point_2 (ip, mult)); 02038 } 02039 } 02040 } 02041 02042 return; 02043 } 02044 02051 unsigned int _multiplicity_of_intersection_point (const Self& arc, 02052 const Point_2& p) const 02053 { 02054 CGAL_assertion (! _is_special_segment() || ! arc._is_special_segment()); 02055 02056 // Compare the slopes of the two arcs at p, using their first-order 02057 // partial derivatives. 02058 Algebraic slope1_numer, slope1_denom; 02059 Algebraic slope2_numer, slope2_denom; 02060 02061 _derive_by_x_at (p, 1, slope1_numer, slope1_denom); 02062 arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); 02063 02064 if (CGAL::compare (slope1_numer*slope2_denom, 02065 slope2_numer*slope1_denom) != EQUAL) 02066 { 02067 // Different slopes at p - the mutiplicity of p is 1: 02068 return (1); 02069 } 02070 02071 if (CGAL::sign (slope1_denom) != ZERO && 02072 CGAL::sign (slope2_denom) != ZERO) 02073 { 02074 // The curves do not have a vertical slope at p. 02075 // Compare their second-order derivative by x: 02076 _derive_by_x_at (p, 2, slope1_numer, slope1_denom); 02077 arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); 02078 } 02079 else 02080 { 02081 // Both curves have a vertical slope at p. 02082 // Compare their second-order derivative by y: 02083 _derive_by_y_at (p, 2, slope1_numer, slope1_denom); 02084 arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); 02085 } 02086 02087 if (CGAL::compare (slope1_numer*slope2_denom, 02088 slope2_numer*slope1_denom) != EQUAL) 02089 { 02090 // Different curvatures at p - the mutiplicity of p is 2: 02091 return (2); 02092 } 02093 02094 // If we reached here, the multiplicity of the intersection point is 3: 02095 return (3); 02096 } 02098 02099 }; 02100 02104 template <class Conic_arc_2> 02105 std::ostream& operator<< (std::ostream& os, 02106 const _Conic_x_monotone_arc_2<Conic_arc_2>& arc) 02107 { 02108 // Output the supporting conic curve. 02109 os << "{" << CGAL::to_double(arc.r()) << "*x^2 + " 02110 << CGAL::to_double(arc.s()) << "*y^2 + " 02111 << CGAL::to_double(arc.t()) << "*xy + " 02112 << CGAL::to_double(arc.u()) << "*x + " 02113 << CGAL::to_double(arc.v()) << "*y + " 02114 << CGAL::to_double(arc.w()) << "}"; 02115 02116 // Output the endpoints. 02117 os << " : (" << CGAL::to_double(arc.source().x()) << "," 02118 << CGAL::to_double(arc.source().y()) << ") "; 02119 02120 if (arc.orientation() == CLOCKWISE) 02121 os << "--cw-->"; 02122 else if (arc.orientation() == COUNTERCLOCKWISE) 02123 os << "--ccw-->"; 02124 else 02125 os << "--l-->"; 02126 02127 os << " (" << CGAL::to_double(arc.target().x()) << "," 02128 << CGAL::to_double(arc.target().y()) << ")"; 02129 02130 return (os); 02131 } 02132 02133 CGAL_END_NAMESPACE 02134 02135 #endif