1 // Copyright (c) 2006,2007,2008,2009,2010,2011 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/Arrangement_on_surface_2/include/CGAL/Arr_algebraic_segment_traits_2.h $
7 // $Id: Arr_algebraic_segment_traits_2.h d08f8b4 2020-07-02T19:09:51+03:00 Efi Fogel
8 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s): Michael Kerber    <mkerber@mpi-inf.mpg.de>
12 //
13 // ============================================================================
14 
15 #ifndef CGAL_ARR_ALGEBRAIC_SEGMENT_TRAITS
16 #define CGAL_ARR_ALGEBRAIC_SEGMENT_TRAITS
17 
18 #include <CGAL/disable_warnings.h>
19 
20 #include <CGAL/config.h>
21 
22 #include <CGAL/Algebraic_kernel_d/flags.h>
23 #include <CGAL/Algebraic_kernel_d_1.h>
24 #include <CGAL/Algebraic_kernel_d/Algebraic_curve_kernel_2.h>
25 
26 #include <CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_impl.h>
27 
28 #include <boost/optional.hpp>
29 #include <boost/none.hpp>
30 
31 namespace CGAL {
32 
33 template< class Coefficient_ >
34 class Arr_algebraic_segment_traits_2 {
35 
36 public:
37 
38     enum Site_of_point {
39         POINT_IN_INTERIOR = 0,
40         MIN_ENDPOINT = -1,
41         MAX_ENDPOINT = 1 };
42 
43     // Template argument
44 
45     typedef Coefficient_ Coefficient;
46 
47     // 'derivation'
48     typedef CGAL::Algebraic_kernel_d_1< Coefficient > Algebraic_kernel_d_1;
49 
50     typedef CGAL::Algebraic_curve_kernel_2< Algebraic_kernel_d_1 >
51         Algebraic_kernel_d_2;
52 
53     typedef CGAL::Curved_kernel_via_analysis_2< Algebraic_kernel_d_2 > CKvA_2;
54 
55     typedef  CGAL::Arr_algebraic_segment_traits_2<Coefficient> Self;
56 
57     // Default constructor
Arr_algebraic_segment_traits_2()58     Arr_algebraic_segment_traits_2 () {}
59 
60 
61     // Copy constructor
Arr_algebraic_segment_traits_2(const Self &)62     Arr_algebraic_segment_traits_2 (const  Self& /* s */) { /* No state...*/}
63 
64     // Assignement operator
65     const Self& operator= (const Self& s)
66         {return s;}
67 
68     // public types
69 
70     typedef typename Algebraic_kernel_d_2::Algebraic_real_1 Algebraic_real_1;
71     typedef typename Algebraic_kernel_d_2::Bound Bound;
72 
73     typedef typename Algebraic_kernel_d_2::Polynomial_2 Polynomial_2;
74 
75     /// public types for ArrangementTraits_2
76 
77     typedef typename Algebraic_kernel_d_2::Curve_analysis_2 Curve_2;
78 
79     typedef typename CKvA_2::Arc_2 X_monotone_curve_2;
80 
81     typedef typename CKvA_2::Point_2 Point_2;
82 
83 
84     typedef typename CKvA_2::Has_left_category Has_left_category;
85     typedef typename CKvA_2::Has_merge_category Has_merge_category;
86     typedef typename CKvA_2::Has_do_intersect_category
87       Has_do_intersect_category;
88 
89     typedef typename CKvA_2::Left_side_category Left_side_category;
90     typedef typename CKvA_2::Bottom_side_category Bottom_side_category;
91     typedef typename CKvA_2::Top_side_category Top_side_category;
92     typedef typename CKvA_2::Right_side_category Right_side_category;
93 
94     typedef typename CKvA_2::Multiplicity Multiplicity;
95 
96     typedef typename CKvA_2::Compare_x_2 Compare_x_2;
compare_x_2_object()97     Compare_x_2 compare_x_2_object() const {
98         return CKvA_2::instance().compare_x_2_object();
99     }
100 
101     typedef typename CKvA_2::Compare_xy_2 Compare_xy_2;
compare_xy_2_object()102     Compare_xy_2 compare_xy_2_object() const {
103         return CKvA_2::instance().compare_xy_2_object();
104     }
105 
106     typedef typename CKvA_2::Compare_endpoints_xy_2 Compare_endpoints_xy_2;
compare_endpoints_xy_2_object()107     Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const {
108         return CKvA_2::instance().compare_endpoints_xy_2_object();
109     }
110 
111     typedef typename CKvA_2::Equal_2 Equal_2;
equal_2_object()112     Equal_2 equal_2_object() const {
113         return CKvA_2::instance().equal_2_object();
114     }
115 
116     typedef typename CKvA_2::Parameter_space_in_y_2 Parameter_space_in_y_2;
parameter_space_in_y_2_object()117     Parameter_space_in_y_2 parameter_space_in_y_2_object() const {
118         return CKvA_2::instance().parameter_space_in_y_2_object();
119     }
120 
121     typedef typename CKvA_2::Compare_y_near_boundary_2
122        Compare_y_near_boundary_2;
compare_y_near_boundary_2_object()123     Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const {
124         return CKvA_2::instance().compare_y_near_boundary_2_object();
125     }
126 
127     typedef typename CKvA_2::Parameter_space_in_x_2 Parameter_space_in_x_2;
parameter_space_in_x_2_object()128     Parameter_space_in_x_2 parameter_space_in_x_2_object() const {
129         return CKvA_2::instance().parameter_space_in_x_2_object();
130     }
131 
132     typedef typename CKvA_2::Compare_x_at_limit_2 Compare_x_at_limit_2;
compare_x_at_limit_2_object()133     Compare_x_at_limit_2 compare_x_at_limit_2_object() const {
134         return CKvA_2::instance().compare_x_at_limit_2_object();
135     }
136 
137     typedef typename CKvA_2::Compare_x_near_limit_2  Compare_x_near_limit_2;
compare_x_near_limit_2_object()138     Compare_x_near_limit_2 compare_x_near_limit_2_object() const {
139         return CKvA_2::instance().compare_x_near_limit_2_object();
140     }
141 
142     typedef typename CKvA_2::Construct_min_vertex_2 Construct_min_vertex_2;
construct_min_vertex_2_object()143     Construct_min_vertex_2 construct_min_vertex_2_object() const {
144         return CKvA_2::instance().construct_min_vertex_2_object();
145     }
146 
147     typedef typename CKvA_2::Construct_max_vertex_2 Construct_max_vertex_2;
construct_max_vertex_2_object()148     Construct_max_vertex_2 construct_max_vertex_2_object() const {
149         return CKvA_2::instance().construct_max_vertex_2_object();
150     }
151 
152     typedef typename CKvA_2::Construct_opposite_2 Construct_opposite_2;
construct_opposite_2_object()153     Construct_opposite_2 construct_opposite_2_object() const {
154         return CKvA_2::instance().construct_opposite_2_object();
155     }
156 
157     typedef typename CKvA_2::Is_vertical_2 Is_vertical_2;
is_vertical_2_object()158     Is_vertical_2 is_vertical_2_object() const {
159         return CKvA_2::instance().is_vertical_2_object();
160     }
161 
162     typedef typename CKvA_2::Compare_y_at_x_2 Compare_y_at_x_2;
compare_y_at_x_2_object()163     Compare_y_at_x_2 compare_y_at_x_2_object() const {
164         return CKvA_2::instance().compare_y_at_x_2_object();
165     }
166 
167     typedef typename CKvA_2::Compare_y_at_x_left_2 Compare_y_at_x_left_2;
compare_y_at_x_left_2_object()168     Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const {
169         return CKvA_2::instance().compare_y_at_x_left_2_object();
170     }
171 
172     typedef typename CKvA_2::Compare_y_at_x_right_2 Compare_y_at_x_right_2;
compare_y_at_x_right_2_object()173     Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const {
174         return CKvA_2::instance().compare_y_at_x_right_2_object();
175     }
176 
177     typedef typename CKvA_2::Intersect_2 Intersect_2;
intersect_2_object()178     Intersect_2 intersect_2_object() const {
179         return CKvA_2::instance().intersect_2_object();
180     }
181 
182     typedef typename CKvA_2::Split_2 Split_2;
split_2_object()183     Split_2 split_2_object() const {
184         return CKvA_2::instance().split_2_object();
185     }
186 
187     typedef typename CKvA_2::Are_mergeable_2 Are_mergeable_2;
are_mergeable_2_object()188     Are_mergeable_2 are_mergeable_2_object() const {
189         return CKvA_2::instance().are_mergeable_2_object();
190     }
191 
192     typedef typename CKvA_2::Merge_2 Merge_2;
merge_2_object()193     Merge_2 merge_2_object() const {
194         return CKvA_2::instance().merge_2_object();
195     }
196 
197     typedef typename CKvA_2::Make_x_monotone_2 Make_x_monotone_2;
make_x_monotone_2_object()198     Make_x_monotone_2 make_x_monotone_2_object() const {
199         return Make_x_monotone_2(&CKvA_2::instance());
200     }
201 
202     typedef typename CKvA_2::Is_on_2 Is_on_2;
203 
is_on_2_object()204     Is_on_2 is_on_2_object() const {
205         return Is_on_2(&CKvA_2::instance());
206     }
207 
208     typedef typename CKvA_2::Construct_point_2 Construct_point_2;
209 
construct_point_2_object()210     Construct_point_2 construct_point_2_object() const {
211         return Construct_point_2(&CKvA_2::instance());
212     }
213 
214 
215     class Construct_x_monotone_segment_2 : public
216     CGAL::internal::Curved_kernel_via_analysis_2_Functors::
217     Curved_kernel_via_analysis_2_functor_base< CKvA_2 > {
218 
219     public:
220 
221         typedef CGAL::internal::Curved_kernel_via_analysis_2_Functors::
222         Curved_kernel_via_analysis_2_functor_base< CKvA_2 > Base;
223 
Construct_x_monotone_segment_2(CKvA_2 * kernel)224         Construct_x_monotone_segment_2(CKvA_2* kernel) : Base(kernel) {}
225 
226 
227     private:
228 
229         // helper function, returning the number of incident branches
230         // of a point wrt to a curve
231         std::pair<std::pair<int,int>, bool>
branch_numbers_and_vertical(Curve_2 cv,Point_2 p)232             branch_numbers_and_vertical(Curve_2 cv, Point_2 p) const {
233 
234             Equal_2 equal = this->_ckva()->equal_2_object();
235 
236             Algebraic_real_1 x = p.x();
237             int no;
238             bool is_event;
239             cv.x_to_index(x,no,is_event);
240             if(! is_event) {
241                 return std::make_pair(std::make_pair(1,1),false);
242             }
243             typename Curve_2::Status_line_1 status_line
244                 = cv.status_line_at_event(no);
245             bool vertical = status_line.covers_line();
246             for(int i = 0; i < status_line.number_of_events(); i++) {
247                 Point_2 curr_point(x,cv,i);
248                 if(equal(p,curr_point)) {
249                     return std::make_pair(
250                             status_line.number_of_incident_branches(i),
251                             vertical);
252                 }
253             }
254             return std::make_pair(std::make_pair(0,0),vertical);
255         }
256 
257         // abbrevation for convenience
is_one_one(Curve_2 cv,Point_2 p)258         bool is_one_one(Curve_2 cv, Point_2 p) const {
259 
260             std::pair<std::pair<int,int>,bool> branches
261                 = branch_numbers_and_vertical(cv,p);
262             return branches.first.first==1 && branches.first.second==1
263                 && !branches.second;
264 
265         }
266 
267       template <typename OutputIterator> OutputIterator
x_monotone_segment(Curve_2 cv,Point_2 p,boost::optional<Point_2> start,boost::optional<Point_2> end,OutputIterator out)268       x_monotone_segment(Curve_2 cv,
269                          Point_2 p,
270                          boost::optional<Point_2> start,
271                          boost::optional<Point_2> end,
272                          OutputIterator out) const
273       {
274         typedef boost::variant<Point_2, X_monotone_curve_2>
275                                                         Make_x_monotone_result;
276         //CGAL_assertion(is_one_one(cv,p));
277 
278         std::list<X_monotone_curve_2> segs;
279 
280         Is_on_2 on_arc = this->_ckva()->is_on_2_object();
281         auto left = this->_ckva()->construct_min_vertex_2_object();
282         auto right = this->_ckva()->construct_max_vertex_2_object();
283         Equal_2 equal = this->_ckva()->equal_2_object();
284 
285         std::vector<Make_x_monotone_result> arcs;
286         this->_ckva()->make_x_monotone_2_object()(cv, std::back_inserter(arcs));
287         auto it = arcs.begin();
288         auto helper = it;
289         const auto* it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
290         while (it != arcs.end()) {
291           if ( on_arc(p, *it_seg_p) ) break;
292           it++;
293           it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
294         }
295 
296         bool left_on_arc = start && on_arc(start.get(), *it_seg_p);
297         bool right_on_arc = end && on_arc(end.get(), *it_seg_p);
298 
299         if ( left_on_arc && right_on_arc ) {
300           segs.push_back(it_seg_p->trim(start.get(),end.get()));
301         }
302         if (left_on_arc && (!right_on_arc)) {
303           if (!it_seg_p->is_finite(CGAL::ARR_MAX_END) ||
304              !equal(start.get(),right(*it_seg_p))) {
305             if (it_seg_p->is_finite(CGAL::ARR_MIN_END) &&
306                 equal(start.get(),left(*it_seg_p)))
307             {
308               segs.push_back(*it_seg_p);
309             }
310             else {
311               X_monotone_curve_2 split1,split2;
312               it_seg_p->split(start.get(),split1,split2);
313               segs.push_back(split2);
314             }
315           }
316         }
317         if ((!left_on_arc) && right_on_arc) {
318           if (!it_seg_p->is_finite(CGAL::ARR_MIN_END) ||
319               ! equal(left(*it_seg_p), end.get()))
320           {
321             if (it_seg_p->is_finite(CGAL::ARR_MAX_END) &&
322                 equal(end.get(), right(*it_seg_p)))
323             {
324               segs.push_back(*it_seg_p);
325             }
326             else {
327               X_monotone_curve_2 split1,split2;
328               it_seg_p->split(end.get(), split1, split2);
329               segs.push_back(split1);
330             }
331           }
332         }
333         if ( (!left_on_arc) && (!right_on_arc)) {
334           segs.push_back(*it_seg_p);
335         }
336         helper = it; // for later usage
337 
338         if (! left_on_arc) {
339 
340           Point_2 point_it;
341           while (true) {
342             if (it_seg_p->is_finite(CGAL::ARR_MIN_END) &&
343                is_one_one(cv, left(*it_seg_p) ) ) {
344               point_it = left(*it_seg_p);
345             } else {
346               CGAL_assertion(! start);
347               break;
348             }
349             CGAL_assertion(it != arcs.begin());
350             it--;
351             it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
352             while (! on_arc(point_it, *it_seg_p)) {
353               CGAL_assertion(it != arcs.begin());
354               it--;
355               it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
356             }
357             if (start && on_arc(start.get(),*it_seg_p)) {
358               segs.push_front(it_seg_p->trim(start.get(), right(*it_seg_p)));
359               break;
360             }
361             else {
362               segs.push_front(*it_seg_p);
363             }
364           }
365         }
366         if (! right_on_arc) {
367           it = helper; // reset
368           it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
369           Point_2 point_it;
370           while (true) {
371             if (it_seg_p->is_finite(CGAL::ARR_MAX_END) &&
372                 is_one_one(cv,right(*it_seg_p) ) )
373             {
374               point_it=right(*it_seg_p);
375             } else {
376               CGAL_assertion(! end);
377               break;
378             }
379             it++;
380             CGAL_assertion(it != arcs.end());
381             it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
382             while(! on_arc(point_it, *it_seg_p)) {
383               it++;
384               CGAL_assertion(it != arcs.end());
385               it_seg_p = boost::get<X_monotone_curve_2>(&(*it));
386             }
387             if(end && on_arc(end.get(),*it_seg_p)) {
388               segs.push_back(it_seg_p->trim(left(*it_seg_p),end.get()));
389               break;
390             }
391             else {
392               segs.push_back(*it_seg_p);
393             }
394           }
395         }
396 
397         std::copy(segs.begin(), segs.end(), out);
398         return out;
399 
400       }
401 
402     public:
403 
404         template<typename OutputIterator> OutputIterator
operator()405             operator() (Curve_2 cv,
406                         Point_2 p,
407                         Site_of_point site_of_p,
408                         OutputIterator out) const {
409             if(site_of_p==POINT_IN_INTERIOR) {
410                 return x_monotone_segment(cv,p,boost::none, boost::none,out);
411             } else if(site_of_p==MIN_ENDPOINT) {
412                 return x_monotone_segment(cv,
413                                        p,
414                                        boost::optional<Point_2>(p),
415                                        boost::none,
416                                        out);
417             }
418             CGAL_assertion(site_of_p==MAX_ENDPOINT);
419             return x_monotone_segment(cv,
420                                    p,
421                                    boost::none,
422                                    boost::optional<Point_2>(p),
423                                    out);
424         }
425 
426 
427         template<typename OutputIterator> OutputIterator
operator()428             operator() (Curve_2 cv,
429                         Point_2 end_left,
430                         Point_2 end_right,
431                         OutputIterator out) const {
432 
433 
434 
435             CGAL_assertion((branch_numbers_and_vertical(cv,end_left).
436                             first.second==1 &&
437                             !branch_numbers_and_vertical(cv,end_left).second)||
438                            (branch_numbers_and_vertical(cv,end_right).
439                             first.first==1 &&
440                             !branch_numbers_and_vertical(cv,end_right).second)
441                            ||
442                            (branch_numbers_and_vertical(cv,end_left).
443                             first.second==0 &&
444                             branch_numbers_and_vertical(cv,end_left).second) ||
445                            (branch_numbers_and_vertical(cv,end_right).
446                             first.first==0 &&
447                             branch_numbers_and_vertical(cv,end_right).second));
448             CGAL_assertion_code(
449                     if((branch_numbers_and_vertical(cv,end_left).
450                         first.second==0 &&
451                         branch_numbers_and_vertical(cv,end_left).second) ||
452                        (branch_numbers_and_vertical(cv,end_right).
453                         first.first==0 &&
454                         branch_numbers_and_vertical(cv,end_right).second)) {
455                         Compare_x_2 equal_x
456                             = this->_ckva()->compare_x_2_object(); )
457                     CGAL_assertion(equal_x(end_left,end_right)==CGAL::EQUAL);
458             CGAL_assertion_code(});
459 
460 
461             if( (branch_numbers_and_vertical(cv,end_left).
462                  first.second==0 &&
463                  branch_numbers_and_vertical(cv,end_left).second) ||
464                 (branch_numbers_and_vertical(cv,end_left).
465                  first.second==1 &&
466                  !branch_numbers_and_vertical(cv,end_left).second)) {
467 
468                 return x_monotone_segment
469                     (cv,
470                      end_left,
471                      boost::optional<Point_2>(end_left),
472                      boost::optional<Point_2>(end_right),
473                      out);
474             } else {
475                 return x_monotone_segment
476                     (cv,
477                      end_right,
478                      boost::optional<Point_2>(end_left),
479                      boost::optional<Point_2>(end_right),
480                      out);
481             }
482         }
483 
484         template<typename OutputIterator> OutputIterator
485           operator() (Point_2 p, Point_2 q, OutputIterator out) {
486           bool same_x=(this->_ckva()->compare_x_2_object()(p,q)==CGAL::EQUAL);
487           if(same_x) {
488             Algebraic_real_1 x = p.x();
489             Polynomial_2 f = Polynomial_2(x.polynomial());
490             Curve_2 cv
491               = this->_ckva()->kernel().construct_curve_2_object() (f);
492             *out++=typename CKvA_2::Arc_2(p,q,cv);
493             return out;
494           }
495           Algebraic_real_1 px
496             =this->_ckva()->kernel().compute_x_2_object()(p.xy()),
497             py=this->_ckva()->kernel().compute_y_2_object()(p.xy()),
498             qx=this->_ckva()->kernel().compute_x_2_object()(q.xy()),
499             qy=this->_ckva()->kernel().compute_y_2_object()(q.xy());
500           bool p_rat=px.is_rational() && py.is_rational();
501           bool q_rat=qx.is_rational() && qy.is_rational();
502           if(p_rat && q_rat) {
503             typedef typename Algebraic_real_1::Rational Rational;
504             Rational pxr=px.rational(), pyr=py.rational(),
505               qxr=qx.rational(), qyr=qy.rational();
506             typedef CGAL::Fraction_traits<Rational> FT;
507             typename FT::Decompose decompose;
508             typedef typename FT::Numerator_type Numerator;
509             typedef typename FT::Denominator_type Denominator;
510             Rational term_at_y=qxr-pxr, term_at_x=-qyr+pyr,
511               term_at_1=pxr*qyr-pyr*qxr;
512             Denominator denom_curr;
513             Numerator term_at_y_int, term_at_x_int, term_at_1_int;
514             decompose(term_at_y, term_at_y_int, denom_curr);
515             term_at_x=term_at_x*denom_curr;
516             term_at_1=term_at_1*denom_curr;
517             decompose(term_at_x,term_at_x_int,denom_curr);
518             term_at_y_int=term_at_y_int*denom_curr;
519             term_at_1=term_at_1*denom_curr;
520             decompose(term_at_1,term_at_1_int,denom_curr);
521             term_at_y_int=term_at_y_int*denom_curr;
522             term_at_x_int=term_at_x_int*denom_curr;
523             typedef typename CGAL::Polynomial_traits_d<Polynomial_2>
524               ::Coefficient_type Polynomial_1;
525             Polynomial_2 pol(Polynomial_1(term_at_1_int,term_at_x_int),
526                              Polynomial_1(term_at_y_int));
527             Curve_2 curve=this->_ckva()->kernel().construct_curve_2_object()
528               (pol);
529 
530             CGAL_assertion(this->_ckva()->is_on_2_object()(p,curve));
531             CGAL_assertion(this->_ckva()->is_on_2_object()(q,curve));
532             return this->operator()(curve,p,q,out);
533           }
534           CGAL_precondition(same_x || (p_rat && q_rat));
535           return out;
536         }
537     };
538 
539     Construct_x_monotone_segment_2 construct_x_monotone_segment_2_object()
540         const {
541         return Construct_x_monotone_segment_2(&CKvA_2::instance());
542     }
543 
544 /*
545 
546     class Construct_vertical_segment_2 : public
547     CGAL::internal::Curved_kernel_via_analysis_2_Functors::
548     Curved_kernel_via_analysis_2_functor_base< CKvA_2 > {
549 
550     public:
551 
552         typedef CGAL::internal::Curved_kernel_via_analysis_2_Functors::
553         Curved_kernel_via_analysis_2_functor_base< CKvA_2 > Base;
554 
555         Construct_vertical_segment_2(CKvA_2* kernel) : Base(kernel) {}
556 
557 
558     public:
559 
560         X_monotone_curve_2 operator() (Point_2 p, Point_2 q) {
561             Algebraic_real_1 x = p.x();
562             Polynomial_2 f = Polynomial_2(x.polynomial());
563             Curve_2 cv
564                 = this->_ckva()->kernel().construct_curve_2_object() (f);
565             return typename CKvA_2::Arc_2(p,q,cv);
566         }
567 
568 
569         template<typename OutputIterator> OutputIterator
570             operator() (Point_2 p,
571                         Site_of_point site_of_p) const {
572             Algebraic_real_1 x = p.x();
573             Polynomial_2 f = Polynomial_2(x.polynomial());
574             Curve_2 cv = this->_ckva().kernel().construct_curve_2_object() (f);
575 
576             if(site_of_p==POINT_IN_INTERIOR) {
577                 return typename CKvA_2::Arc_2(x,cv);
578             } else if(site_of_p==MIN_ENDPOINT) {
579                 return typename CKvA_2::Arc_2(p,ARR_MIN_END,cv);
580             }
581             CGAL_assertion(site_of_p==MAX_ENDPOINT);
582             return typename CKvA_2::Arc_2(p,ARR_MAX_END,cv);
583 
584         }
585     };
586 
587     Construct_vertical_segment_2 construct_vertical_segment_2_object() const {
588         return Construct_vertical_segment_2(&CKvA_2::instance());
589     }
590 
591 */
592 
593     class Construct_curve_2 : public
594     CGAL::internal::Curved_kernel_via_analysis_2_Functors::
595     Curved_kernel_via_analysis_2_functor_base< CKvA_2 > {
596 
597     public:
598 
599         typedef CGAL::internal::Curved_kernel_via_analysis_2_Functors::
600         Curved_kernel_via_analysis_2_functor_base< CKvA_2 > Base;
601 
602         Construct_curve_2(CKvA_2* kernel) : Base(kernel) {}
603 
604         Curve_2 operator() (Polynomial_2 p) const {
605             return this->_ckva()->kernel().construct_curve_2_object() (p);
606         }
607     };
608 
609     Construct_curve_2 construct_curve_2_object() const {
610         return Construct_curve_2(&CKvA_2::instance());
611     }
612 
613 
614 
615 
616 
617 /*
618 
619   // additional functionality (for not introducing a "general" arc)
620 
621   class Connect_points_2 {
622 
623 
624     template< class OutputIterator >
625     OutputIterator operator() (Curve_2, Point_2, Point_2, ...,
626                                OutputIterator) {
627 
628 
629       while (false || true) {
630         *oi++ = X_monotone_curve_2(...);
631       }
632 
633       return oi;
634     }
635 
636     template< class OutputIterator >
637     OutputIterator operator() (Curve_2, Point_2, Point_2, int, ...,
638                                OutputIterator) {
639 
640 
641       while (false || true) {
642         *oi++ = X_monotone_curve_2(...);
643       }
644 
645       return oi;
646     }
647 
648   };
649 
650 */
651 
652 };
653 
654 } //namespace CGAL
655 
656 #include <CGAL/enable_warnings.h>
657 
658 #endif // CGAL_ARR_ALGEBRAIC_SEGMENT_TRAITS
659