BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Circular_kernel_3/internal_functions_on_circular_arc_3.h
Go to the documentation of this file.
00001 // Copyright (c) 2008  INRIA Sophia-Antipolis (France).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Circular_kernel_3/include/CGAL/Circular_kernel_3/internal_functions_on_circular_arc_3.h $
00015 // $Id: internal_functions_on_circular_arc_3.h 50731 2009-07-21 09:08:07Z sloriot $
00016 //
00017 // Author(s) : Monique Teillaud, Sylvain Pion, Pedro Machado, 
00018 //             Sebastien Loriot, Julien Hazebrouck, Damien Leroy
00019 
00020 // Partially supported by the IST Programme of the EU as a 
00021 // STREP (FET Open) Project under Contract No  IST-006413 
00022 // (ACS -- Algorithms for Complex Shapes)
00023 
00024 #ifndef CGAL_SPHERICAL_KERNEL_PREDICATES_ON_CIRCULAR_ARC_3_H
00025 #define CGAL_SPHERICAL_KERNEL_PREDICATES_ON_CIRCULAR_ARC_3_H
00026 
00027 #include <CGAL/Circular_kernel_3/internal_function_has_on_spherical_kernel.h>
00028 #include <CGAL/Circular_kernel_3/internal_functions_on_circle_3.h>
00029 
00030 namespace CGAL {
00031   namespace SphericalFunctors {
00032 
00033     template< class SK>
00034     bool
00035     equal( const typename SK::Circular_arc_3 &c1,
00036            const typename SK::Circular_arc_3 &c2)
00037     {
00038       return c1.rep() == c2.rep();
00039     }
00040 
00041     template <class SK>
00042     inline
00043     bool
00044     do_overlap(const typename SK::Circular_arc_3 &c1,
00045                const typename SK::Circular_arc_3 &c2,
00046                const bool known_equal_supporting_circle = false)
00047     { 
00048       if(!known_equal_supporting_circle) {
00049         if(!non_oriented_equal<SK>(c1.supporting_circle(), 
00050                                    c2.supporting_circle()))
00051           return false;
00052       }
00053       if(c1.rep().is_full()) return true;
00054       if(c2.rep().is_full()) return true;
00055       if((SK().has_on_3_object()(c1,c2.target(),true)) || 
00056          (SK().has_on_3_object()(c1,c2.source(),true))) return true;
00057       return SK().has_on_3_object()(c2,c1.source(),true);
00058     }
00059 
00060     template < class SK >
00061     void
00062     split(const typename SK::Circular_arc_3 &c,
00063           const typename SK::Circular_arc_point_3 &p,
00064           typename SK::Circular_arc_3 &c1,
00065           typename SK::Circular_arc_3 &c2)
00066     {
00067       // The point must be on the circular arc 
00068       CGAL_kernel_precondition(SK().has_on_3_object()(c, p));
00069       typedef typename SK::Circular_arc_3  Circular_arc_3;
00070       // It doesn't make sense to split an arc on an extremity
00071       CGAL_kernel_precondition(c.source() != p);
00072       CGAL_kernel_precondition(c.target() != p);
00073       const Circular_arc_3 &rc1 = 
00074         Circular_arc_3(c.supporting_circle(), c.source(), p);
00075       const Circular_arc_3 &rc2 = 
00076         Circular_arc_3(c.supporting_circle(), p, c.target());
00077       if ( SK().compare_xyz_3_object()(rc1.source(), rc2.source()) != 
00078            SMALLER) {
00079         c1 = rc2; c2 = rc1;
00080       } else { c1 = rc1; c2 = rc2; }
00081     }
00082 
00083     template < class SK, class OutputIterator >
00084     OutputIterator
00085     intersect_3(const typename SK::Line_3 & l, 
00086                 const typename SK::Circular_arc_3 & ca, 
00087                 OutputIterator res)
00088     { 
00089       typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;
00090       typedef std::vector<CGAL::Object> solutions_container;
00091       typedef std::pair<Circular_arc_point_3, unsigned> Solution;
00092 
00093       solutions_container solutions;
00094 
00095       SK().intersect_3_object()(l, ca.supporting_circle(),
00096                                 std::back_inserter(solutions) );
00097       if(solutions.size() == 0) return res;
00098       if(solutions.size() == 1) {
00099          const Solution& sol=*object_cast<Solution>(&solutions[0]);
00100          if(SK().has_on_3_object()(ca,sol.first,true))
00101            *res++ = solutions[0];
00102       } else {
00103          const Solution& sol1=*object_cast<Solution>(&solutions[0]);
00104          const Solution& sol2=*object_cast<Solution>(&solutions[1]);        
00105          if(SK().has_on_3_object()(ca,sol1.first,true))
00106            *res++ = solutions[0];
00107          if(SK().has_on_3_object()(ca,sol2.first,true))
00108            *res++ = solutions[1];
00109       }
00110       return res;
00111     }
00112 
00113     template < class SK, class OutputIterator >
00114     OutputIterator
00115     intersect_3(const typename SK::Circle_3 & c, 
00116                 const typename SK::Circular_arc_3 & ca, 
00117                 OutputIterator res)
00118     { 
00119       typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;
00120       typedef std::vector<CGAL::Object> solutions_container;
00121       typedef std::pair<Circular_arc_point_3, unsigned> Solution;
00122 
00123       if(non_oriented_equal<SK>(c, ca.supporting_circle())) {
00124         *res++ = make_object(ca);
00125       }
00126 
00127       solutions_container solutions;
00128 
00129       SK().intersect_3_object()(ca.supporting_circle(), c, 
00130                                 std::back_inserter(solutions) );
00131       if(solutions.size() == 0) return res;
00132       if(solutions.size() == 1) {
00133          const Solution& sol=*object_cast<Solution>(&solutions[0]);
00134          if(SK().has_on_3_object()(ca,sol.first,true))
00135            *res++ = solutions[0];
00136       } else {
00137          const Solution& sol1=*object_cast<Solution>(&solutions[0]);
00138          const Solution& sol2=*object_cast<Solution>(&solutions[1]);        
00139          if(SK().has_on_3_object()(ca,sol1.first,true))
00140            *res++ = solutions[0];
00141          if(SK().has_on_3_object()(ca,sol2.first,true))
00142            *res++ = solutions[1];
00143       }
00144       return res;
00145     }
00146 
00147     template < class SK, class OutputIterator >
00148     OutputIterator
00149     intersect_3(const typename SK::Sphere_3 & s,
00150                 const typename SK::Circular_arc_3 & c,
00151                OutputIterator res)
00152     {
00153       typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;
00154       typedef std::vector<CGAL::Object> solutions_container;
00155       typedef std::pair<Circular_arc_point_3, unsigned> Solution;
00156 
00157       if(SK().has_on_3_object()(s, c.supporting_circle())) {
00158         *res++ = make_object(c);
00159       }
00160 
00161       solutions_container solutions;
00162 
00163       SK().intersect_3_object()(c.supporting_circle(), s,
00164                                 std::back_inserter(solutions) );
00165       if(solutions.size() == 0) return res;
00166       if(solutions.size() == 1) {
00167          const Solution& sol=*object_cast<Solution>(&solutions[0]);
00168          if(SK().has_on_3_object()(c,sol.first,true))
00169            *res++ = solutions[0];
00170       } else {
00171          const Solution& sol1=*object_cast<Solution>(&solutions[0]);        
00172          const Solution& sol2=*object_cast<Solution>(&solutions[1]);        
00173          if(SK().has_on_3_object()(c,sol1.first,true))
00174            *res++ = solutions[0];
00175          if(SK().has_on_3_object()(c,sol2.first,true))
00176            *res++ = solutions[1];
00177       }
00178       return res;
00179     }
00180 
00181     template < class SK, class OutputIterator >
00182     OutputIterator
00183     intersect_3(const typename SK::Plane_3 & p, 
00184                 const typename SK::Circular_arc_3 & ca, 
00185                 OutputIterator res)
00186     {
00187       typedef typename SK::Point_3 Point_3;
00188       typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;
00189       typedef std::vector<CGAL::Object> solutions_container;
00190       typedef std::pair<Circular_arc_point_3, unsigned> Solution;
00191       if(SK().has_on_3_object()(p,ca.supporting_circle())) {
00192         *res++ = make_object(ca);
00193       }
00194       solutions_container solutions;
00195 
00196       SK().intersect_3_object()(ca.supporting_circle(), p,
00197                                 std::back_inserter(solutions) );
00198       if(solutions.size() == 0) return res;
00199       if(solutions.size() == 1) {
00200          const Solution& sol=*object_cast<Solution>(&solutions[0]);
00201          if(SK().has_on_3_object()(ca,sol.first,true))
00202            *res++ = solutions[0];
00203       } else {
00204          const Solution& sol1=*object_cast<Solution>(&solutions[0]);
00205          const Solution& sol2=*object_cast<Solution>(&solutions[1]);        
00206          if(SK().has_on_3_object()(ca,sol1.first,true))
00207            *res++ = solutions[0];
00208          if(SK().has_on_3_object()(ca,sol2.first,true))
00209            *res++ = solutions[1];
00210       }
00211       return res;
00212     }
00213 
00214     template < class SK, class OutputIterator >
00215     OutputIterator
00216     intersect_3(const typename SK::Line_arc_3 & la, 
00217                 const typename SK::Circular_arc_3 & ca, 
00218                 OutputIterator res)
00219     { 
00220       typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;
00221       typedef std::vector<CGAL::Object> solutions_container;
00222       typedef std::pair<Circular_arc_point_3, unsigned> Solution;
00223 
00224       solutions_container solutions;
00225 
00226       SK().intersect_3_object()(la.supporting_line(), ca.supporting_circle(),
00227                                 std::back_inserter(solutions) );
00228       if(solutions.size() == 0) return res;
00229       if(solutions.size() == 1) {
00230          const Solution& sol=*object_cast<Solution>(&solutions[0]);
00231          if(SK().has_on_3_object()(ca,sol.first,true) &&
00232             SK().has_on_3_object()(la,sol.first,true))
00233            *res++ = solutions[0];
00234       } else {
00235          const Solution& sol1=*object_cast<Solution>(&solutions[0]);
00236          const Solution& sol2=*object_cast<Solution>(&solutions[1]);        
00237          if(SK().has_on_3_object()(ca,sol1.first,true) &&
00238             SK().has_on_3_object()(la,sol1.first,true))
00239            *res++ = solutions[0];
00240          if(SK().has_on_3_object()(ca,sol2.first,true) &&
00241             SK().has_on_3_object()(la,sol2.first,true))
00242            *res++ = solutions[1];
00243       }
00244       return res;
00245     }
00246 
00247     template < class SK, class OutputIterator >
00248     OutputIterator
00249     intersect_3(const typename SK::Circular_arc_3 & a1, 
00250                 const typename SK::Circular_arc_3 & a2, 
00251                 OutputIterator res)
00252     { 
00253       typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;
00254       typedef typename SK::Circular_arc_3 Circular_arc_3;
00255       typedef std::vector<CGAL::Object> solutions_container;
00256       typedef std::pair<Circular_arc_point_3, unsigned> Solution;
00257 
00258       if(non_oriented_equal<SK>(a1.supporting_circle(), a2.supporting_circle())) {
00259         if(a1.rep().is_full()) {
00260           *res++ = make_object(a2); 
00261           //return res;
00262         }
00263         else if(a2.rep().is_full()) {
00264           *res++ = make_object(a1); 
00265           //return res;
00266         } else {
00267           bool t2_in_a1 = SK().has_on_3_object()(a1,a2.target(),true);
00268           bool s2_in_a1 = SK().has_on_3_object()(a1,a2.source(),true);
00269           if(t2_in_a1 && s2_in_a1) {
00270             bool t1_in_a2 = SK().has_on_3_object()(a2,a1.target(),true);
00271             bool s1_in_a2 = SK().has_on_3_object()(a2,a1.source(),true);
00272             if(t1_in_a2 && s1_in_a2) {
00273               const Comparison_result comp = 
00274                 SK().compare_xyz_3_object()(a1.source(), a2.source());
00275               if(comp < 0) {
00276                 if(a1.source() == a2.target()) {
00277                   *res++ = make_object(std::make_pair(a1.source(),1u));
00278                 } else {
00279                   const Circular_arc_3 & arc =
00280                   Circular_arc_3(a1.supporting_circle(),a1.source(),a2.target());
00281                   *res++ = make_object(arc);
00282                 }
00283                 if(a2.source() == a1.target()) {
00284                   *res++ = make_object(std::make_pair(a2.source(),1u));
00285                 } else {
00286                   const Circular_arc_3 & arc =
00287                   Circular_arc_3(a1.supporting_circle(),a2.source(),a1.target());
00288                   *res++ = make_object(arc);
00289                 }
00290               } else if(comp > 0) {
00291                 if(a2.source() == a1.target()) {
00292                   *res++ = make_object(std::make_pair(a2.source(),1u));
00293                 } else {
00294                   const Circular_arc_3 & arc =
00295                   Circular_arc_3(a1.supporting_circle(),a2.source(),a1.target());
00296                   *res++ = make_object(arc);
00297                 }
00298                 if(a1.source() == a2.target()) {
00299                   *res++ = make_object(std::make_pair(a1.source(),1u));
00300                 } else {
00301                   const Circular_arc_3 & arc =
00302                   Circular_arc_3(a1.supporting_circle(),a1.source(),a2.target());
00303                   *res++ = make_object(arc);
00304                 } 
00305               } else { 
00306                 *res++ = make_object(a1);
00307               }
00308             } else {
00309               *res++ = make_object(a2);
00310             }
00311           } else if(t2_in_a1) {
00312             if(a1.source() == a2.target()) 
00313               *res++ = make_object(std::make_pair(a1.source(),1u));
00314             else {
00315               const Circular_arc_3 & arc =
00316                 Circular_arc_3(a1.supporting_circle(),a1.source(),a2.target());
00317               *res++ = make_object(arc);
00318             } //return res;
00319           } else if(s2_in_a1) {
00320             if(a2.source() == a1.target()) {
00321               *res++ = make_object(std::make_pair(a2.source(),1u));
00322             } else {
00323               const Circular_arc_3 & arc =
00324                 Circular_arc_3(a1.supporting_circle(),a2.source(),a1.target());
00325               *res++ = make_object(arc);
00326             }
00327           } else if(SK().has_on_3_object()(a2,a1.source(),true)) {
00328               *res++ = make_object(a1);
00329           } 
00330         }
00331       } else {
00332         solutions_container solutions;
00333 
00334         SK().intersect_3_object()(a1.supporting_circle(), a2.supporting_circle(), 
00335                                   std::back_inserter(solutions) );
00336         if(solutions.size() == 0) return res;
00337         if(solutions.size() == 1) {
00338           const Solution& sol=*object_cast<Solution>(&solutions[0]);
00339           if(SK().has_on_3_object()(a1,sol.first,true) &&
00340              SK().has_on_3_object()(a2,sol.first,true))
00341             *res++ = solutions[0];
00342         } else {
00343           const Solution& sol1=*object_cast<Solution>(&solutions[0]);
00344           const Solution& sol2=*object_cast<Solution>(&solutions[1]);          
00345           if(SK().has_on_3_object()(a1,sol1.first,true) &&
00346              SK().has_on_3_object()(a2,sol1.first,true))
00347             *res++ = solutions[0];
00348           if(SK().has_on_3_object()(a1,sol2.first,true) &&
00349              SK().has_on_3_object()(a2,sol2.first,true))
00350             *res++ = solutions[1];
00351         }
00352       }
00353       return res;
00354     }
00355 
00356     template < class SK>
00357     bool
00358     is_theta_monotone_3(const typename SK::Circular_arc_3 & arc,const typename SK::Sphere_3& sphere)
00359     {
00360       CGAL_kernel_precondition(SK().has_on_3_object()(sphere,arc));
00361       CGAL::Circle_type type=classify_circle_3<SK>(arc.supporting_circle(),sphere);
00362       CGAL_kernel_precondition(type!=CGAL::BIPOLAR);
00363       if (type==THREADED)
00364         return true;
00365       if (type==POLAR){
00366         bool circle_contains_north = arc.supporting_circle().center().z() > sphere.center().z();
00367         typename SK::Root_of_2 radius=make_root_of_2(typename SK::FT(0),typename SK::FT(1),sphere.squared_radius());
00368         typename SK::Circular_arc_point_3 pole (
00369           typename SK::Algebraic_kernel::Root_for_spheres_2_3( sphere.center().x(),
00370                                                               sphere.center().y(),
00371                                                               sphere.center().z()+(circle_contains_north?1:-1)*radius
00372           )
00373         );
00374         
00375         if (arc.source().z()==pole.z() || arc.target().z()==pole.z())
00376           return true;
00377         
00378         return !has_on<SK>(arc,pole);
00379       }
00380       
00381       
00382       typename SK::FT z_coord=extremal_points_z_coordinate<SK>(arc.supporting_circle(),sphere);
00383       typename SK::Plane_3 plane(0,0,1,-z_coord);
00384       std::vector<CGAL::Object> inters;
00385       
00386       intersect_3<SK>(plane,arc,std::back_inserter(inters));
00387       
00388       if (inters.empty())
00389         return true;
00390       
00391       //checks whether circular arc endpoints are theta extremal
00392       unsigned nb_extrem = (arc.source().z()-z_coord == 0)? 1:0;
00393       if (arc.target().z()-z_coord == 0) ++nb_extrem;
00394       
00395       if (inters.size()==nb_extrem)
00396         return true;
00397       
00398       return false;
00399     }
00400     
00401     template < class SK,class Output_iterator>
00402     Output_iterator 
00403     make_circular_arc_theta_monotone( const typename SK::Circular_arc_3& arc,
00404                                       const typename SK::Sphere_3& sphere,
00405                                       Output_iterator out_it)
00406     {
00407       CGAL::Circle_type type=classify_circle_3<SK>(arc.supporting_circle(),sphere);
00408       CGAL_kernel_precondition(type!=BIPOLAR);
00409       switch (type){
00410         case THREADED:
00411         case POLAR:{
00412           bool circle_contains_north = arc.supporting_circle().center().z() > sphere.center().z();
00413           typename SK::Root_of_2 radius=make_root_of_2(typename SK::FT(0),typename SK::FT(1),sphere.squared_radius());
00414           typename SK::Circular_arc_point_3 pole (
00415             typename SK::Algebraic_kernel::Root_for_spheres_2_3( sphere.center().x(),
00416                                                                 sphere.center().y(),
00417                                                                 sphere.center().z()+(circle_contains_north?1:-1)*radius
00418             )
00419           );
00420           
00421           if (arc.source().z()==pole.z() || arc.target().z()==pole.z())
00422             *out_it++=arc;
00423           else{
00424             if ( has_on<SK>(arc,pole) ){
00425               *out_it++=typename SK::Circular_arc_3(arc.supporting_circle(),arc.source(),pole);
00426               *out_it++=typename SK::Circular_arc_3(arc.supporting_circle(),pole,arc.target());
00427             }
00428             else
00429               *out_it++=arc;
00430           }
00431         }
00432         break;
00433         case NORMAL:{
00434           typename SK::FT z_coord=extremal_points_z_coordinate<SK>(arc.supporting_circle(),sphere);
00435           typename SK::Plane_3 plane(0,0,1,-z_coord);
00436           std::vector<CGAL::Object> inters;
00437           
00438           intersect_3<SK>(plane,arc,std::back_inserter(inters));
00439           
00440           //No intersection with horizontal plane: theta-monotone
00441           if (inters.empty()){
00442             *out_it++=arc;
00443             break;
00444           }
00445           
00446           //check if endpoints of circular arc are theta extremal points
00447           unsigned nb_extrem = (arc.source().z()-z_coord == 0)? 1:0;
00448           if (arc.target().z()-z_coord == 0) ++nb_extrem;
00449           
00450           if (inters.size()==nb_extrem){
00451             *out_it++=arc;
00452             break;
00453           }
00454 
00455           //one endpoint is extremal: just split the arc
00456           if (nb_extrem==1){
00457             const std::pair<typename SK::Circular_arc_point_3,unsigned>* pt[2]={NULL,NULL};
00458             pt[0]=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[0]);
00459             pt[1]=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[1]);
00460             CGAL_kernel_precondition(pt[0]!=NULL);
00461             CGAL_kernel_precondition(pt[1]!=NULL);
00462             const typename SK::Circular_arc_point_3& midpt=(arc.source()==pt[0]->first || arc.target()==pt[0]->first)?pt[1]->first:pt[0]->first;
00463             *out_it++=typename SK::Circular_arc_3(arc.supporting_circle(),arc.source(),midpt);
00464             *out_it++=typename SK::Circular_arc_3(arc.supporting_circle(),midpt,arc.target());
00465             break;
00466           }
00467           
00468           CGAL_kernel_precondition(nb_extrem==0);
00469           
00470           //only one intersection points
00471           if (inters.size()==1){
00472             const std::pair<typename SK::Circular_arc_point_3,unsigned>* midpt=NULL;
00473             midpt=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[0]);
00474             CGAL_kernel_precondition(midpt!=NULL);
00475             *out_it++=typename SK::Circular_arc_3(arc.supporting_circle(),arc.source(),midpt->first);
00476             *out_it++=typename SK::Circular_arc_3(arc.supporting_circle(),midpt->first,arc.target());
00477             break;
00478           }
00479           
00480           //three arcs are defined by two intersection points
00481           const std::pair<typename SK::Circular_arc_point_3,unsigned>* pt[2]={NULL,NULL};
00482           pt[0]=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[0]);
00483           pt[1]=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[1]);
00484           CGAL_kernel_precondition(pt[0]!=NULL);
00485           CGAL_kernel_precondition(pt[1]!=NULL);
00486           
00487           typename SK::Circular_arc_3 arc1=typename SK::Circular_arc_3(arc.supporting_circle(),arc.source(),pt[0]->first);
00488           typename SK::Circular_arc_3 arc2=typename SK::Circular_arc_3(arc.supporting_circle(),pt[0]->first,arc.target());
00489           if ( has_on<SK>(arc1,pt[1]->first) ){
00490             *out_it++=typename SK::Circular_arc_3(arc1.supporting_circle(),arc1.source(),pt[1]->first);
00491             *out_it++=typename SK::Circular_arc_3(arc1.supporting_circle(),pt[1]->first,arc1.target());            
00492             *out_it++=arc2;
00493           }
00494           else{
00495             *out_it++=arc1;            
00496             *out_it++=typename SK::Circular_arc_3(arc2.supporting_circle(),arc2.source(),pt[1]->first);
00497             *out_it++=typename SK::Circular_arc_3(arc2.supporting_circle(),pt[1]->first,arc2.target());            
00498           }
00499           break;
00500         }
00501         case BIPOLAR:
00502           CGAL_kernel_precondition(!"This function does not accept bipolar circle as input.");
00503       }
00504       
00505       return out_it;
00506     }
00507     
00508     //this function indicates whether a theta monotone circular arc is 
00509     //included in the upper part of its supporting circle (wrt theta extremal pts)
00510     template <class SK>
00511     bool 
00512     is_upper_arc(const typename SK::Circular_arc_3& arc,
00513                  const typename SK::Sphere_3& sphere)
00514     {
00515       CGAL_kernel_precondition(is_theta_monotone_3<SK>(arc,sphere));
00516       CGAL::Circle_type type=classify_circle_3<SK>(arc.supporting_circle(),sphere);
00517       CGAL_kernel_precondition(type!=THREADED && type !=BIPOLAR);
00518       
00519       //case of POLAR circle
00520       if (type==POLAR)
00521         return ( ( arc.supporting_circle().center().z()-sphere.center().z() ) < 0 );
00522       
00523       //case of NORMAL circle
00524       typename SK::FT z_coord=extremal_points_z_coordinate<SK>(arc.supporting_circle(),sphere);
00525       if ( z_coord < arc.source().z() ) return true;
00526       if ( z_coord > arc.source().z() ) return false;
00527       if ( z_coord < arc.target().z() ) return true;
00528       if ( z_coord > arc.target().z() ) return false;
00529       
00530       //source and target are theta extremal points
00531       
00532       typename SK::Point_3 out_sphere_normal=CGAL::ORIGIN + ( arc.supporting_circle().center()-sphere.center() );
00533       typename SK::Point_3 ori(0,0,0);
00534       int wise=(out_sphere_normal > ori)? 1:-1; //check if seen ccw from the side going from the sphere center to the circle center
00535       
00536       typename SK::Vector_3 cir_center(arc.supporting_circle().center().x()-sphere.center().x(),arc.supporting_circle().center().y()-sphere.center().y(),0);
00537       CGAL::Comparison_result source_vs_center=compare_theta_pt_vector<SK>(arc.source(),cir_center,sphere);
00538       CGAL::Comparison_result target_vs_center=compare_theta_pt_vector<SK>(arc.target(),cir_center,sphere);
00539       
00540       
00541       if (source_vs_center==target_vs_center){//circle is cut by meridian at theta=0
00542         CGAL::Comparison_result source_vs_target=compare_theta_of_pts<SK>(arc.source(),arc.target(),sphere);  
00543         wise*=(source_vs_target==SMALLER)?-1:1;
00544       }
00545       else
00546         wise*=(source_vs_center==SMALLER)?1:-1;
00547       
00548       return wise==1?false:true;
00549     }
00550 
00551     //compute the intersection points of a theta monotone arc with a meridian.
00552     //precondition: the intersection point always exists.
00553     template <class SK>
00554     typename SK::Circular_arc_point_3 
00555     intersect_3( const typename SK::Circular_arc_3& arc,
00556                  const typename SK::Vector_3&m,
00557                  const typename SK::Sphere_3& sphere)
00558     {
00559       typename SK::Plane_3 plane(sphere.center(),sphere.center()+m,sphere.center()+typename SK::Vector_3(0,0,1));
00560       std::vector<CGAL::Object> inters;
00561       intersect_3<SK>(plane,arc,std::back_inserter(inters));
00562       CGAL_kernel_precondition(!inters.empty());
00563       if (inters.size()==1){
00564           const typename SK::Circular_arc_point_3& pt=
00565             object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[0])->first;
00566           return pt;
00567       }
00568       
00569       CGAL_kernel_precondition(classify_circle_3<SK>(arc.supporting_circle(),sphere)!=NORMAL);
00570       
00571       const typename SK::Circular_arc_point_3& pts1=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[0])->first;
00572       const typename SK::Circular_arc_point_3& pts2=object_cast<std::pair<typename SK::Circular_arc_point_3,unsigned> >(&inters[1])->first;
00573       
00574       
00575       //either a polar (1 pole + 1 pt) or a threaded circle (2 pts with theta-coord = +/- pi)
00576       if ( (pts1.x()!=0 && pts1.y()!=0) && compare_theta_pt_vector<SK>(pts1,m,sphere)==CGAL::EQUAL)
00577         return pts1;
00578       else
00579         return pts2;
00580     }
00581       
00582     
00583     template <class SK>
00584     //Compare the z coordinates of the intersection points with the meridian defined by m of two theta monotone arcs.
00585     CGAL::Comparison_result 
00586     compare_z_at_theta_arcs( const typename SK::Circular_arc_3& arc1,
00587                              const typename SK::Circular_arc_3& arc2,
00588                              const typename SK::Vector_3& m,
00589                              const typename SK::Sphere_3& sphere) 
00590     {
00591       CGAL_kernel_precondition(is_theta_monotone_3<SK>(arc1,sphere));
00592       CGAL_kernel_precondition(is_theta_monotone_3<SK>(arc2,sphere));
00593       
00594       typename SK::Circular_arc_point_3 pt1=intersect_3<SK>(arc1,m,sphere);
00595       typename SK::Circular_arc_point_3 pt2=intersect_3<SK>(arc2,m,sphere);
00596       return CGAL::compare(pt1.z(),pt2.z());
00597     }
00598 
00599     template <class SK>
00600     CGAL::Comparison_result 
00601     compare_z_at_theta_pt_arc(const typename SK::Circular_arc_point_3& pt,
00602                               const typename SK::Circular_arc_3& arc,
00603                               const typename SK::Sphere_3& sphere)
00604     {
00605       CGAL_kernel_precondition(is_theta_monotone_3<SK>(arc,sphere));
00606       CGAL::Circle_type type=classify_circle_3<SK>(arc.supporting_circle(),sphere);
00607       CGAL_kernel_precondition(type!=BIPOLAR);
00608       
00609       switch(type){
00610         case THREADED:
00611         case POLAR:
00612         {
00613           const typename SK::Plane_3& plane=arc.supporting_circle().supporting_plane();
00614           typename SK::Vector_3 ortho=plane.orthogonal_vector();
00615           int res=typename SK::Algebraic_kernel().sign_at_object()(
00616               typename SK::Algebraic_kernel::Polynomial_1_3(ortho.x(),ortho.y(),ortho.z(),plane.d()),
00617               pt.coordinates()
00618           );
00619           res*=(plane.orthogonal_vector().z()>0)?1:-1;
00620           return CGAL::Comparison_result(res);
00621         }
00622         default:
00623         {
00624           typename SK::Vector_3 ortho=arc.supporting_circle().center()-sphere.center();
00625           typename SK::FT d=-ortho * typename SK::Vector_3(CGAL::ORIGIN,arc.supporting_circle().center());
00626           int res=typename SK::Algebraic_kernel().sign_at_object()(
00627               typename SK::Algebraic_kernel::Polynomial_1_3(ortho.x(),ortho.y(),ortho.z(),d),
00628               pt.coordinates()
00629           );
00630           if (res==0) return CGAL::EQUAL;
00631           if (res==-1) return CGAL::compare(pt.z(),extremal_points_z_coordinate<SK>(arc.supporting_circle(),sphere));
00632           return is_upper_arc<SK>(arc,sphere)?CGAL::SMALLER:CGAL::LARGER;
00633         }
00634       }
00635     }
00636     
00637   }//SphericalFunctors
00638 }//CGAL
00639 
00640 #endif //CGAL_SPHERICAL_KERNEL_PREDICATES_ON_CIRCULAR_ARC_3_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines