// Copyright (c) 2014 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Remy Thomasse #ifndef CGAL_CONVEX_RANDOM_POLYTOPE_IN_DISC_H #define CGAL_CONVEX_RANDOM_POLYTOPE_IN_DISC_H #include #include #include #ifndef Q_MOC_RUN #include #endif #include #include #include namespace CGAL{ namespace internal{ template struct compare_points_angle{ bool operator()(const P& p, const P& q ){ typedef typename Kernel_traits

::Kernel Traits; Traits ch_traits; typedef typename Traits::Left_turn_2 Left_turn; Left_turn left_turn = ch_traits.left_turn_2_object(); if ( to_double(p.y())>0 ) { if (to_double(q.y())>0) return left_turn(ORIGIN,p,q); else return false; } else { if (to_double(q.y())>0) return true; else return left_turn(ORIGIN,p,q); } } }; ////////////////////////////////////// template void generate_points_annulus(long n,double a, double b,double small_radius, double big_radius,std::list

& l,GEN & gen){ //generate n points between a and b if (n>1){ boost::random::binomial_distributiondi(n,.5); boost::random::variate_generator >d(gen,di); long nb=d(); generate_points_annulus(nb,a,(a+b)/2.0,small_radius,big_radius,l,gen); generate_points_annulus(n-nb,(a+b)/2.0,b,small_radius,big_radius, l,gen); } if (n==1)//generation of a point { boost::random::uniform_real_distribution gd(small_radius*small_radius/(big_radius*big_radius),1); boost::random::uniform_real_distribution hd(a,b); boost::random::variate_generator >h(gen,hd); boost::random::variate_generator >g(gen,gd); double alpha=h(); double r=big_radius*std::sqrt(g()); typedef Creator_uniform_2::Kernel::RT,P> Creator; Creator creator; typedef typename Creator::argument_type T; l.push_back(creator(T(r*cos(alpha)) ,T(r*std::sin(alpha)))); } } template void Cyclic_increment_iterator(typename std::list

::iterator & it,std::list

& l){ ++it; if (it==l.end()) { it=l.begin(); } } ////////////////////////////////////////////////////////////////////////////// template void Graham_without_sort_2( std::list

&l, const Traits& ch_traits){ if (l.size()>3){ typedef typename Traits::Left_turn_2 Left_turn; Left_turn left_turn = ch_traits.left_turn_2_object(); typename std::list

::iterator pmin=l.begin(); for (typename std::list

::iterator it=l.begin(); it!=l.end(); ++it) { if ((*pmin).x()>(*it).x()) { pmin=it; } }//*pmin is the extremal point on the left typename std::list

::iterator u=pmin; typename std::list

::iterator u_next=u; Cyclic_increment_iterator(u_next,l); typename std::list

::iterator u_next_next=u_next; Cyclic_increment_iterator(u_next_next,l); while (u_next !=pmin){ if (left_turn(*u,*u_next,*u_next_next)){ Cyclic_increment_iterator(u,l); Cyclic_increment_iterator(u_next,l); Cyclic_increment_iterator(u_next_next,l); } else{ u_next=l.erase(u_next); if (u_next==l.end()) u_next=l.begin(); if(u !=pmin){ u_next=u; if(u==l.begin()){u=l.end();} --u; } else{ u_next_next=u_next; Cyclic_increment_iterator(u_next_next,l); } } } } } } //namespace CGAL::internal ////////////////////////////////////////////////////////////////////////////// template void convex_random_polygon(size_t n, typename Kernel_traits

::Kernel::FT radius, std::list

& l,GEN & gen, bool fast=true ){ CGAL_precondition( n >= 3); typedef typename Kernel_traits

::Kernel K; typedef typename Kernel_traits

::Kernel::FT FT; size_t simulated_points=0; size_t generated_points=0; do { //Initialisation size_t init=std::min( (size_t)100,n-simulated_points ); internal::generate_points_annulus(init,-CGAL_PI, CGAL_PI,0,radius,l,gen); simulated_points+=init; generated_points+=init; internal::Graham_without_sort_2(l,K()); } while ((bounded_side_2(l.begin(),l.end(),P (0,0),K())!=ON_BOUNDED_SIDE)&&(simulated_points::iterator it=l.begin(); while(to_double((*it).y())>0){ l.push_back(*it); l.pop_front(); it=l.begin(); } it=l.end(); --it;//last element while(to_double((*it).y())<0){ l.push_front(*it); l.pop_back(); it=l.end(); --it;//last element } } FT squared_radius=radius*radius; FT squared_small_radius=squared_radius; { P zero(0,0); typename std::list

::iterator it=l.begin(); typename std::list

::iterator it2=++it; for(;it!=l.end();++it,internal::Cyclic_increment_iterator(it2,l)){ //computation of annulus typename K::Segment_2 s(*it,*it2); FT temp=squared_distance(s,zero); if (squared_small_radius>temp) squared_small_radius=temp; } }//squared_small_radius=squared small radius of the annulus FT p_disc=squared_small_radius/squared_radius; size_t nb; if (simulated_points< T){nb=std::min(simulated_points,n-simulated_points);} else {nb=std::min(T,n-simulated_points); } boost::random::binomial_distribution dbin(nb,p_disc); boost::random::variate_generator >bin(gen,dbin); //How many points are falling in the small disc and wont be generated: long k_disc=bin(); simulated_points+=k_disc; std::list

m; m.clear(); internal::generate_points_annulus(nb-k_disc,-CGAL_PI, CGAL_PI,std::sqrt(to_double(squared_small_radius)),to_double(radius),m,gen); l.merge(m,internal::compare_points_angle

()); generated_points+=nb-k_disc; simulated_points+=nb-k_disc; m.clear(); internal::Graham_without_sort_2(l,K()); } } /// }//namespace CGAL #endif