dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/point_generators_2.h

713 lines
24 KiB
C++
Executable File

// Copyright (c) 1997
// 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$
// SPDX-License-Identifier: LGPL-3.0+
//
//
// Author(s) : Lutz Kettner <kettner@inf.ethz.ch>
// Pedro Machado Manhaes de Castro <pmmc@cin.ufpe.br>
// Alexandru Tifrea
// Maxime Gimeno
#ifndef CGAL_POINT_GENERATORS_2_H
#define CGAL_POINT_GENERATORS_2_H 1
#include <CGAL/disable_warnings.h>
#include <CGAL/generators.h>
#include <CGAL/number_type_basic.h>
#include <CGAL/internal/Generic_random_point_generator.h>
#include <CGAL/iterator.h>
#include <iterator>
namespace CGAL {
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P> >
class Random_points_in_disc_2 : public Random_generator_base<P>{
void generate_point();
public:
typedef Random_points_in_disc_2<P,Creator> This;
Random_points_in_disc_2( double r = 1, Random& rnd = CGAL::get_default_random())
// g is an input iterator creating points of type `P' uniformly
// distributed in the open disc with radius r, i.e. |`*g'| < r .
// Two random numbers are needed from `rnd' for each point.
: Random_generator_base<P>(r, rnd) { generate_point(); }
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P, class Creator >
void
Random_points_in_disc_2<P,Creator>::
generate_point() {
typedef typename Creator::argument_type T;
double alpha = this->_rnd.get_double() * 2.0 * CGAL_PI;
double r = this->d_range * std::sqrt( this->_rnd.get_double());
Creator creator;
this->d_item = creator( T(r * std::cos(alpha)),
T(r * std::sin(alpha)));
}
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT, P> >
class Random_points_on_circle_2 : public Random_generator_base<P> {
void generate_point();
public:
typedef Random_points_on_circle_2<P,Creator> This;
Random_points_on_circle_2( double r = 1, Random& rnd = CGAL::get_default_random())
// g is an input iterator creating points of type `P' uniformly
// distributed on the circle with radius r, i.e. |`*g'| == r . A
// single random number is needed from `rnd' for each point.
: Random_generator_base<P>(r, rnd) { generate_point(); }
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P, class Creator >
void
Random_points_on_circle_2<P,Creator>::
generate_point() {
typedef typename Creator::argument_type T;
double a = this->_rnd.get_double() * 2.0 * CGAL_PI;
Creator creator;
this->d_item = creator( T(this->d_range * std::cos(a)),
T(this->d_range * std::sin(a)));
}
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P> >
class Random_points_in_square_2 : public Random_generator_base<P> {
void generate_point();
public:
typedef Random_points_in_square_2<P,Creator> This;
Random_points_in_square_2( double a = 1, Random& rnd = CGAL::get_default_random())
// g is an input iterator creating points of type `P' uniformly
// distributed in the half-open square with side length a,
// centered around the origin, i.e. \forall p = `*g': -\frac{a}{2}
// <= p.x() < \frac{a}{2} and -\frac{a}{2} <= p.y() < \frac{a}{2}
// . Two random numbers are needed from `rnd' for each point.
: Random_generator_base<P>( a, rnd) { generate_point(); }
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P, class Creator >
void
Random_points_in_square_2<P,Creator>::
generate_point() {
typedef typename Creator::argument_type T;
Creator creator;
this->d_item =
creator( T(this->d_range * (2 * this->_rnd.get_double() - 1.0)),
T(this->d_range * (2 * this->_rnd.get_double() - 1.0)));
}
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P> >
class Random_points_on_square_2 : public Random_generator_base<P> {
void generate_point();
public:
typedef Random_points_on_square_2<P,Creator> This;
Random_points_on_square_2( double a = 1, Random& rnd = CGAL::get_default_random())
// g is an input iterator creating points of type `P' uniformly
// distributed on the boundary of the square with side length a,
// centered around the origin, i.e. \forall p = `*g': one
// coordinate is either \frac{a}{2} or -\frac{a}{2} and for the
// other coordinate c holds -\frac{a}{2} <= c < \frac{a}{2} . A
// single random number is needed from `rnd' for each point.
: Random_generator_base<P>( a, rnd) { generate_point(); }
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P, class Creator >
void
Random_points_on_square_2<P,Creator>::
generate_point() {
typedef typename Creator::argument_type T;
double d = this->_rnd.get_double() * 4.0;
int k = int(d);
d = this->d_range * (2 * (d - k) - 1.0);
CGAL_assertion( - this->d_range <= d && d < this->d_range);
Creator creator;
switch (k) {
case 0:
this->d_item = creator( T(d), T(-this->d_range));
break;
case 1:
this->d_item = creator( T(d), T(this->d_range));
break;
case 2:
this->d_item = creator( T(-this->d_range), T(d));
break;
case 3:
this->d_item = creator( T( this->d_range), T(d));
break;
}
}
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P> >
class Random_points_in_iso_rectangle_2 : public Random_generator_base<P> {
double left, right, top, bottom;
void generate_point();
public:
typedef Random_points_in_iso_rectangle_2<P,Creator> This;
Random_points_in_iso_rectangle_2( const P&p, const P& q, Random& rnd = CGAL::get_default_random())
: Random_generator_base<P>( 1.0 , rnd)
{
left = (std::min)(to_double(p.x()), to_double(q.x()));
right = (std::max)(to_double(p.x()), to_double(q.x()));
top = (std::min)(to_double(p.y()), to_double(q.y()));
bottom = (std::max)(to_double(p.y()), to_double(q.y()));
generate_point();
}
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P, class Creator >
void
Random_points_in_iso_rectangle_2<P,Creator>::
generate_point() {
typedef typename Creator::argument_type T;
Creator creator;
this->d_item =
creator( T(this->_rnd.get_double(left,right)),
T(this->_rnd.get_double(top,bottom)));
}
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P> >
class Random_points_on_segment_2 : public Random_generator_base<P> {
P _p;
P _q;
void generate_point();
public:
typedef Random_points_on_segment_2<P,Creator> This;
Random_points_on_segment_2( const P& p = P( -1, 0),
const P& q = P( 1, 0),
Random& rnd = CGAL::get_default_random())
// g is an input iterator creating points of type `P' uniformly
// distributed on the segment from p to q except q, i.e. `*g' ==
// \lambda p + (1-\lambda)\, q where 0 <= \lambda < 1 . A single
// random number is needed from `rnd' for each point.
: Random_generator_base<P>( (std::max)( (std::max)( to_double(p.x()), to_double(q.x())),
(std::max)( to_double(p.y()),
to_double(q.y()))),
rnd) , _p(p), _q(q)
{
generate_point();
}
const P& source() const { return _p; }
const P& target() const { return _q; }
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P, class Creator >
void
Random_points_on_segment_2<P,Creator>::
generate_point() {
typedef typename Creator::argument_type T;
double la = this->_rnd.get_double();
double mu = 1.0 - la;
Creator creator;
this->d_item = creator(T(mu * to_double(_p.x()) + la * to_double(_q.x())),
T(mu * to_double(_p.y()) + la * to_double(_q.y())));
}
template < class P >
class Points_on_segment_2 : public Generator_base<P> {
P _p;
P _q;
std::size_t d_i;
std::size_t d_mx;
void generate_point();
public:
typedef Points_on_segment_2<P> This;
Points_on_segment_2() {}
Points_on_segment_2( const P& p, const P& q,
std::size_t mx, std::size_t i = 0)
: Generator_base<P>( (std::max)( (std::max)( to_double(p.x()), to_double(q.x())),
(std::max)( to_double(p.y()), to_double(q.y())))),
_p(p), _q(q), d_i(i), d_mx(mx)
{
generate_point();
}
const P& source() const { return _p; }
const P& target() const { return _q; }
// Sufficient equality test.
bool operator==( const This& base) const { return ( d_i == base.d_i); }
bool operator!=( const This& base) const { return ! operator==(base); }
This& operator++() {
d_i++;
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template < class P >
void
Points_on_segment_2<P>::
generate_point() { this->d_item = _p + (_q-_p) * static_cast<double>(d_i) / (static_cast<double>(d_mx)-1); }
template <class OutputIterator, class Creator>
OutputIterator
points_on_square_grid_2( double a, std::size_t n, OutputIterator o,
Creator creator)
{
typedef typename Creator::argument_type T;
if (n == 0)
return o;
int m = int(std::ceil(std::sqrt(static_cast<double>(n))));
double base = -a; // Left and bottom boundary.
double step = (2*a)/(m - 1);
int j = 0;
double px = base;
double py = base;
*o++ = creator( T(px), T(py));
for (std::size_t i = 1; i < n; i++) {
j++;
if ( j == m) {
px = base;
py = py + step;
j = 0;
} else {
px = px + step;
}
*o++ = creator( T(px), T(py));
}
return o;
}
template <class OutputIterator>
OutputIterator
points_on_square_grid_2( double a, std::size_t n, OutputIterator o)
{
typedef std::iterator_traits<OutputIterator> ITraits;
typedef typename ITraits::value_type P;
return points_on_square_grid_2(a, n, o,
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P>());
}
template <class P, class OutputIterator>
OutputIterator
points_on_segment_2( const P& p, const P& q, std::size_t n,
OutputIterator o)
// creates n points regular spaced on the segment from p to q, i.e.
// \forall i: 0 <= i < n: o[i] := \frac{n-i-1}{n-1} p + \frac{i}{n-1
// } q.
{
for (std::size_t i = 0; i < n; i++) {
*o++ = p + (q-p) * static_cast<typename Kernel_traits<P>::Kernel::FT>(static_cast<double>(i) / (static_cast<double>(n)-1));
}
return o;
}
template <class ForwardIterator, class Creator>
void perturb_points_2( ForwardIterator first,
ForwardIterator last,
double xeps,
double yeps,
Random& rnd,
Creator creator)
// perturbs the points in the range [`first',`last') by replacing
// each point with a random point from the rectangle `xeps' \times
// `yeps' centered around the original point. Two random numbers are
// needed from `rnd' for each point. Precondition:
// The expression `to_double((*first).x())' and `to_double((
// *begin).y())' must be legal.
{
typedef typename Creator::argument_type T;
xeps *= 2.0;
yeps *= 2.0;
for ( ; first != last; ++first) {
double x = to_double( (*first).x());
double y = to_double( (*first).y());
x += xeps * (rnd.get_double() - 0.5);
y += yeps * (rnd.get_double() - 0.5);
*first = creator( T(x), T(y));
}
}
template <class ForwardIterator>
void perturb_points_2( ForwardIterator first,
ForwardIterator last,
double xeps,
double yeps,
Random& rnd)
{
typedef std::iterator_traits<ForwardIterator> ITraits;
typedef typename ITraits::value_type P;
perturb_points_2( first, last, xeps, yeps, rnd,
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P>());
}
template <class ForwardIterator>
inline
void perturb_points_2( ForwardIterator first,
ForwardIterator last,
double xeps,
Random& rnd)
{
perturb_points_2( first, last, xeps, xeps, rnd);
}
template <class ForwardIterator>
void perturb_points_2( ForwardIterator first,
ForwardIterator last,
double xeps,
double yeps)
{
perturb_points_2( first, last, xeps, yeps, CGAL::get_default_random());
}
template <class ForwardIterator>
void perturb_points_2( ForwardIterator first,
ForwardIterator last,
double xeps)
{
perturb_points_2( first, last, xeps, xeps, CGAL::get_default_random());
}
template <class RandomAccessIterator, class OutputIterator, class Creator>
OutputIterator random_collinear_points_2(
RandomAccessIterator first,
RandomAccessIterator last,
std::size_t n,
OutputIterator first2,
Random& rnd,
Creator creator)
{
typedef typename Creator::result_type Point;
typedef typename Creator::argument_type T;
std::ptrdiff_t m = last - first;
for ( std::size_t i = 0; i < n; i++) {
const Point& p = first[ rnd.uniform_int<std::ptrdiff_t>( 0, m-1)];
const Point& q = first[ rnd.uniform_int<std::ptrdiff_t>( 0, m-1)];
double la = rnd.get_double();
double mu = 1.0 - la;
*first2++ = creator(T(mu * to_double(p.x()) +
la * to_double(q.x())),
T(mu * to_double(p.y()) +
la * to_double(q.y())));
}
return first2;
}
template <class RandomAccessIterator, class OutputIterator>
OutputIterator random_collinear_points_2(
RandomAccessIterator first,
RandomAccessIterator last,
std::size_t n,
OutputIterator first2,
Random& rnd)
// choose two random points from the range [`first',`last'), create a
// random third point on the segment connecting this two points, and
// write it to `first2'. Repeat this n times, thus writing n points to
// `first2' that are collinear with points in the range [`first',
// `last'). Three random numbers are needed from `rnd' for each point.
// Returns the value of `first2' after inserting the n points.
// Precondition: The expression `to_double((*first).x()
// )' and `to_double((*first).y())' must be legal.
{
typedef std::iterator_traits<RandomAccessIterator> ITraits;
typedef typename ITraits::value_type P;
return random_collinear_points_2( first, last, n, first2, rnd,
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P>());
}
template <class RandomAccessIterator, class OutputIterator>
OutputIterator random_collinear_points_2(
RandomAccessIterator first,
RandomAccessIterator last,
std::size_t n,
OutputIterator first2)
{
return random_collinear_points_2( first, last, n, first2,
CGAL::get_default_random());
}
template < class P, class Creator =
Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT,P> >
class Random_points_in_triangle_2 : public Random_generator_base<P> {
P _p,_q,_r;
void generate_point();
public:
typedef P result_type;
typedef Random_points_in_triangle_2<P, Creator> This;
typedef typename Kernel_traits<P>::Kernel::Triangle_2 Triangle_2;
Random_points_in_triangle_2() {}
Random_points_in_triangle_2( const This& x,Random& rnd)
: Random_generator_base<P>( 1, rnd ),_p(x._p),_q(x._q),_r(x._r) {
generate_point();
}
Random_points_in_triangle_2( const P& p, const P& q, const P& r, Random& rnd = get_default_random())
: Random_generator_base<P>( 1, rnd ),_p(p),_q(q),_r(r) {
generate_point();
}
Random_points_in_triangle_2( const Triangle_2& triangle,Random& rnd = get_default_random())
: Random_generator_base<P>( 1,
rnd),_p(triangle[0]),_q(triangle[1]),_r(triangle[2]) {
generate_point();
}
This& operator++() {
generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
template<class P, class Creator >
void Random_points_in_triangle_2<P, Creator>::generate_point() {
typedef typename Creator::argument_type T;
Creator creator;
double a1 = this->_rnd.get_double(0,1);
double a2 = this->_rnd.get_double(0,1);
if(a1>a2) std::swap(a1,a2);
double b1 = a1;
double b2 = a2-a1;
double b3 = 1.0-a2;
this->d_item = creator(T(to_double(_p.x())*b1+to_double(_q.x())*b2+to_double(_r.x())*b3),
T(to_double(_p.y())*b1+to_double(_q.y())*b2+to_double(_r.y())*b3));
}
namespace internal {
//Functor returning Triangle_2 from Triangulation_2 Faces
template <class T>
class Triangle_from_face_2
{
typedef typename T::Triangle Triangle;
public:
typedef Triangle result_type;
Triangle_from_face_2() {}
Triangle operator()(typename T::Finite_faces_iterator face) const {
return Triangle(face->vertex(0)->point(), face->vertex(1)->point(), face->vertex(2)->point());
}
};
struct Is_not_in_domain
{
typedef bool result_type;
template <class FH>
result_type operator()(const FH fh) const {
return (!fh->is_in_domain());
}
};
template <class T>
class In_domain_finite_faces_iterator
: public Filter_iterator<typename T::Finite_faces_iterator, Is_not_in_domain>
{
typedef CGAL::Filter_iterator<typename T::Finite_faces_iterator, Is_not_in_domain> Base;
typedef In_domain_finite_faces_iterator<T> Self;
typedef typename T::Face_handle Face_handle;
typedef typename T::Finite_faces_iterator Finite_faces_iterator;
public:
In_domain_finite_faces_iterator() : Base() {}
In_domain_finite_faces_iterator(const Base &b) : Base(b) {}
Self & operator++() { Base::operator++(); return *this; }
Self & operator--() { Base::operator--(); return *this; }
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
operator Finite_faces_iterator() const { return Base::base(); }
operator Face_handle() const { return Face_handle(Base::base()); }
};
}//end namespace internal
template <class P,
class T,
class Creator = Creator_uniform_2<typename Kernel_traits<P>::Kernel::RT, P> >
class Random_points_in_triangle_mesh_2
: public Generic_random_point_generator<internal::In_domain_finite_faces_iterator<T>,
internal::Triangle_from_face_2<T>,
Random_points_in_triangle_2<P, Creator>,
P>
{
public:
typedef Generic_random_point_generator<internal::In_domain_finite_faces_iterator<T>,
internal::Triangle_from_face_2<T>,
Random_points_in_triangle_2<P, Creator>,
P> Base;
typedef typename T::Face_handle Id;
typedef P result_type;
typedef Random_points_in_triangle_mesh_2<P, T, Creator> This;
Random_points_in_triangle_mesh_2(const T& triangulation, Random& rnd = get_default_random())
: Base(CGAL::make_prevent_deref_range(
CGAL::filter_iterator(triangulation.finite_faces_end(),
internal::Is_not_in_domain(),
triangulation.finite_faces_begin()),
CGAL::filter_iterator(triangulation.finite_faces_end(),
internal::Is_not_in_domain())),
internal::Triangle_from_face_2<T>(),
typename Kernel_traits<P>::Kernel::Compute_area_2(),
rnd)
{
}
This& operator++() {
Base::generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
namespace internal
{
template<class T>
class Deref
{
public:
typedef const T& result_type;
const T& operator()(const T* triangle) const
{
return *triangle;
}
};
template<class A>
struct Address_of {
typedef const A* result_type;
const A* operator()(const A& a) const
{
return &a;
}
};
}//namesapce internal
template <class Point_2,
class Triangle_2=typename Kernel_traits<Point_2>::Kernel::Triangle_2,
class Creator =
Creator_uniform_2<typename Kernel_traits<Point_2>::Kernel::RT,Point_2> >
struct Random_points_in_triangles_2
: public Generic_random_point_generator<const Triangle_2*,
internal::Deref<Triangle_2>,
Random_points_in_triangle_2<Point_2>,
Point_2>
{
typedef Generic_random_point_generator<const Triangle_2*,
internal::Deref<Triangle_2>,
Random_points_in_triangle_2<Point_2, Creator>,
Point_2> Base;
typedef const Triangle_2* Id;
typedef Point_2 result_type;
typedef Random_points_in_triangles_2<Point_2, Triangle_2, Creator> This;
template<typename TriangleRange>
Random_points_in_triangles_2( const TriangleRange& triangles, Random& rnd = get_default_random())
: Base(make_range( boost::make_transform_iterator(triangles.begin(), internal::Address_of<Triangle_2>()),
boost::make_transform_iterator(triangles.end(), internal::Address_of<Triangle_2>()) ),
internal::Deref<Triangle_2>(),
typename Kernel_traits<Point_2>::Kernel::Compute_area_2(),
rnd )
{
}
This& operator++() {
Base::generate_point();
return *this;
}
This operator++(int) {
This tmp = *this;
++(*this);
return tmp;
}
};
} //namespace CGAL
#include <CGAL/enable_warnings.h>
#endif // CGAL_POINT_GENERATORS_2_H //
// EOF //