1 // Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). 2 // All rights reserved. 3 // 4 // This file is part of CGAL (www.cgal.org) 5 // 6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CPA_1.h $ 7 // $Id: Status_line_CPA_1.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot 8 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial 9 // 10 // 11 // Author(s) : Pavel Emeliyanenko <asm@mpi-sb.mpg.de> 12 // 13 // ============================================================================ 14 15 #ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H 16 #define CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H 17 18 #include <CGAL/basic.h> 19 #include <CGAL/Handle_with_policy.h> 20 #include <CGAL/algorithm.h> 21 22 namespace CGAL { 23 24 namespace internal { 25 26 template < class CurvePairAnalysis_2, class Rep_ > 27 class Status_line_CPA_1; 28 29 template <class CurvePairAnalysis_2, class Rep> 30 std::ostream& operator<< (std::ostream&, 31 const Status_line_CPA_1<CurvePairAnalysis_2, Rep>&); 32 33 template < class CurvePairAnalysis_2 > 34 class Status_line_CPA_1_rep { 35 36 // this template argument 37 typedef CurvePairAnalysis_2 Curve_pair_analysis_2; 38 39 // myself 40 typedef Status_line_CPA_1_rep<Curve_pair_analysis_2> Self; 41 42 // type of x-coordinate 43 typedef typename Curve_pair_analysis_2::Algebraic_real_1 44 Algebraic_real_1; 45 46 // type of a curve point 47 typedef typename Curve_pair_analysis_2::Algebraic_real_2 48 Algebraic_real_2; 49 50 // an instance of a size type 51 typedef typename Curve_pair_analysis_2::size_type size_type; 52 53 // encodes number of arcs to the left and to the right 54 typedef std::pair<size_type, size_type> Arc_pair; 55 56 // container of arcs 57 typedef std::vector<Arc_pair> Arc_container; 58 59 // container of integers ? 60 typedef std::vector<size_type> Int_container; 61 62 // constructors 63 public: 64 // default constructor () Status_line_CPA_1_rep()65 Status_line_CPA_1_rep() 66 { } 67 68 // constructs an empty status line object Status_line_CPA_1_rep(size_type i,Curve_pair_analysis_2 cpa)69 Status_line_CPA_1_rep(size_type i, Curve_pair_analysis_2 cpa) : 70 _m_index(i), _m_cpa(cpa), _m_event(false), _m_intersection(false) { 71 } 72 73 // stores this status line interval or event index of a curve pair 74 size_type _m_index; 75 76 // represents x-coordinate of event of rational value over interval 77 // computed only by demand 78 mutable boost::optional<Algebraic_real_1> _m_x; 79 80 // for each event point stores a pair of arcnos of the 1st and 2nd curve 81 // or -1 if respective curve is not involved 82 mutable Arc_container _m_arcs; 83 84 // inverse mapping from arcnos of the 1st and 2nd curve to respective 85 // y-position 86 mutable Int_container _m_arcno_to_pos[2]; 87 88 // stores multiplicities of intersection points (-1 if there is no 2-curve 89 // intersection) 90 mutable Int_container _m_mults; 91 92 // underlying curve pair analysis 93 Curve_pair_analysis_2 _m_cpa; 94 95 // is there an event 96 mutable bool _m_event; 97 98 // is there is an intersection of both curves 99 mutable bool _m_intersection; 100 101 // befriending the handle 102 friend class Status_line_CPA_1<Curve_pair_analysis_2, Self>; 103 }; 104 105 //! \brief The class provides information about the intersections of a pair of 106 //! curves with a (intended) vertical line (ignoring vertical lines of the 107 //! curves themselves). 108 //! 109 //! Each intersection of a curve with the vertical line defined by some given x 110 //! induces an event. An event can be asked for its coordinates 111 //! (\c Algebraic_real_2) and the involved curve(s). Note that the involvement 112 //! also holds for curve ends approaching the vertical asymptote. 113 //! Curve_pair_vertical_line_1 at x = +/-oo are not allowed. 114 template <class CurvePairAnalysis_2, 115 class Rep_ = internal::Status_line_CPA_1_rep<CurvePairAnalysis_2> > 116 class Status_line_CPA_1 : 117 public ::CGAL::Handle_with_policy< Rep_ > 118 { 119 public: 120 //!@{ 121 //!\name typedefs 122 123 //! this instance's first template parameter 124 typedef CurvePairAnalysis_2 Curve_pair_analysis_2; 125 126 //! this instance's second template parameter 127 typedef Rep_ Rep; 128 129 //! this instance itself 130 typedef Status_line_CPA_1<Curve_pair_analysis_2, Rep> Self; 131 132 //! type of x-coordinate 133 typedef typename Curve_pair_analysis_2::Algebraic_real_1 Algebraic_real_1; 134 135 //! type of a curve point 136 typedef typename Curve_pair_analysis_2::Algebraic_real_2 Algebraic_real_2; 137 138 //! an instance of a size type 139 typedef typename Curve_pair_analysis_2::size_type size_type; 140 141 //! encodes number of arcs to the left and to the right 142 typedef std::pair<size_type, size_type> Arc_pair; 143 144 //! container of arcs 145 typedef std::vector<Arc_pair> Arc_container; 146 147 //! container of integers ? 148 typedef std::vector<size_type> Int_container; 149 150 //! the handle superclass 151 typedef ::CGAL::Handle_with_policy< Rep > Base; 152 153 //!@} 154 public: 155 //!\name constructors 156 //!@{ 157 158 /*!\brief 159 * Default constructor 160 */ Status_line_CPA_1()161 Status_line_CPA_1() : 162 Base(Rep()) { 163 } 164 165 /*!\brief 166 * copy constructor 167 */ 168 #ifdef DOXYGEN_RUNNING Status_line_CPA_1(const Self & p)169 Status_line_CPA_1(const Self& p) : 170 Base(static_cast<const Base&>(p)) { 171 } 172 #endif 173 174 /*!\brief 175 * constructs undefined status line 176 */ Status_line_CPA_1(size_type i,Curve_pair_analysis_2 cpa)177 Status_line_CPA_1(size_type i, Curve_pair_analysis_2 cpa) : 178 Base(Rep(i, cpa)) { 179 } 180 181 /*!\brief 182 * constructs a status line at the \c i -th event of a curve pair 183 * 184 * each element of \c arcs is a pair with the first item specifying the 185 * type of event (0 - event of the 1st curve, 1 - of the second curve, 186 * 2 - of both curves), and the second item - multiplicity of intersection 187 * or -1 if not available 188 */ Status_line_CPA_1(size_type i,const Arc_container & arcs,Curve_pair_analysis_2 cpa)189 Status_line_CPA_1(size_type i, const Arc_container& arcs, 190 Curve_pair_analysis_2 cpa) : 191 Base(Rep(i, cpa)) { 192 _set_event_arcs(arcs); 193 } 194 195 /*!\brief 196 * constructs a status line over the \c i -th interval of a curve pair 197 * 198 * each element of \c arcs specifies to which curve a respective arc 199 * belongs to (0 - arc of the 1st curve, 1 - arc of the 2nd curve) 200 * \c is_swapped defines that the curves in targeting curve pair analysis 201 * were swapped during precaching 202 */ Status_line_CPA_1(size_type i,const Int_container & arcs,Curve_pair_analysis_2 cpa)203 Status_line_CPA_1(size_type i, const Int_container& arcs, 204 Curve_pair_analysis_2 cpa) : 205 Base(Rep(i, cpa)) { 206 _set_interval_arcs(arcs); 207 } 208 209 protected: 210 /*!\brief 211 * constructs from a given represenation 212 */ Status_line_CPA_1(Rep rep)213 Status_line_CPA_1(Rep rep) : 214 Base(rep) { 215 } 216 217 //!@} 218 public: 219 //!\name access functions 220 //!@{ 221 222 /*! \brief 223 * returns the x-coordinate of the vertical line (always a finite value). 224 */ x()225 Algebraic_real_1 x() const { 226 // unless x-coordiate was explicitly set with _set_x: compute its value 227 if(!this->ptr()->_m_x) { 228 this->ptr()->_m_x = (is_event() ? 229 #if CGAL_ACK_USE_EXACUS 230 this->ptr()->_m_cpa._internal_curve_pair().event_x(index()) : 231 Algebraic_real_1(this->ptr()->_m_cpa._internal_curve_pair(). 232 bound_value_in_interval(index()))); 233 #else 234 this->ptr()->_m_cpa.event_x(index()) : 235 Algebraic_real_1(this->ptr()->_m_cpa. 236 bound_value_in_interval(index()))); 237 #endif 238 } 239 return *(this->ptr()->_m_x); 240 } 241 242 //! returns this vertical line's index (event or interval index) index()243 size_type index() const { 244 CGAL_precondition(this->ptr()->_m_index>=0); 245 return this->ptr()->_m_index; 246 } 247 248 /*! \brief 249 * returns number of distinct and finite intersections of a pair 250 * of curves with a (intended) vertical line ignoring a real vertical 251 * line component of the curve at the given x-coordinate. 252 */ number_of_events()253 size_type number_of_events() const { 254 return static_cast<size_type>(this->ptr()->_m_arcs.size()); 255 } 256 257 258 /*! \brief 259 * returns the y-position of the k-th event of 260 * the curve in the sequence of events. 261 * 262 * Note that each event is formed by the 1st, 2nd, or both curves 263 * 264 * \pre 0 <= k < "number of arcs defined for curve c at x()" 265 */ event_of_curve(size_type k,const typename Curve_pair_analysis_2::Curve_analysis_2 & c)266 size_type event_of_curve(size_type k, 267 const typename Curve_pair_analysis_2 268 ::Curve_analysis_2& c) const { 269 CGAL_assertion(c.id()==this->ptr()->_m_cpa.curve_analysis(false).id()|| 270 c.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); 271 bool b = (c.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); 272 return event_of_curve(k,b); 273 } 274 275 276 277 278 /*! \brief 279 * returns the y-position of the k-th event of the c-th (0 or 1) 280 * curve in the sequence of events. 281 * 282 * Note that each event is formed by the 1st, 2nd, or both curves 283 * 284 * \pre 0 <= k < "number of arcs defined for curve[c] at x()" 285 */ event_of_curve(size_type k,bool c)286 size_type event_of_curve(size_type k, bool c) const { 287 288 CGAL_precondition_msg(0 <= k && 289 k < static_cast<size_type>(this->ptr()->_m_arcno_to_pos[c].size()), 290 "Invalid arc number of the c-th curve specified"); 291 return this->ptr()->_m_arcno_to_pos[c][k]; 292 } 293 294 /*! \brief 295 * returns the multiplicity of intersection defined at event with 296 * position \c j. May return -1 in case multiplicity is unknown. 297 * 298 * \pre There is an intersection of both curves at j-th event 299 * \pre 0 <= j < number_of_events() 300 */ multiplicity_of_intersection(size_type j)301 size_type multiplicity_of_intersection(size_type j) const 302 { 303 CGAL_precondition(0 <= j && j < number_of_events()); 304 CGAL_precondition(is_intersection()); 305 CGAL_precondition(this->ptr()->_m_arcs[j].first != -1 && 306 this->ptr()->_m_arcs[j].second != -1); 307 308 return this->ptr()->_m_mults[j]; 309 } 310 311 /*! \brief 312 * returns a pair of \c int indicating whether event \c j is formed 313 * by which arc numbers of the first and the second curve, or -1, if the 314 * corresponding curve is not involved. 315 * 316 * \pre 0 <= j < number_of_events() 317 */ curves_at_event(size_type j)318 Arc_pair curves_at_event(size_type j) const 319 { 320 CGAL_precondition(0 <= j && j < number_of_events()); 321 const Arc_pair& arc = this->ptr()->_m_arcs[j]; 322 return arc; 323 } 324 325 /*! 326 * returns an index indicating whether event \c j is formed 327 * by which arc numbers of the curve \c ca, or -1, if the 328 * corresponding curve is not involved. 329 */ curves_at_event(size_type j,const typename Curve_pair_analysis_2::Curve_analysis_2 & c1,const typename Curve_pair_analysis_2::Curve_analysis_2 & CGAL_precondition_code (c2))330 Arc_pair curves_at_event(size_type j, 331 const typename Curve_pair_analysis_2 332 ::Curve_analysis_2& c1, 333 const typename Curve_pair_analysis_2 334 ::Curve_analysis_2& CGAL_precondition_code(c2)) const 335 { 336 337 CGAL_precondition(0 <= j && j < number_of_events()); 338 CGAL_assertion(c1.id()!=c2.id()); 339 CGAL_assertion 340 (c1.id()==this->ptr()->_m_cpa.curve_analysis(false).id()|| 341 c1.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); 342 CGAL_assertion 343 (c2.id()==this->ptr()->_m_cpa.curve_analysis(false).id()|| 344 c2.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); 345 bool b = (c1.id()==this->ptr()->_m_cpa.curve_analysis(false).id()); 346 const Arc_pair& arc_pair = curves_at_event(j); 347 return b ? arc_pair : std::make_pair(arc_pair.second, arc_pair.first); 348 } 349 350 /*! \brief 351 * returns true if a curve has an event or in case there is an 352 * intersection of both curves. 353 */ is_event()354 bool is_event() const { 355 return this->ptr()->_m_event; 356 } 357 358 /*! \brief 359 * returns true if there is an intersection of both curves. 360 */ is_intersection()361 bool is_intersection() const { 362 return this->ptr()->_m_intersection; 363 } 364 365 //!@} 366 public: 367 //!@{ 368 369 /*!\brief 370 * sets x-coordinate of a status line 371 */ _set_x(Algebraic_real_1 x)372 void _set_x(Algebraic_real_1 x) const { 373 this->ptr()->_m_x = x; 374 } 375 376 /*!\brief 377 * sets arcs at event (use at your own risk!) 378 */ _set_event_arcs(const Arc_container & arcs)379 void _set_event_arcs(const Arc_container& arcs) const { 380 381 size_type k = 0, arcf = 0, arcg = 0; 382 this->ptr()->_m_arcs.resize(arcs.size()); 383 this->ptr()->_m_mults.resize(arcs.size()); 384 this->ptr()->_m_event = true; 385 386 for(typename Arc_container::const_iterator ait = arcs.begin(); 387 ait != arcs.end(); ait++, k++) { 388 389 if(ait->first == 0) { // 1st curve 390 this->ptr()->_m_arcs[k].first = arcf++; 391 this->ptr()->_m_arcs[k].second = -1; 392 this->ptr()->_m_arcno_to_pos[0].push_back(k); 393 394 } else if(ait->first == 1) { // 2nd curve 395 this->ptr()->_m_arcs[k].first = -1; 396 this->ptr()->_m_arcs[k].second = arcg++; 397 this->ptr()->_m_arcno_to_pos[1].push_back(k); 398 399 } else if(ait->first == 2) { // intersection 400 this->ptr()->_m_arcs[k].first = arcf++; 401 this->ptr()->_m_arcs[k].second = arcg++; 402 this->ptr()->_m_arcno_to_pos[0].push_back(k); 403 this->ptr()->_m_arcno_to_pos[1].push_back(k); 404 this->ptr()->_m_intersection = true; 405 406 } else 407 CGAL_error_msg("Bogus curve index.."); 408 this->ptr()->_m_mults[k] = ait->second; 409 } 410 } 411 412 /*!\brief 413 * sets arcs over interval (use at your own risk!) 414 */ _set_interval_arcs(const Int_container & arcs)415 void _set_interval_arcs(const Int_container& arcs) const { 416 417 this->ptr()->_m_arcs.resize(arcs.size()); 418 this->ptr()->_m_event = false; 419 this->ptr()->_m_intersection = false; 420 421 size_type k = 0, arcf = 0, arcg = 0; 422 for(typename Int_container::const_iterator ait = arcs.begin(); 423 ait != arcs.end(); ait++, k++) { 424 if(*ait == 0) { // 1st curve 425 this->ptr()->_m_arcs[k].first = arcf++; 426 this->ptr()->_m_arcs[k].second = -1; 427 this->ptr()->_m_arcno_to_pos[0].push_back(k); 428 429 } else if(*ait == 1) { // 2nd curve 430 this->ptr()->_m_arcs[k].first = -1; 431 this->ptr()->_m_arcs[k].second = arcg++; 432 this->ptr()->_m_arcno_to_pos[1].push_back(k); 433 434 } else 435 CGAL_error_msg("Bogus curve index.."); 436 } 437 } 438 439 //!@} 440 public: 441 //!\name IO 442 //!@{ 443 write(std::ostream & os)444 void write(std::ostream& os) const { 445 446 os << "status_line [CPA@" << this->ptr()->_m_cpa.id(); 447 448 os << "; x = " << (index()==-1 ? 999.999 : CGAL::to_double(x())) << "; #events: " << number_of_events() << "; "; 449 450 typename Arc_container::const_iterator ait = 451 this->ptr()->_m_arcs.begin(); 452 if(is_event()) 453 os << "arcs at event: {"; 454 else 455 os << "arcs of interval: {"; 456 457 for(; ait != this->ptr()->_m_arcs.end(); ait++) { 458 if(ait != this->ptr()->_m_arcs.begin()) 459 os << ", "; 460 os << "(" << ait->first << "; " << ait->second << ")"; 461 } 462 os << "}, arcno2pos: ("; 463 464 CGAL::output_range(os, this->ptr()->_m_arcno_to_pos[0].begin(), 465 this->ptr()->_m_arcno_to_pos[0].end(), ","); 466 os << "), ("; 467 CGAL::output_range(os, this->ptr()->_m_arcno_to_pos[1].begin(), 468 this->ptr()->_m_arcno_to_pos[1].end(), ","); 469 os << ")]"; 470 } 471 472 //!@} 473 }; // class Status_line_CPA_1 474 475 template <class CurvePairAnalysis_2, class Rep> 476 std::ostream& operator<< (std::ostream& os, 477 const internal::Status_line_CPA_1<CurvePairAnalysis_2, Rep>& sline) { 478 479 sline.write(os); 480 return os; 481 } 482 483 } // namespace internal 484 485 } //namespace CGAL 486 487 #endif // CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H 488