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