Completely revised version. build function replaced by creator

function objects. Three creators for 3D points added. Segment
generator replaced by examples based on Join_input_iterator.
Points on segment also as iterator.
Documents generator.any release 1.8.
This commit is contained in:
Lutz Kettner 1997-11-02 18:48:12 +00:00
parent 8e42db4650
commit fd78a1612b
6 changed files with 558 additions and 362 deletions

View File

@ -10,13 +10,15 @@
#include <CGAL/Point_2.h> #include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h> #include <CGAL/Segment_2.h>
#include <CGAL/point_generators_2.h> #include <CGAL/point_generators_2.h>
#include <CGAL/Segment_generator.h> #include <CGAL/function_objects.h>
#include <CGAL/Join_input_iterator.h>
#include <CGAL/copy_n.h> #include <CGAL/copy_n.h>
#include <CGAL/IO/Window_stream.h> /* only for visualization used */ #include <CGAL/IO/Window_stream.h> /* only for visualization used */
typedef CGAL_Cartesian<double> R; typedef CGAL_Cartesian<double> R;
typedef CGAL_Point_2<R> Point; typedef CGAL_Point_2<R> Point;
typedef CGAL_Segment_2<R> Segment; typedef CGAL_Creator_uniform_2<double,Point> Pt_creator;
typedef CGAL_Segment_2<R> Segment;
int main() int main()
{ {
@ -25,15 +27,17 @@ int main()
segs.reserve(200); segs.reserve(200);
/* Prepare point generator for the horizontal segment, length 200. */ /* Prepare point generator for the horizontal segment, length 200. */
typedef CGAL_Random_points_on_segment_2<Point> P1; typedef CGAL_Random_points_on_segment_2<Point,Pt_creator> P1;
P1 p1( Point(-100,0), Point(100,0)); P1 p1( Point(-100,0), Point(100,0));
/* Prepare point generator for random points on circle, radius 250. */ /* Prepare point generator for random points on circle, radius 250. */
typedef CGAL_Random_points_on_circle_2<Point> P2; typedef CGAL_Random_points_on_circle_2<Point,Pt_creator> P2;
P2 p2( 250); P2 p2( 250);
/* Create 200 segments. */ /* Create 200 segments. */
CGAL_Segment_generator<Segment, P1, P2> g( p1, p2); typedef CGAL_Creator_uniform_2< Point, Segment> Seg_creator;
typedef CGAL_Join_input_iterator_2< P1, P2, Seg_creator> Seg_iterator;
Seg_iterator g( p1, p2);
CGAL_copy_n( g, 200, back_inserter( segs)); CGAL_copy_n( g, 200, back_inserter( segs));
/* Visualize segments. Can be omitted, see example programs */ /* Visualize segments. Can be omitted, see example programs */

View File

@ -1,65 +1,55 @@
/* Segment_generator_prog2.C */ /* Segment_generator_prog2.C */
/* ------------------------------- */ /* ------------------------------- */
/* CGAL example program for the generic segment generator */ /* CGAL example program generating a regular segment pattern. */
/* using precomputed point locations. */
#include <CGAL/basic.h> #include <CGAL/basic.h>
#include <assert.h>
#include <vector.h>
#include <algo.h> #include <algo.h>
#include <CGAL/Cartesian.h> #include <CGAL/Cartesian.h>
#include <CGAL/Point_2.h> #include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h> #include <CGAL/Segment_2.h>
#include <CGAL/point_generators_2.h> #include <CGAL/point_generators_2.h>
#include <CGAL/Segment_generator.h> #include <CGAL/function_objects.h>
#include <CGAL/copy_n.h> #include <CGAL/Join_input_iterator.h>
#include <CGAL/IO/Window_stream.h> /* only for visualization used */ #include <CGAL/Counting_iterator.h>
#include <CGAL/IO/Ostream_iterator.h>
#include <CGAL/IO/Window_stream.h>
typedef CGAL_Cartesian<double> R;
typedef CGAL_Point_2<R> Point;
typedef CGAL_Segment_2<R> Segment;
typedef CGAL_Points_on_segment_2<Point> PG;
typedef CGAL_Creator_uniform_2< Point, Segment> Creator;
typedef CGAL_Join_input_iterator_2< PG, PG, Creator> Segm_iterator;
typedef CGAL_Counting_iterator<Segm_iterator,Segment> Count_iterator;
typedef CGAL_Cartesian<double> R;
typedef CGAL_Point_2<R> Point;
typedef CGAL_Segment_2<R> Segment;
int main() int main()
{ {
/* Prepare two point vectors for the precomputed points. */ /* Open window. */
vector<Point> p1, p2;
p1.reserve(100);
p2.reserve(100);
/* Create points for a horizontal like fan. */
CGAL_points_on_segment_2( Point(-250, -50), Point(-250, 50),
50, back_inserter( p1));
CGAL_points_on_segment_2( Point( 250,-250), Point( 250,250),
50, back_inserter( p2));
/* Create points for a vertical like fan. */
CGAL_points_on_segment_2( Point( -50,-250), Point( 50,-250),
50, back_inserter( p1));
CGAL_points_on_segment_2( Point(-250, 250), Point( 250, 250),
50, back_inserter( p2));
/* Create test segment set. Prepare a vector for 100 segments. */
vector<Segment> segs;
segs.reserve(100);
/* Create both fans at once from the precomputed points. */
typedef vector<Point>::iterator I;
I i1 = p1.begin();
I i2 = p2.begin();
CGAL_Segment_generator<Segment,I,I> g( i1, i2);
CGAL_copy_n( g, 100, back_inserter( segs));
/* Visualize segments. Can be omitted, see example programs */
/* in the CGAL source code distribution. */
CGAL_Window_stream W(512, 512); CGAL_Window_stream W(512, 512);
W.init(-256.0, 255.0, -256.0); W.init(-256.0, 255.0, -256.0);
W << CGAL_BLACK; W << CGAL_BLACK;
for( vector<Segment>::iterator i = segs.begin(); i != segs.end(); i++)
W << *i; /* A horizontal like fan. */
PG p1( Point(-250, -50), Point(-250, 50),50); /* Point generator. */
PG p2( Point( 250,-250), Point( 250,250),50);
Segm_iterator t1( p1, p2); /* Segment generator. */
Count_iterator t1_begin( t1); /* Finite range. */
Count_iterator t1_end( 50);
copy( t1_begin, t1_end,
CGAL_Ostream_iterator<Segment,CGAL_Window_stream>(W));
/* A vertical like fan. */
PG p3( Point( -50,-250), Point( 50,-250),50);
PG p4( Point(-250, 250), Point( 250, 250),50);
Segm_iterator t2( p3, p4);
Count_iterator t2_begin( t2);
Count_iterator t2_end( 50);
copy( t2_begin, t2_end,
CGAL_Ostream_iterator<Segment,CGAL_Window_stream>(W));
/* Wait for mouse click in window. */ /* Wait for mouse click in window. */
Point p; Point p;
W >> p; W >> p;
return 0; return 0;
} }

View File

@ -26,10 +26,15 @@ e.g.~for testing algorithms on degenerate object sets and for
performance analysis. performance analysis.
The first section describes the random number source used for random The first section describes the random number source used for random
generators. The second section documents generators for point sets, generators. The second section provides useful generic functions
the third section for segments. Note that the \stl\ algorithm related to random numbers like \ccc{CGAL_random_selection()}. The
\ccc{random_shuffle} is useful in this context to achieve random third section documents generators for two-dimensional point sets, the
permutations (e.g.~for points on a grid). fourth section for three-dimensional point sets. The fifth section
presents examples using functions from
Section~\ref{sectionGenericFunctions} to generate composed objects
like segments. Note that the \stl\ algorithm \ccc{random_shuffle} is
useful in this context to achieve random permutations for otherwise
regular generators (e.g.~points on a grid or segment).
% +------------------------------------------------------------------------+ % +------------------------------------------------------------------------+
@ -40,28 +45,14 @@ permutations (e.g.~for points on a grid).
\section{Support Functions for Generators} \section{Support Functions for Generators}
\ccThree{OutputIterator}{rand}{} \ccThree{OutputIterator}{rand}{}
Two support functions are provided. \ccc{CGAL_copy_n()} copies $n$
items from an input iterator to an output iterator which is useful for
possibly infinite sequences of random geometric objects\footnote{%
The STL release June 13, 1997, from SGI has a new function \ccc{copy_n} which is equivalent with \ccc{CGAL_copy_n}.}.
\ccc{CGAL_random_selection} chooses $n$ items at random from a random
access iterator range which is useful to produce degenerate input data
sets with multiple entries of identical items.
\subsection{{\it CGAL\_copy\_n()}}
\label{sectionCopyN}
\ccInclude{CGAL/copy_n.h}
\ccFunction{template <class InputIterator, class Size, class OutputIterator>
OutputIterator CGAL_copy_n( InputIterator first, Size n,
OutputIterator result);}
{copies the first $n$ items from \ccc{first} to \ccc{result}.
Returns the value of \ccc{result} after inserting the $n$ items.}
\subsection{{\it CGAL\_random\_selection()}} \subsection{{\it CGAL\_random\_selection()}}
\label{sectionRandomSelection} \label{sectionRandomSelection}
\ccc{CGAL_random_selection} chooses $n$ items at random from a random
access iterator range which is useful to produce degenerate input data
sets with multiple entries of identical items.
\ccInclude{CGAL/random_selection.h} \ccInclude{CGAL/random_selection.h}
\ccFunction{template <class RandomAccessIterator, class Size, \ccFunction{template <class RandomAccessIterator, class Size,
@ -69,9 +60,9 @@ sets with multiple entries of identical items.
OutputIterator CGAL_random_selection( RandomAccessIterator first, OutputIterator CGAL_random_selection( RandomAccessIterator first,
RandomAccessIterator last, RandomAccessIterator last,
Size n, OutputIterator result, Random& rnd = CGAL_random);} Size n, OutputIterator result, Random& rnd = CGAL_random);}
{ choose a random item from the range $[\ccc{first},\ccc{last})$ and { chooses a random item from the range $[\ccc{first},\ccc{last})$ and
write it to \ccc{result}, each item from the range with equal writes it to \ccc{result}, each item from the range with equal
probability. Repeat this $n$ times, thus writing $n$ items to probability, and repeats this $n$ times, thus writing $n$ items to
\ccc{result}. \ccc{result}.
A single random number is needed from \ccc{rnd} for each item. A single random number is needed from \ccc{rnd} for each item.
Returns the value of \ccc{result} after inserting the $n$ items. Returns the value of \ccc{result} after inserting the $n$ items.
@ -85,48 +76,56 @@ sets with multiple entries of identical items.
\newpage \newpage
\section{2D Point Generators} \section{2D Point Generators}
Two kind of point generators are provided: First, random point
generators and second deterministic point generators. Most random
point generators and a few deterministic point generators are provided
as input iterators. The input iterators model an infinite sequence of
points. The function \ccc{CGAL_copy_n()} could be used to copy a
finite sequence, see Section~\ref{sectionCopyN}. The iterator adaptor
\ccc{CGAL_Counting_iterator} can be used to create finite iterator
ranges, see Section~\ref{sectionCountingIterator}.
Other generators are provided as functions writing to an output
iterator. Further functions add degeneracies or random perturbations.
% +------------------------------------------------------------------------+
\subsection{Point Generators as Input Iterators}
\ccDefinition \ccDefinition
Point generators are provided for random points uniformly distributed Input iterators are provided for random points uniformly distributed
over a two-dimensional domain (square or disc) or a one-dimensional over a two-dimensional domain (square or disc) or a one-dimensional
domain (boundary of a square, circle, or segment). Other point domain (boundary of a square, circle, or segment). Another input
generators create two-dimensional grids or equally spaced points on a iterator generates equally spaced points from a segment.
segment. A perturbation function adds random noise to a given set of
points. Several functions add degeneracies: the duplication of randomly
chosen points and the construction of a collinear point between two randomly
chosen points from a set of points.
All iterators are parameterized with the point type \ccc{P} and all
with the exception of \ccc{CGAL_Points_on_segment_2} have a second
template argument \ccc{Creator} which defaults to
\ccc{CGAL_Creator_uniform_2<double,P>}\footnote{%
For compilers not supporting these kind of default arguments, both
template arguments must be provided when using these generators.}.
The \ccc{Creator} must be a function object accepting two \ccc{double}
values $x$ and $y$ and returning an initialized point \ccc{(x,y)} of type
\ccc{P}. Predifined implementations for these creators like the
default can be found in Section~\ref{sectionCreatorFunctionObjects}.
They simply assume an appropriate constructor for type \ccc{P}.
All generators know a range within which the coordinates of the
generated points will lie.
\ccInclude{CGAL/point_generators_2.h} \ccInclude{CGAL/point_generators_2.h}
\ccTypes
The generators comply to the requirements of input iterators which
includes local type declarations including \ccc{value_type} which
denotes \ccc{P} here.
\ccCreation \ccCreation
The random point generators build two-dimensional points from a pair
of \ccc{double}'s. Depending on the point representation and
arithmetic, a different building process is necessary. It is
encapsulated in the global function \ccc{CGAL_build_point()}.
Implementations exist for \ccc{CGAL_Cartesian<double>} and
\ccc{CGAL_Cartesian<float>}. They are automatically included if the
representation type \ccc{CGAL_Cartesian} has been included beforehand.
For other representations and arithmetic types the function can be
overloaded.
\ccThree{void}{random}{}
\ccFunction{void CGAL_build_point( double x, double y, Point&
p);}{builds a point $(x,y)$ in $p$. \ccc{Point} is the point type in
question.}
\ccHeading{Random Points}
The random point generators are implemented as classes that satisfies
the requirements for input iterators. They represent the possibly
infinite sequence of randomly generated points. Each call to the
\ccc{operator*} returns a new point. To create a finite sequence in a
container, the function \ccc{CGAL_copy_n()} could be used, see
Section~\ref{sectionCopyN}.
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_disc_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_in_disc_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_disc_2( double r, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_in_disc_2( double r, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
@ -134,12 +133,11 @@ Section~\ref{sectionCopyN}.
distributed in the open disc with radius $r$, distributed in the open disc with radius $r$,
i.e.~$|\ccc{*g}| < r$~. Two random numbers are needed from i.e.~$|\ccc{*g}| < r$~. Two random numbers are needed from
\ccc{rnd} for each point. \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_on_circle_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_on_circle_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_circle_2( double r, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_on_circle_2( double r, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
@ -147,76 +145,116 @@ Section~\ref{sectionCopyN}.
distributed on the circle with radius $r$, distributed on the circle with radius $r$,
i.e.~$|\ccc{*g}| == r$~. A single random number is needed from i.e.~$|\ccc{*g}| == r$~. A single random number is needed from
\ccc{rnd} for each point. \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_square_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_in_square_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_square_2( double a, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_in_square_2( double a, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly $g$ is an input iterator creating points of type \ccc{P} uniformly
distributed in the half-open square with side length $a$, centered distributed in the half-open square with side length $2 a$, centered
at the origin, i.e.~$\forall p = \ccc{*g}: -\frac{a}{2} \le at the origin, i.e.~$\forall p = \ccc{*g}: -a \le p.x() < a$ and
p.x() < \frac{a}{2}$ and $-\frac{a}{2} \le p.y() < \frac{a}{2}$~. $-a \le p.y() < a$~.
Two random numbers are needed from \ccc{rnd} for each point. Two random numbers are needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_on_square_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_on_square_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_square_2( double a, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_on_square_2( double a, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly $g$ is an input iterator creating points of type \ccc{P} uniformly
distributed on the boundary of the square with side length $a$, distributed on the boundary of the square with side length $2 a$,
centered at the origin, i.e.~$\forall p = \ccc{*g}:$ one centered at the origin, i.e.~$\forall p = \ccc{*g}:$ one
coordinate is either $\frac{a}{2}$ or $-\frac{a}{2}$ and for the coordinate is either $a$ or $-a$ and for the
other coordinate $c$ holds $-\frac{a}{2} \le c < \frac{a}{2}$~. other coordinate $c$ holds $-a \le c < a$~.
A single random number is needed from \ccc{rnd} for each point. A single random number is needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_on_segment_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_on_segment_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_segment_2( const P& p, const P& q, \ccConstructor{CGAL_Random_points_on_segment_2( const P& p, const P& q,
CGAL_Random& rnd = CGAL_random);}{% CGAL_Random& rnd = CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly $g$ is an input iterator creating points of type \ccc{P} uniformly
distributed on the segment from $p$ to $q$ except $q$, distributed on the segment from $p$ to $q$ (excluding $q$),
i.e.~$\ccc{*g} == (1-\lambda)\, p + \lambda q$ where $0 \le \lambda < 1$~. i.e.~$\ccc{*g} == (1-\lambda)\, p + \lambda q$ where $0 \le \lambda < 1$~.
A single random number is needed from \ccc{rnd} for each point. A single random number is needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type \ccc{P} \ccPrecond The expressions \ccc{CGAL_to_double(p.x())} and
exists. The expressions \ccc{CGAL_to_double(p.x())} and
\ccc{CGAL_to_double(p.y())} must result in the respective \ccc{CGAL_to_double(p.y())} must result in the respective
\ccc{double} representation of the coordinates and similar for $q$.} \ccc{double} representation of the coordinates and similar for $q$.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Points_on_segment_2<P>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Points_on_segment_2( const P& p, const P& q,
size_t n, size_t i = 0);}{%
$g$ is an input iterator creating points of type \ccc{P} equally
spaced on the segment from $p$ to $q$. $n$ points are placed on the
segment including $p$ and $q$. The iterator denoted the point $i$
where $p$ has the index 0 and $q$ the index $n$.
\ccPrecond The expressions \ccc{CGAL_to_double(p.x())} and
\ccc{CGAL_to_double(p.y())} must result in the respective
\ccc{double} representation of the coordinates and similar for $q$.}
\ccOperations
\ccThree{double}{g.source();}{}
\ccMethod{double range();}{returns the range in which the point
coordinates lie, i.e.~$\forall x: |x| \leq $\ccc{range()} and
$\forall y: |y| \leq $\ccc{range()}.}
The generators \ccc{CGAL_Random_points_on_segment_2} and
\ccc{CGAL_Points_on_segment_2} have to additional methods.
\ccMethod{const P& source();}{returns the source point of the segment.}
\ccGlue
\ccMethod{const P& target();}{returns the target point of the segment.}
\end{ccClassTemplate}
% +------------------------------------------------------------------------+
\subsection{Point Generators as Functions}
\ccHeading{Grid Points} \ccHeading{Grid Points}
\ccThree{OutputIterator}{rand}{} \ccThree{OutputIterator}{rand}{}
Grid points are produced by generating functions writing to an output Grid points are generated by functions writing to an output iterator.
iterator.
\ccFunction{template <class OutputIterator> \def\ccLongParamLayout{\ccTrue}
\ccFunction{template <class OutputIterator, Creator creator>
OutputIterator OutputIterator
CGAL_points_on_square_grid_2( double a, size_t n, OutputIterator o, CGAL_points_on_square_grid_2( double a, size_t n, OutputIterator o,
const P*);} const P*, Creator creator =
CGAL_Creator_uniform_2<double,P>);}
{ creates the $n$ first points on the regular $\lceil\sqrt{n}\,\rceil { creates the $n$ first points on the regular $\lceil\sqrt{n}\,\rceil
\times \lceil \sqrt{n}\,\rceil$ grid within the square \times \lceil \sqrt{n}\,\rceil$ grid within the square
$[-\frac{a}{2},\frac{a}{2}]\times [-\frac{a}{2},\frac{a}{2}]$. $[-a,a]\times [-a,a]$. Returns the value of $o$ after inserting
Returns the value of $o$ after inserting the $n$ points. the $n$ points.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type \ccPrecond \ccc{Creator} must be a function object accepting two
$P$ and $P$ must be assignable to the value type of \ccc{double} values $x$ and $y$ and returning an initialized point
\ccc{OutputIterator}.} \ccc{(x,y)} of type \ccc{P}. Predifined implementations for these
creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. The
\ccc{OutputIterator} must accept values of type \ccc{P}. If the
\ccc{OutputIterator} has a \ccc{value_type} the default
initializer of the \ccc{creator} can be used. \ccc{P} is set to
the \ccc{value_type} in this case.}
\def\ccLongParamLayout{\ccFalse}
\ccFunction{template <class P, class OutputIterator> \ccFunction{template <class P, class OutputIterator>
OutputIterator CGAL_points_on_segment_2( const P& p, const P& q, size_t n, OutputIterator CGAL_points_on_segment_2( const P& p, const P& q, size_t n,
OutputIterator o);} OutputIterator o);}
{ creates $n$ points regular spaced on the segment from $p$ to $q$, { creates $n$ points equally spaced on the segment from $p$ to $q$,
i.e.~$\forall i: 0 \le i < n: o[i] := \frac{n-i-1}{n-1}\, p + i.e.~$\forall i: 0 \le i < n: o[i] := \frac{n-i-1}{n-1}\, p +
\frac{i}{n-1}\, q$. Returns the value of $o$ after inserting \frac{i}{n-1}\, q$. Returns the value of $o$ after inserting
the $n$ points.} the $n$ points.}
@ -230,13 +268,20 @@ exact predicates to compute the sign of expressions slightly off from zero.
\ccFunction{template <class ForwardIterator> \ccFunction{template <class ForwardIterator>
void CGAL_perturb_points_2( ForwardIterator first, ForwardIterator last, void CGAL_perturb_points_2( ForwardIterator first, ForwardIterator last,
double xeps, double yeps = xeps, CGAL_Random& rnd = CGAL_random);} double xeps, double yeps = xeps, CGAL_Random& rnd = CGAL_random,
Creator creator = CGAL_Creator_uniform_2<double,P>);}
{ perturbs the points in the range $[\ccc{first},\ccc{last})$ by { perturbs the points in the range $[\ccc{first},\ccc{last})$ by
replacing each point with a random point from the rectangle replacing each point with a random point from the rectangle
\ccc{xeps} $\times$ \ccc{yeps} centered at the original point. \ccc{xeps} $\times$ \ccc{yeps} centered at the original point.
Two random numbers are needed from \ccc{rnd} for each point. Two random numbers are needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the value type of \ccPrecond \ccc{Creator} must be a function object accepting two
the \ccc{ForwardIterator} exists. \ccc{double} values $x$ and $y$ and returning an initialized point
\ccc{(x,y)} of type \ccc{P}. Predifined implementations for these
creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. The \ccc{value_type} of the
\ccc{ForwardIterator} must be assignable to \ccc{P}.
\ccc{P} is equal to the \ccc{value_type} of the
\ccc{ForwardIterator} when using the default initializer.
The expressions \ccc{CGAL_to_double((*first).x())} and The expressions \ccc{CGAL_to_double((*first).x())} and
\ccc{CGAL_to_double((*first).y())} must result in the respective \ccc{CGAL_to_double((*first).y())} must result in the respective
coordinate values. coordinate values.
@ -252,23 +297,33 @@ Section~\ref{sectionRandomSelection}. The
a point set. a point set.
\def\ccLongParamLayout{\ccTrue}
\ccFunction{template <class RandomAccessIterator, class OutputIterator> \ccFunction{template <class RandomAccessIterator, class OutputIterator>
OutputIterator CGAL_random_collinear_points_2( RandomAccessIterator first, OutputIterator CGAL_random_collinear_points_2( RandomAccessIterator first,
RandomAccessIterator last, RandomAccessIterator last,
size_t n, OutputIterator first2, CGAL_Random& rnd = CGAL_random);} size_t n, OutputIterator first2, CGAL_Random& rnd = CGAL_random,
Creator creator = CGAL_Creator_uniform_2<double,P>);}
{ randomly chooses two points from the range $[\ccc{first},\ccc{last})$, { randomly chooses two points from the range $[\ccc{first},\ccc{last})$,
creates a random third point on the segment connecting this two creates a random third point on the segment connecting this two
points, and writes it to \ccc{first2}. Repeats this $n$ times, thus points, writes it to \ccc{first2}, and repeats this $n$ times, thus
writing $n$ points to \ccc{first2} that are collinear with points writing $n$ points to \ccc{first2} that are collinear with points
in the range $[\ccc{first},\ccc{last})$. in the range $[\ccc{first},\ccc{last})$.
Three random numbers are needed from \ccc{rnd} for each point. Three random numbers are needed from \ccc{rnd} for each point.
Returns the value of \ccc{first2} after inserting the $n$ points. Returns the value of \ccc{first2} after inserting the $n$ points.
\ccPrecond a function \ccc{CGAL_build_point()} for the value type of \ccPrecond \ccc{Creator} must be a function object accepting two
the \ccc{ForwardIterator} exists. \ccc{double} values $x$ and $y$ and returning an initialized point
\ccc{(x,y)} of type \ccc{P}. Predifined implementations for these
creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. The \ccc{value_type} of the
\ccc{RandomAccessIterator} must be assignable to \ccc{P}.
\ccc{P} is equal to the \ccc{value_type} of the
\ccc{RandomAccessIterator} when using the default initializer.
The expressions \ccc{CGAL_to_double((*first).x())} and The expressions \ccc{CGAL_to_double((*first).x())} and
\ccc{CGAL_to_double((*first).y())} must result in the respective \ccc{CGAL_to_double((*first).y())} must result in the respective
coordinate values. coordinate values.
} }
\def\ccLongParamLayout{\ccFalse}
\ccExample \ccExample
@ -343,47 +398,96 @@ for the example output.
% +------------------------------------------------------------------------+ % +------------------------------------------------------------------------+
\newpage \newpage
\section{2D Segment Generators} \section{3D Point Generators}
The following generic segment generator uses two point generators to One kind of point generators is currently provided: Random point
create a segment from two endpoints. This is a design example how generators implemented as input iterators. The input iterators model
further generators could look like -- for segments and for other an infinite sequence of points. The function \ccc{CGAL_copy_n()} could
higher level objects. be used to copy a finite sequence, see Section~\ref{sectionCopyN}. The
iterator adaptor \ccc{CGAL_Counting_iterator} can be used to create
finite iterator ranges, see Section~\ref{sectionCountingIterator}.
% +------------------------------------------------------------------------+ % +------------------------------------------------------------------------+
\begin{ccClassTemplate}{CGAL_Segment_generator<S,P1,P2>} \subsection{Point Generators as Input Iterators}
\ccCreationVariable{g}
\subsection{A Generic Segment Generator from Two Points}
\ccDefinition \ccDefinition
The generic segment generator \ccClassTemplateName\ uses two point Input iterators are provided for random points uniformly distributed
generators \ccc{P1} and \ccc{P2} to create a segment of type $S$ from in a three-dimensional volume (sphere or cube) or a two-dimensional
two endpoints. \ccClassTemplateName\ satisfies the requirements for surface (boundary of a sphere).
an input iterator. It represents the possibly infinite sequence of
generated segments. Each call to the \ccc{operator*} returns a new
segment. To create a finite sequence in a container, the function
\ccc{CGAL_copy_n()} could be used, see Section~\ref{sectionCopyN}.
\ccInclude{CGAL/Segment_generator.h} All iterators are parameterized with the point type \ccc{P} and a second
template argument \ccc{Creator} which defaults to
\ccc{CGAL_Creator_uniform_3<double,P>}\footnote{%
For compilers not supporting these kind of default arguments, both
template arguments must be provided when using these generators.}.
The \ccc{Creator} must be a function object accepting three
\ccc{double} values $x$, $y$ and $z$ and returning an initialized
point \ccc{(x,y,z)} of type \ccc{P}. Predifined implementations for
these creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. They simply assume an
appropriate constructor for type \ccc{P}.
All generators know a range within which the coordinates of the
generated points will lie.
\ccInclude{CGAL/point_generators_3.h}
\ccTypes
The generators comply to the requirements of input iterators which
includes local type declarations including \ccc{value_type} which
denotes \ccc{P} here.
\ccCreation \ccCreation
\ccConstructor{CGAL_Segment_generator( P1& p1, P2& p2);}{%
$g$ is an input iterator creating segments of type \ccc{S} from two
input points, one chosen from \ccc{p1}, the other chosen from
\ccc{p2}. \ccc{p1} and \ccc{p2} are allowed be be same point
generator.\ccPrecond $S$ must provide a constructor with two
arguments, such that the value type of \ccc{P1} and the
value type of \ccc{P2} can be used to construct a segment.}
\ccOperations \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_sphere_3<P,Creator>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_sphere_3( double r, CGAL_Random& rnd =
CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly
distributed in the open sphere with radius $r$,
i.e.~$|\ccc{*g}| < r$~.
}
\end{ccClassTemplate}
$g$ satisfies the requirements of an input iterator. Each call to the \ccHtmlNoClassFile
\ccc{operator*} returns a new segment. \begin{ccClassTemplate}{CGAL_Random_points_on_sphere_3<P,Creator>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_sphere_3( double r, CGAL_Random& rnd =
CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly
distributed on the boundary of a sphere with radius $r$,
i.e.~$|\ccc{*g}| == r$~. Two random numbers are needed from
\ccc{rnd} for each point.
}
\end{ccClassTemplate}
\ccExample \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_cube_3<P,Creator>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_cube_3( double a, CGAL_Random& rnd =
CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly
distributed in the half-open cube with side length $2 a$, centered
at the origin, i.e.~$\forall p = \ccc{*g}: -a \le p.x(),p.y(),p.z() < a$~.
Three random numbers are needed from \ccc{rnd} for each point.
}
\end{ccClassTemplate}
% +------------------------------------------------------------------------+
\newpage
\section{Examples Generating Segments}
The following two examples illustrate the use of the generic functions
from Section~\ref{sectionGenericFunctions} like
\ccc{CGAL_Join_input_iterator} to generate composed objects from other
generators -- here two-dimensional segments from two point generators.
We want to generate a test set of 200 segments, where one endpoint is We want to generate a test set of 200 segments, where one endpoint is
chosen randomly from a horizontal segment of length 200, and the other chosen randomly from a horizontal segment of length 200, and the other
@ -397,16 +501,16 @@ output.
\begin{figure} \begin{figure}
\noindent \noindent
\hspace*{0.025\textwidth}% \hspace*{0.025\textwidth}%
\begin{minipage}{0.45\textwidth}% \begin{minipage}[t]{0.45\textwidth}%
\epsfig{figure=Segment_generator_prog1.ps,width=\textwidth} \epsfig{figure=Segment_generator_prog1.ps,width=\textwidth}
\caption{Output of example program for the generic segment generator.} \caption{Output of the first example program for the generic generator.}
\label{figureSegmentGenerator} \label{figureSegmentGenerator}
\end{minipage}% \end{minipage}%
\hspace*{0.05\textwidth}% \hspace*{0.05\textwidth}%
\begin{minipage}{0.45\textwidth}% \begin{minipage}[t]{0.45\textwidth}%
\epsfig{figure=Segment_generator_prog2.ps,width=\textwidth} \epsfig{figure=Segment_generator_prog2.ps,width=\textwidth}
\caption{Output of example program for the generic segment \caption{Output of the second example program for the generic
generator using precomputed point locations.} generator without using intermediate storage.}
\label{figureSegmentGeneratorFan} \label{figureSegmentGeneratorFan}
\end{minipage}% \end{minipage}%
\end{figure} \end{figure}
@ -427,12 +531,14 @@ output.
</TD></TR></TABLE> </TD></TR></TABLE>
\end{ccHtmlOnly} \end{ccHtmlOnly}
The second example uses precomputed point vectors to generate a The second example generates a regular structure of 100 segments, see
regular structure of 100 segments, see
\ccTexHtml{Figure~\ref{figureSegmentGeneratorFan}}{Figure <A \ccTexHtml{Figure~\ref{figureSegmentGeneratorFan}}{Figure <A
HREF="#SegmentGeneratorFan"> <IMG SRC="cc_ref_up_arrow.gif" HREF="#SegmentGeneratorFan"> <IMG SRC="cc_ref_up_arrow.gif"
ALT="reference arrow" WIDTH="10" HEIGHT="10"></A>} for the example ALT="reference arrow" WIDTH="10" HEIGHT="10"></A>} for the example
output. output. It uses the \ccc{CGAL_Points_on_segment_2} iterator,
\ccc{CGAL_Join_input_iterator_2} and \ccc{CGAL_Counting_iterator} to
avoid any intermediate storage of the generated objects until they are
used, in this example copied to a windowstream.
\cprogfile{Segment_generator_prog2.C} \cprogfile{Segment_generator_prog2.C}
@ -450,8 +556,6 @@ output.
</TD></TR></TABLE> </TD></TR></TABLE>
\end{ccHtmlOnly} \end{ccHtmlOnly}
\end{ccClassTemplate}
% +--------------------------------------------------------+ % +--------------------------------------------------------+
\beforecprogskip\parskip \beforecprogskip\parskip
\aftercprogskip0pt \aftercprogskip0pt

View File

@ -10,13 +10,15 @@
#include <CGAL/Point_2.h> #include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h> #include <CGAL/Segment_2.h>
#include <CGAL/point_generators_2.h> #include <CGAL/point_generators_2.h>
#include <CGAL/Segment_generator.h> #include <CGAL/function_objects.h>
#include <CGAL/Join_input_iterator.h>
#include <CGAL/copy_n.h> #include <CGAL/copy_n.h>
#include <CGAL/IO/Window_stream.h> /* only for visualization used */ #include <CGAL/IO/Window_stream.h> /* only for visualization used */
typedef CGAL_Cartesian<double> R; typedef CGAL_Cartesian<double> R;
typedef CGAL_Point_2<R> Point; typedef CGAL_Point_2<R> Point;
typedef CGAL_Segment_2<R> Segment; typedef CGAL_Creator_uniform_2<double,Point> Pt_creator;
typedef CGAL_Segment_2<R> Segment;
int main() int main()
{ {
@ -25,15 +27,17 @@ int main()
segs.reserve(200); segs.reserve(200);
/* Prepare point generator for the horizontal segment, length 200. */ /* Prepare point generator for the horizontal segment, length 200. */
typedef CGAL_Random_points_on_segment_2<Point> P1; typedef CGAL_Random_points_on_segment_2<Point,Pt_creator> P1;
P1 p1( Point(-100,0), Point(100,0)); P1 p1( Point(-100,0), Point(100,0));
/* Prepare point generator for random points on circle, radius 250. */ /* Prepare point generator for random points on circle, radius 250. */
typedef CGAL_Random_points_on_circle_2<Point> P2; typedef CGAL_Random_points_on_circle_2<Point,Pt_creator> P2;
P2 p2( 250); P2 p2( 250);
/* Create 200 segments. */ /* Create 200 segments. */
CGAL_Segment_generator<Segment, P1, P2> g( p1, p2); typedef CGAL_Creator_uniform_2< Point, Segment> Seg_creator;
typedef CGAL_Join_input_iterator_2< P1, P2, Seg_creator> Seg_iterator;
Seg_iterator g( p1, p2);
CGAL_copy_n( g, 200, back_inserter( segs)); CGAL_copy_n( g, 200, back_inserter( segs));
/* Visualize segments. Can be omitted, see example programs */ /* Visualize segments. Can be omitted, see example programs */

View File

@ -1,65 +1,55 @@
/* Segment_generator_prog2.C */ /* Segment_generator_prog2.C */
/* ------------------------------- */ /* ------------------------------- */
/* CGAL example program for the generic segment generator */ /* CGAL example program generating a regular segment pattern. */
/* using precomputed point locations. */
#include <CGAL/basic.h> #include <CGAL/basic.h>
#include <assert.h>
#include <vector.h>
#include <algo.h> #include <algo.h>
#include <CGAL/Cartesian.h> #include <CGAL/Cartesian.h>
#include <CGAL/Point_2.h> #include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h> #include <CGAL/Segment_2.h>
#include <CGAL/point_generators_2.h> #include <CGAL/point_generators_2.h>
#include <CGAL/Segment_generator.h> #include <CGAL/function_objects.h>
#include <CGAL/copy_n.h> #include <CGAL/Join_input_iterator.h>
#include <CGAL/IO/Window_stream.h> /* only for visualization used */ #include <CGAL/Counting_iterator.h>
#include <CGAL/IO/Ostream_iterator.h>
#include <CGAL/IO/Window_stream.h>
typedef CGAL_Cartesian<double> R;
typedef CGAL_Point_2<R> Point;
typedef CGAL_Segment_2<R> Segment;
typedef CGAL_Points_on_segment_2<Point> PG;
typedef CGAL_Creator_uniform_2< Point, Segment> Creator;
typedef CGAL_Join_input_iterator_2< PG, PG, Creator> Segm_iterator;
typedef CGAL_Counting_iterator<Segm_iterator,Segment> Count_iterator;
typedef CGAL_Cartesian<double> R;
typedef CGAL_Point_2<R> Point;
typedef CGAL_Segment_2<R> Segment;
int main() int main()
{ {
/* Prepare two point vectors for the precomputed points. */ /* Open window. */
vector<Point> p1, p2;
p1.reserve(100);
p2.reserve(100);
/* Create points for a horizontal like fan. */
CGAL_points_on_segment_2( Point(-250, -50), Point(-250, 50),
50, back_inserter( p1));
CGAL_points_on_segment_2( Point( 250,-250), Point( 250,250),
50, back_inserter( p2));
/* Create points for a vertical like fan. */
CGAL_points_on_segment_2( Point( -50,-250), Point( 50,-250),
50, back_inserter( p1));
CGAL_points_on_segment_2( Point(-250, 250), Point( 250, 250),
50, back_inserter( p2));
/* Create test segment set. Prepare a vector for 100 segments. */
vector<Segment> segs;
segs.reserve(100);
/* Create both fans at once from the precomputed points. */
typedef vector<Point>::iterator I;
I i1 = p1.begin();
I i2 = p2.begin();
CGAL_Segment_generator<Segment,I,I> g( i1, i2);
CGAL_copy_n( g, 100, back_inserter( segs));
/* Visualize segments. Can be omitted, see example programs */
/* in the CGAL source code distribution. */
CGAL_Window_stream W(512, 512); CGAL_Window_stream W(512, 512);
W.init(-256.0, 255.0, -256.0); W.init(-256.0, 255.0, -256.0);
W << CGAL_BLACK; W << CGAL_BLACK;
for( vector<Segment>::iterator i = segs.begin(); i != segs.end(); i++)
W << *i; /* A horizontal like fan. */
PG p1( Point(-250, -50), Point(-250, 50),50); /* Point generator. */
PG p2( Point( 250,-250), Point( 250,250),50);
Segm_iterator t1( p1, p2); /* Segment generator. */
Count_iterator t1_begin( t1); /* Finite range. */
Count_iterator t1_end( 50);
copy( t1_begin, t1_end,
CGAL_Ostream_iterator<Segment,CGAL_Window_stream>(W));
/* A vertical like fan. */
PG p3( Point( -50,-250), Point( 50,-250),50);
PG p4( Point(-250, 250), Point( 250, 250),50);
Segm_iterator t2( p3, p4);
Count_iterator t2_begin( t2);
Count_iterator t2_end( 50);
copy( t2_begin, t2_end,
CGAL_Ostream_iterator<Segment,CGAL_Window_stream>(W));
/* Wait for mouse click in window. */ /* Wait for mouse click in window. */
Point p; Point p;
W >> p; W >> p;
return 0; return 0;
} }

View File

@ -26,10 +26,15 @@ e.g.~for testing algorithms on degenerate object sets and for
performance analysis. performance analysis.
The first section describes the random number source used for random The first section describes the random number source used for random
generators. The second section documents generators for point sets, generators. The second section provides useful generic functions
the third section for segments. Note that the \stl\ algorithm related to random numbers like \ccc{CGAL_random_selection()}. The
\ccc{random_shuffle} is useful in this context to achieve random third section documents generators for two-dimensional point sets, the
permutations (e.g.~for points on a grid). fourth section for three-dimensional point sets. The fifth section
presents examples using functions from
Section~\ref{sectionGenericFunctions} to generate composed objects
like segments. Note that the \stl\ algorithm \ccc{random_shuffle} is
useful in this context to achieve random permutations for otherwise
regular generators (e.g.~points on a grid or segment).
% +------------------------------------------------------------------------+ % +------------------------------------------------------------------------+
@ -40,28 +45,14 @@ permutations (e.g.~for points on a grid).
\section{Support Functions for Generators} \section{Support Functions for Generators}
\ccThree{OutputIterator}{rand}{} \ccThree{OutputIterator}{rand}{}
Two support functions are provided. \ccc{CGAL_copy_n()} copies $n$
items from an input iterator to an output iterator which is useful for
possibly infinite sequences of random geometric objects\footnote{%
The STL release June 13, 1997, from SGI has a new function \ccc{copy_n} which is equivalent with \ccc{CGAL_copy_n}.}.
\ccc{CGAL_random_selection} chooses $n$ items at random from a random
access iterator range which is useful to produce degenerate input data
sets with multiple entries of identical items.
\subsection{{\it CGAL\_copy\_n()}}
\label{sectionCopyN}
\ccInclude{CGAL/copy_n.h}
\ccFunction{template <class InputIterator, class Size, class OutputIterator>
OutputIterator CGAL_copy_n( InputIterator first, Size n,
OutputIterator result);}
{copies the first $n$ items from \ccc{first} to \ccc{result}.
Returns the value of \ccc{result} after inserting the $n$ items.}
\subsection{{\it CGAL\_random\_selection()}} \subsection{{\it CGAL\_random\_selection()}}
\label{sectionRandomSelection} \label{sectionRandomSelection}
\ccc{CGAL_random_selection} chooses $n$ items at random from a random
access iterator range which is useful to produce degenerate input data
sets with multiple entries of identical items.
\ccInclude{CGAL/random_selection.h} \ccInclude{CGAL/random_selection.h}
\ccFunction{template <class RandomAccessIterator, class Size, \ccFunction{template <class RandomAccessIterator, class Size,
@ -69,9 +60,9 @@ sets with multiple entries of identical items.
OutputIterator CGAL_random_selection( RandomAccessIterator first, OutputIterator CGAL_random_selection( RandomAccessIterator first,
RandomAccessIterator last, RandomAccessIterator last,
Size n, OutputIterator result, Random& rnd = CGAL_random);} Size n, OutputIterator result, Random& rnd = CGAL_random);}
{ choose a random item from the range $[\ccc{first},\ccc{last})$ and { chooses a random item from the range $[\ccc{first},\ccc{last})$ and
write it to \ccc{result}, each item from the range with equal writes it to \ccc{result}, each item from the range with equal
probability. Repeat this $n$ times, thus writing $n$ items to probability, and repeats this $n$ times, thus writing $n$ items to
\ccc{result}. \ccc{result}.
A single random number is needed from \ccc{rnd} for each item. A single random number is needed from \ccc{rnd} for each item.
Returns the value of \ccc{result} after inserting the $n$ items. Returns the value of \ccc{result} after inserting the $n$ items.
@ -85,48 +76,56 @@ sets with multiple entries of identical items.
\newpage \newpage
\section{2D Point Generators} \section{2D Point Generators}
Two kind of point generators are provided: First, random point
generators and second deterministic point generators. Most random
point generators and a few deterministic point generators are provided
as input iterators. The input iterators model an infinite sequence of
points. The function \ccc{CGAL_copy_n()} could be used to copy a
finite sequence, see Section~\ref{sectionCopyN}. The iterator adaptor
\ccc{CGAL_Counting_iterator} can be used to create finite iterator
ranges, see Section~\ref{sectionCountingIterator}.
Other generators are provided as functions writing to an output
iterator. Further functions add degeneracies or random perturbations.
% +------------------------------------------------------------------------+
\subsection{Point Generators as Input Iterators}
\ccDefinition \ccDefinition
Point generators are provided for random points uniformly distributed Input iterators are provided for random points uniformly distributed
over a two-dimensional domain (square or disc) or a one-dimensional over a two-dimensional domain (square or disc) or a one-dimensional
domain (boundary of a square, circle, or segment). Other point domain (boundary of a square, circle, or segment). Another input
generators create two-dimensional grids or equally spaced points on a iterator generates equally spaced points from a segment.
segment. A perturbation function adds random noise to a given set of
points. Several functions add degeneracies: the duplication of randomly
chosen points and the construction of a collinear point between two randomly
chosen points from a set of points.
All iterators are parameterized with the point type \ccc{P} and all
with the exception of \ccc{CGAL_Points_on_segment_2} have a second
template argument \ccc{Creator} which defaults to
\ccc{CGAL_Creator_uniform_2<double,P>}\footnote{%
For compilers not supporting these kind of default arguments, both
template arguments must be provided when using these generators.}.
The \ccc{Creator} must be a function object accepting two \ccc{double}
values $x$ and $y$ and returning an initialized point \ccc{(x,y)} of type
\ccc{P}. Predifined implementations for these creators like the
default can be found in Section~\ref{sectionCreatorFunctionObjects}.
They simply assume an appropriate constructor for type \ccc{P}.
All generators know a range within which the coordinates of the
generated points will lie.
\ccInclude{CGAL/point_generators_2.h} \ccInclude{CGAL/point_generators_2.h}
\ccTypes
The generators comply to the requirements of input iterators which
includes local type declarations including \ccc{value_type} which
denotes \ccc{P} here.
\ccCreation \ccCreation
The random point generators build two-dimensional points from a pair
of \ccc{double}'s. Depending on the point representation and
arithmetic, a different building process is necessary. It is
encapsulated in the global function \ccc{CGAL_build_point()}.
Implementations exist for \ccc{CGAL_Cartesian<double>} and
\ccc{CGAL_Cartesian<float>}. They are automatically included if the
representation type \ccc{CGAL_Cartesian} has been included beforehand.
For other representations and arithmetic types the function can be
overloaded.
\ccThree{void}{random}{}
\ccFunction{void CGAL_build_point( double x, double y, Point&
p);}{builds a point $(x,y)$ in $p$. \ccc{Point} is the point type in
question.}
\ccHeading{Random Points}
The random point generators are implemented as classes that satisfies
the requirements for input iterators. They represent the possibly
infinite sequence of randomly generated points. Each call to the
\ccc{operator*} returns a new point. To create a finite sequence in a
container, the function \ccc{CGAL_copy_n()} could be used, see
Section~\ref{sectionCopyN}.
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_disc_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_in_disc_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_disc_2( double r, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_in_disc_2( double r, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
@ -134,12 +133,11 @@ Section~\ref{sectionCopyN}.
distributed in the open disc with radius $r$, distributed in the open disc with radius $r$,
i.e.~$|\ccc{*g}| < r$~. Two random numbers are needed from i.e.~$|\ccc{*g}| < r$~. Two random numbers are needed from
\ccc{rnd} for each point. \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_on_circle_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_on_circle_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_circle_2( double r, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_on_circle_2( double r, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
@ -147,76 +145,116 @@ Section~\ref{sectionCopyN}.
distributed on the circle with radius $r$, distributed on the circle with radius $r$,
i.e.~$|\ccc{*g}| == r$~. A single random number is needed from i.e.~$|\ccc{*g}| == r$~. A single random number is needed from
\ccc{rnd} for each point. \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_square_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_in_square_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_square_2( double a, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_in_square_2( double a, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly $g$ is an input iterator creating points of type \ccc{P} uniformly
distributed in the half-open square with side length $a$, centered distributed in the half-open square with side length $2 a$, centered
at the origin, i.e.~$\forall p = \ccc{*g}: -\frac{a}{2} \le at the origin, i.e.~$\forall p = \ccc{*g}: -a \le p.x() < a$ and
p.x() < \frac{a}{2}$ and $-\frac{a}{2} \le p.y() < \frac{a}{2}$~. $-a \le p.y() < a$~.
Two random numbers are needed from \ccc{rnd} for each point. Two random numbers are needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_on_square_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_on_square_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_square_2( double a, CGAL_Random& rnd = \ccConstructor{CGAL_Random_points_on_square_2( double a, CGAL_Random& rnd =
CGAL_random);}{% CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly $g$ is an input iterator creating points of type \ccc{P} uniformly
distributed on the boundary of the square with side length $a$, distributed on the boundary of the square with side length $2 a$,
centered at the origin, i.e.~$\forall p = \ccc{*g}:$ one centered at the origin, i.e.~$\forall p = \ccc{*g}:$ one
coordinate is either $\frac{a}{2}$ or $-\frac{a}{2}$ and for the coordinate is either $a$ or $-a$ and for the
other coordinate $c$ holds $-\frac{a}{2} \le c < \frac{a}{2}$~. other coordinate $c$ holds $-a \le c < a$~.
A single random number is needed from \ccc{rnd} for each point. A single random number is needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type }
\ccc{P} exists.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_on_segment_2<P>} \begin{ccClassTemplate}{CGAL_Random_points_on_segment_2<P,Creator>}
\ccCreationVariable{g} \ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_segment_2( const P& p, const P& q, \ccConstructor{CGAL_Random_points_on_segment_2( const P& p, const P& q,
CGAL_Random& rnd = CGAL_random);}{% CGAL_Random& rnd = CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly $g$ is an input iterator creating points of type \ccc{P} uniformly
distributed on the segment from $p$ to $q$ except $q$, distributed on the segment from $p$ to $q$ (excluding $q$),
i.e.~$\ccc{*g} == (1-\lambda)\, p + \lambda q$ where $0 \le \lambda < 1$~. i.e.~$\ccc{*g} == (1-\lambda)\, p + \lambda q$ where $0 \le \lambda < 1$~.
A single random number is needed from \ccc{rnd} for each point. A single random number is needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type \ccc{P} \ccPrecond The expressions \ccc{CGAL_to_double(p.x())} and
exists. The expressions \ccc{CGAL_to_double(p.x())} and
\ccc{CGAL_to_double(p.y())} must result in the respective \ccc{CGAL_to_double(p.y())} must result in the respective
\ccc{double} representation of the coordinates and similar for $q$.} \ccc{double} representation of the coordinates and similar for $q$.}
\end{ccClassTemplate} \end{ccClassTemplate}
\ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Points_on_segment_2<P>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Points_on_segment_2( const P& p, const P& q,
size_t n, size_t i = 0);}{%
$g$ is an input iterator creating points of type \ccc{P} equally
spaced on the segment from $p$ to $q$. $n$ points are placed on the
segment including $p$ and $q$. The iterator denoted the point $i$
where $p$ has the index 0 and $q$ the index $n$.
\ccPrecond The expressions \ccc{CGAL_to_double(p.x())} and
\ccc{CGAL_to_double(p.y())} must result in the respective
\ccc{double} representation of the coordinates and similar for $q$.}
\ccOperations
\ccThree{double}{g.source();}{}
\ccMethod{double range();}{returns the range in which the point
coordinates lie, i.e.~$\forall x: |x| \leq $\ccc{range()} and
$\forall y: |y| \leq $\ccc{range()}.}
The generators \ccc{CGAL_Random_points_on_segment_2} and
\ccc{CGAL_Points_on_segment_2} have to additional methods.
\ccMethod{const P& source();}{returns the source point of the segment.}
\ccGlue
\ccMethod{const P& target();}{returns the target point of the segment.}
\end{ccClassTemplate}
% +------------------------------------------------------------------------+
\subsection{Point Generators as Functions}
\ccHeading{Grid Points} \ccHeading{Grid Points}
\ccThree{OutputIterator}{rand}{} \ccThree{OutputIterator}{rand}{}
Grid points are produced by generating functions writing to an output Grid points are generated by functions writing to an output iterator.
iterator.
\ccFunction{template <class OutputIterator> \def\ccLongParamLayout{\ccTrue}
\ccFunction{template <class OutputIterator, Creator creator>
OutputIterator OutputIterator
CGAL_points_on_square_grid_2( double a, size_t n, OutputIterator o, CGAL_points_on_square_grid_2( double a, size_t n, OutputIterator o,
const P*);} const P*, Creator creator =
CGAL_Creator_uniform_2<double,P>);}
{ creates the $n$ first points on the regular $\lceil\sqrt{n}\,\rceil { creates the $n$ first points on the regular $\lceil\sqrt{n}\,\rceil
\times \lceil \sqrt{n}\,\rceil$ grid within the square \times \lceil \sqrt{n}\,\rceil$ grid within the square
$[-\frac{a}{2},\frac{a}{2}]\times [-\frac{a}{2},\frac{a}{2}]$. $[-a,a]\times [-a,a]$. Returns the value of $o$ after inserting
Returns the value of $o$ after inserting the $n$ points. the $n$ points.
\ccPrecond a function \ccc{CGAL_build_point()} for the point type \ccPrecond \ccc{Creator} must be a function object accepting two
$P$ and $P$ must be assignable to the value type of \ccc{double} values $x$ and $y$ and returning an initialized point
\ccc{OutputIterator}.} \ccc{(x,y)} of type \ccc{P}. Predifined implementations for these
creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. The
\ccc{OutputIterator} must accept values of type \ccc{P}. If the
\ccc{OutputIterator} has a \ccc{value_type} the default
initializer of the \ccc{creator} can be used. \ccc{P} is set to
the \ccc{value_type} in this case.}
\def\ccLongParamLayout{\ccFalse}
\ccFunction{template <class P, class OutputIterator> \ccFunction{template <class P, class OutputIterator>
OutputIterator CGAL_points_on_segment_2( const P& p, const P& q, size_t n, OutputIterator CGAL_points_on_segment_2( const P& p, const P& q, size_t n,
OutputIterator o);} OutputIterator o);}
{ creates $n$ points regular spaced on the segment from $p$ to $q$, { creates $n$ points equally spaced on the segment from $p$ to $q$,
i.e.~$\forall i: 0 \le i < n: o[i] := \frac{n-i-1}{n-1}\, p + i.e.~$\forall i: 0 \le i < n: o[i] := \frac{n-i-1}{n-1}\, p +
\frac{i}{n-1}\, q$. Returns the value of $o$ after inserting \frac{i}{n-1}\, q$. Returns the value of $o$ after inserting
the $n$ points.} the $n$ points.}
@ -230,13 +268,20 @@ exact predicates to compute the sign of expressions slightly off from zero.
\ccFunction{template <class ForwardIterator> \ccFunction{template <class ForwardIterator>
void CGAL_perturb_points_2( ForwardIterator first, ForwardIterator last, void CGAL_perturb_points_2( ForwardIterator first, ForwardIterator last,
double xeps, double yeps = xeps, CGAL_Random& rnd = CGAL_random);} double xeps, double yeps = xeps, CGAL_Random& rnd = CGAL_random,
Creator creator = CGAL_Creator_uniform_2<double,P>);}
{ perturbs the points in the range $[\ccc{first},\ccc{last})$ by { perturbs the points in the range $[\ccc{first},\ccc{last})$ by
replacing each point with a random point from the rectangle replacing each point with a random point from the rectangle
\ccc{xeps} $\times$ \ccc{yeps} centered at the original point. \ccc{xeps} $\times$ \ccc{yeps} centered at the original point.
Two random numbers are needed from \ccc{rnd} for each point. Two random numbers are needed from \ccc{rnd} for each point.
\ccPrecond a function \ccc{CGAL_build_point()} for the value type of \ccPrecond \ccc{Creator} must be a function object accepting two
the \ccc{ForwardIterator} exists. \ccc{double} values $x$ and $y$ and returning an initialized point
\ccc{(x,y)} of type \ccc{P}. Predifined implementations for these
creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. The \ccc{value_type} of the
\ccc{ForwardIterator} must be assignable to \ccc{P}.
\ccc{P} is equal to the \ccc{value_type} of the
\ccc{ForwardIterator} when using the default initializer.
The expressions \ccc{CGAL_to_double((*first).x())} and The expressions \ccc{CGAL_to_double((*first).x())} and
\ccc{CGAL_to_double((*first).y())} must result in the respective \ccc{CGAL_to_double((*first).y())} must result in the respective
coordinate values. coordinate values.
@ -252,23 +297,33 @@ Section~\ref{sectionRandomSelection}. The
a point set. a point set.
\def\ccLongParamLayout{\ccTrue}
\ccFunction{template <class RandomAccessIterator, class OutputIterator> \ccFunction{template <class RandomAccessIterator, class OutputIterator>
OutputIterator CGAL_random_collinear_points_2( RandomAccessIterator first, OutputIterator CGAL_random_collinear_points_2( RandomAccessIterator first,
RandomAccessIterator last, RandomAccessIterator last,
size_t n, OutputIterator first2, CGAL_Random& rnd = CGAL_random);} size_t n, OutputIterator first2, CGAL_Random& rnd = CGAL_random,
Creator creator = CGAL_Creator_uniform_2<double,P>);}
{ randomly chooses two points from the range $[\ccc{first},\ccc{last})$, { randomly chooses two points from the range $[\ccc{first},\ccc{last})$,
creates a random third point on the segment connecting this two creates a random third point on the segment connecting this two
points, and writes it to \ccc{first2}. Repeats this $n$ times, thus points, writes it to \ccc{first2}, and repeats this $n$ times, thus
writing $n$ points to \ccc{first2} that are collinear with points writing $n$ points to \ccc{first2} that are collinear with points
in the range $[\ccc{first},\ccc{last})$. in the range $[\ccc{first},\ccc{last})$.
Three random numbers are needed from \ccc{rnd} for each point. Three random numbers are needed from \ccc{rnd} for each point.
Returns the value of \ccc{first2} after inserting the $n$ points. Returns the value of \ccc{first2} after inserting the $n$ points.
\ccPrecond a function \ccc{CGAL_build_point()} for the value type of \ccPrecond \ccc{Creator} must be a function object accepting two
the \ccc{ForwardIterator} exists. \ccc{double} values $x$ and $y$ and returning an initialized point
\ccc{(x,y)} of type \ccc{P}. Predifined implementations for these
creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. The \ccc{value_type} of the
\ccc{RandomAccessIterator} must be assignable to \ccc{P}.
\ccc{P} is equal to the \ccc{value_type} of the
\ccc{RandomAccessIterator} when using the default initializer.
The expressions \ccc{CGAL_to_double((*first).x())} and The expressions \ccc{CGAL_to_double((*first).x())} and
\ccc{CGAL_to_double((*first).y())} must result in the respective \ccc{CGAL_to_double((*first).y())} must result in the respective
coordinate values. coordinate values.
} }
\def\ccLongParamLayout{\ccFalse}
\ccExample \ccExample
@ -343,47 +398,96 @@ for the example output.
% +------------------------------------------------------------------------+ % +------------------------------------------------------------------------+
\newpage \newpage
\section{2D Segment Generators} \section{3D Point Generators}
The following generic segment generator uses two point generators to One kind of point generators is currently provided: Random point
create a segment from two endpoints. This is a design example how generators implemented as input iterators. The input iterators model
further generators could look like -- for segments and for other an infinite sequence of points. The function \ccc{CGAL_copy_n()} could
higher level objects. be used to copy a finite sequence, see Section~\ref{sectionCopyN}. The
iterator adaptor \ccc{CGAL_Counting_iterator} can be used to create
finite iterator ranges, see Section~\ref{sectionCountingIterator}.
% +------------------------------------------------------------------------+ % +------------------------------------------------------------------------+
\begin{ccClassTemplate}{CGAL_Segment_generator<S,P1,P2>} \subsection{Point Generators as Input Iterators}
\ccCreationVariable{g}
\subsection{A Generic Segment Generator from Two Points}
\ccDefinition \ccDefinition
The generic segment generator \ccClassTemplateName\ uses two point Input iterators are provided for random points uniformly distributed
generators \ccc{P1} and \ccc{P2} to create a segment of type $S$ from in a three-dimensional volume (sphere or cube) or a two-dimensional
two endpoints. \ccClassTemplateName\ satisfies the requirements for surface (boundary of a sphere).
an input iterator. It represents the possibly infinite sequence of
generated segments. Each call to the \ccc{operator*} returns a new
segment. To create a finite sequence in a container, the function
\ccc{CGAL_copy_n()} could be used, see Section~\ref{sectionCopyN}.
\ccInclude{CGAL/Segment_generator.h} All iterators are parameterized with the point type \ccc{P} and a second
template argument \ccc{Creator} which defaults to
\ccc{CGAL_Creator_uniform_3<double,P>}\footnote{%
For compilers not supporting these kind of default arguments, both
template arguments must be provided when using these generators.}.
The \ccc{Creator} must be a function object accepting three
\ccc{double} values $x$, $y$ and $z$ and returning an initialized
point \ccc{(x,y,z)} of type \ccc{P}. Predifined implementations for
these creators like the default can be found in
Section~\ref{sectionCreatorFunctionObjects}. They simply assume an
appropriate constructor for type \ccc{P}.
All generators know a range within which the coordinates of the
generated points will lie.
\ccInclude{CGAL/point_generators_3.h}
\ccTypes
The generators comply to the requirements of input iterators which
includes local type declarations including \ccc{value_type} which
denotes \ccc{P} here.
\ccCreation \ccCreation
\ccConstructor{CGAL_Segment_generator( P1& p1, P2& p2);}{%
$g$ is an input iterator creating segments of type \ccc{S} from two
input points, one chosen from \ccc{p1}, the other chosen from
\ccc{p2}. \ccc{p1} and \ccc{p2} are allowed be be same point
generator.\ccPrecond $S$ must provide a constructor with two
arguments, such that the value type of \ccc{P1} and the
value type of \ccc{P2} can be used to construct a segment.}
\ccOperations \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_sphere_3<P,Creator>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_sphere_3( double r, CGAL_Random& rnd =
CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly
distributed in the open sphere with radius $r$,
i.e.~$|\ccc{*g}| < r$~.
}
\end{ccClassTemplate}
$g$ satisfies the requirements of an input iterator. Each call to the \ccHtmlNoClassFile
\ccc{operator*} returns a new segment. \begin{ccClassTemplate}{CGAL_Random_points_on_sphere_3<P,Creator>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_on_sphere_3( double r, CGAL_Random& rnd =
CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly
distributed on the boundary of a sphere with radius $r$,
i.e.~$|\ccc{*g}| == r$~. Two random numbers are needed from
\ccc{rnd} for each point.
}
\end{ccClassTemplate}
\ccExample \ccHtmlNoClassFile
\begin{ccClassTemplate}{CGAL_Random_points_in_cube_3<P,Creator>}
\ccCreationVariable{g}
\ccConstructor{CGAL_Random_points_in_cube_3( double a, CGAL_Random& rnd =
CGAL_random);}{%
$g$ is an input iterator creating points of type \ccc{P} uniformly
distributed in the half-open cube with side length $2 a$, centered
at the origin, i.e.~$\forall p = \ccc{*g}: -a \le p.x(),p.y(),p.z() < a$~.
Three random numbers are needed from \ccc{rnd} for each point.
}
\end{ccClassTemplate}
% +------------------------------------------------------------------------+
\newpage
\section{Examples Generating Segments}
The following two examples illustrate the use of the generic functions
from Section~\ref{sectionGenericFunctions} like
\ccc{CGAL_Join_input_iterator} to generate composed objects from other
generators -- here two-dimensional segments from two point generators.
We want to generate a test set of 200 segments, where one endpoint is We want to generate a test set of 200 segments, where one endpoint is
chosen randomly from a horizontal segment of length 200, and the other chosen randomly from a horizontal segment of length 200, and the other
@ -397,16 +501,16 @@ output.
\begin{figure} \begin{figure}
\noindent \noindent
\hspace*{0.025\textwidth}% \hspace*{0.025\textwidth}%
\begin{minipage}{0.45\textwidth}% \begin{minipage}[t]{0.45\textwidth}%
\epsfig{figure=Segment_generator_prog1.ps,width=\textwidth} \epsfig{figure=Segment_generator_prog1.ps,width=\textwidth}
\caption{Output of example program for the generic segment generator.} \caption{Output of the first example program for the generic generator.}
\label{figureSegmentGenerator} \label{figureSegmentGenerator}
\end{minipage}% \end{minipage}%
\hspace*{0.05\textwidth}% \hspace*{0.05\textwidth}%
\begin{minipage}{0.45\textwidth}% \begin{minipage}[t]{0.45\textwidth}%
\epsfig{figure=Segment_generator_prog2.ps,width=\textwidth} \epsfig{figure=Segment_generator_prog2.ps,width=\textwidth}
\caption{Output of example program for the generic segment \caption{Output of the second example program for the generic
generator using precomputed point locations.} generator without using intermediate storage.}
\label{figureSegmentGeneratorFan} \label{figureSegmentGeneratorFan}
\end{minipage}% \end{minipage}%
\end{figure} \end{figure}
@ -427,12 +531,14 @@ output.
</TD></TR></TABLE> </TD></TR></TABLE>
\end{ccHtmlOnly} \end{ccHtmlOnly}
The second example uses precomputed point vectors to generate a The second example generates a regular structure of 100 segments, see
regular structure of 100 segments, see
\ccTexHtml{Figure~\ref{figureSegmentGeneratorFan}}{Figure <A \ccTexHtml{Figure~\ref{figureSegmentGeneratorFan}}{Figure <A
HREF="#SegmentGeneratorFan"> <IMG SRC="cc_ref_up_arrow.gif" HREF="#SegmentGeneratorFan"> <IMG SRC="cc_ref_up_arrow.gif"
ALT="reference arrow" WIDTH="10" HEIGHT="10"></A>} for the example ALT="reference arrow" WIDTH="10" HEIGHT="10"></A>} for the example
output. output. It uses the \ccc{CGAL_Points_on_segment_2} iterator,
\ccc{CGAL_Join_input_iterator_2} and \ccc{CGAL_Counting_iterator} to
avoid any intermediate storage of the generated objects until they are
used, in this example copied to a windowstream.
\cprogfile{Segment_generator_prog2.C} \cprogfile{Segment_generator_prog2.C}
@ -450,8 +556,6 @@ output.
</TD></TR></TABLE> </TD></TR></TABLE>
\end{ccHtmlOnly} \end{ccHtmlOnly}
\end{ccClassTemplate}
% +--------------------------------------------------------+ % +--------------------------------------------------------+
\beforecprogskip\parskip \beforecprogskip\parskip
\aftercprogskip0pt \aftercprogskip0pt