970204 beta version

This commit is contained in:
Sven Schönherr 1997-02-06 10:13:59 +00:00
parent 95b971db9c
commit a0fea7a5c0
2 changed files with 248 additions and 206 deletions

View File

@ -2,7 +2,7 @@
% The CGAL Reference Manual % The CGAL Reference Manual
% Section: 2D Smallest Enclosing Circle % Section: 2D Smallest Enclosing Circle
% ----------------------------------------------------------------------------- % -----------------------------------------------------------------------------
% file : Min_circle_2.tex % file : spec/Min_circle_2.tex
% author: Bernd Gärtner, Sven Schönherr (sven@inf.fu-berlin.de) % author: Bernd Gärtner, Sven Schönherr (sven@inf.fu-berlin.de)
% $Id$ % $Id$
% ============================================================================= % =============================================================================
@ -12,32 +12,34 @@
\ccDefinition \ccDefinition
An object of the class \ccClassTemplateName\ is the unique smallest An object of the class \ccClassTemplateName\ is the unique circle of
enclosing circle of a set of points in two-dimensional euclidean space smallest area enclosing a finite set of points in two-dimensional
$\E_2$. For point sets $P$ and $B$ we denote by $\textit{mc}(P,B)$ euclidean space $\E_2$. For a point set $P$ we denote by $mc(P)$ the
the smallest circle that contains all points of $P$ and has (at least) smallest circle that contains all points of $P$. Note that $mc(P)$ can
the points of $B$ on the boundary. Note that $\textit{mc}(P,B)$ can be be degenerate, i.e.\ $P=$\ccTexHtml{$\emptyset$}{Ø} if
degenerate, i.e.\ $\textit{mc}(P,B) = \emptyset$ if $P \cup B = $P=$\ccTexHtml{$\emptyset$}{Ø} and $mc(P)=\{p\}$ if $P=\{p\}$.
\emptyset$ and $\textit{mc}(P,B) = \{p\}$ if $P \cup B = p$. If $B
\neq \emptyset$ then $\textit{mc}(P,B)$ may be undefined, i.e.\ there
is no circle containing $P$ with $B$ on the boundary.
The smallest enclosing circle of a point set $P$ is determined by at An inclusion-minimal subset $S$ of $P$ with $mc(S)=mc(P)$ is called
most three points on the boundary. A minimal subset $S$ of $P$ with a {\em support set}, the points in $S$ are the {\em support points}.
$\textit{mc}(S,\emptyset) = \textit{mc}(P,\emptyset)$ is called a A support set has size at most three, and all its points lie on the
\emph{support set}, the points in $S$ are the \emph{support points}. boundary of $mc(P)$.
Note that in general the set $S$ is not unique.
The underlying algorithm can cope with all kinds of input, e.g.\ one If $mc(P)$ has more than three points on the boundary,
or both of the point sets $P$ or $B$ may be empty, $B$ may contain neither the support set nor its size are necessarily unique.
more than three points, or some points may occure more than once in
$P$ or $B$. The algorithm computes a support set $S$, which remains
fixed until the next update operation.
The underlying algorithm can cope with all kinds of input, e.g.\
$P$ may be empty or points may occur more than once. The algorithm
computes a support set $S$ which remains fixed until the next insert
operation.
\ccCreation \ccCreation
\ccCreationVariable{min_circle} \ccCreationVariable{min_circle}
A \ccClassTemplateName\ object can be created from an arbitrary point
set $P$ and by specialized construction methods expecting no, one, two
or three points as arguments. The latter methods can be useful for
reconstructing $mc(P)$ from a given support set $S$ of $P$.
\ccSetThreeColumns{CGAL_Bounded_side}{}{ \ccSetThreeColumns{CGAL_Bounded_side}{}{
returns \ccStyle{CGAL_ON_BOUNDED_SIDE}, \ccStyle{CGAL_ON_BOUNDARY},} returns \ccStyle{CGAL_ON_BOUNDED_SIDE}, \ccStyle{CGAL_ON_BOUNDARY},}
\ccPropagateThreeToTwoColumns \ccPropagateThreeToTwoColumns
@ -46,161 +48,180 @@ fixed until the next update operation.
\ccConstructor{ CGAL_Min_circle_2( );}{ \ccConstructor{ CGAL_Min_circle_2( );}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to $\textit{mc}(\emptyset,\emptyset)$, It is initialized to
i.e.\ to the empty set. $mc($\ccTexHtml{$\emptyset$}{Ø}$)$, the empty set.
\ccPostcond \ccVar\ccStyle{.is_degenerate()}.} \ccPostcond \ccStyle{\ccVar.is_empty()} = \ccStyle{true}.}
\ccHidden \ccHidden
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Min_circle_2<R>& min_circle2);}{ \ccConstructor{ CGAL_Min_circle_2( const CGAL_Min_circle_2<R>&);}{
copy constructor.} copy constructor.}
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p);}{ \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to $\textit{mc}(\emptyset,\{\ccStyle{p}\})$, It is initialized to $mc(\{p\})$, the set $\{p\}$.
i.e.\ to the set $\{\ccStyle{p}\}$. \ccPostcond \ccStyle{\ccVar.is_degenerate()} = \ccStyle{true}.}
\ccPostcond \ccVar\ccStyle{.is_degenerate()}.}
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1, \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1,
const CGAL_Point_2<R>& p2);}{ const CGAL_Point_2<R>& p2);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to It is initialized to $mc(\{p1,p2\})$, the circle with diameter
$\textit{mc}(\emptyset,\{\ccStyle{p1},\ccStyle{p2}\})$, i.e.\ equal to the segment connecting $p1$ and $p2$.}
to the circle with diameter
$\overline{\ccStyle{p1}\ccStyle{p2}}$, if $\ccStyle{p1} \neq
\ccStyle{p2}$, or to the set $\{\ccStyle{p1}\}$ otherwise.}
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1, \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1,
const CGAL_Point_2<R>& p2, const CGAL_Point_2<R>& p2,
const CGAL_Point_2<R>& p3);}{ const CGAL_Point_2<R>& p3);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to $\textit{mc}(\emptyset, It is initialized to $mc(\{p1,p2,p3\})$.}
\{\ccStyle{p1},\ccStyle{p2},\ccStyle{p3}\})$, i.e.\ to the
unique circle with \ccStyle{p1}, \ccStyle{p2} and \ccStyle{p3}
on the boundary, if it exists. Otherwise \ccVar\ is
undefined.}
\ccConstructor{ CGAL_Min_circle_2( forward_iterator< CGAL_Point_2<R> > first, \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>* first,
forward_iterator< CGAL_Point_2<R> > last, const CGAL_Point_2<R>* last,
bool randomize = false);}{ bool randomize = false);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. It introduces a variable \ccVar\ of type \ccClassTemplateName. It
is initialized to $\textit{mc}(P,\emptyset)$ with $P$ being is initialized to $mc(P)$ with $P$ being the set of points in
the set of points in the range the range [\ccStyle{first},\ccStyle{last}). If
$[\ccStyle{first},\ccStyle{last})$. If \ccStyle{randomize} is \ccStyle{randomize} is \ccStyle{true}, a random permutation of
\ccStyle{true}, a random permutation of $P$ is computed in $P$ is computed in advance. Usually, this will not be
advance.} necessary, however, the algorithm's efficiency depends on the
order in which the points are processed, and a bad order might
\ccConstructor{ CGAL_Min_circle_2( forward_iterator< CGAL_Point_2<R> > p_first, lead to extremely poor performance (see example below).}
forward_iterator< CGAL_Point_2<R> > p_last,
forward_iterator< CGAL_Point_2<R> > b_first,
forward_iterator< CGAL_Point_2<R> > b_last,
bool randomize = false);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. It
is initialized to $\textit{mc}(P,B)$ (if it exists, to
undefined otherwise) with $P$ being the set of points in the
range $[\ccStyle{p_first},\ccStyle{p_last})$ and $B$ being the
set of points in the range
$[\ccStyle{b_first},\ccStyle{b_last})$. If \ccStyle{randomize}
is \ccStyle{true}, a random permutation of $P$ is computed in
advance.}
\ccHidden \ccHidden
\ccMemberFunction{ const Min_circle_2<R>& \ccMemberFunction{ CGAL_Min_circle_2<R>&
operator = ( const Min_circle_2<R>& min_circle2);}{ operator = ( const CGAL_Min_circle_2<R>&);}{
assignment operator.} assignment operator.}
\ccHeading{Access operations} \ccHeading{Access operations}
\ccMemberFunction{ int number_of_points( ) const;}{ \ccMemberFunction{ int number_of_points( ) const;}{
returns the number of points of \ccVar, i.e.\ $|P|+|B|$.} returns the number of points of \ccVar, i.e.\ $|P|$.}
\ccMemberFunction{ int number_of_support_points( ) const;}{ \ccMemberFunction{ int number_of_support_points( ) const;}{
returns the number of support points of \ccVar, i.e.\ $|S|$, returns the number of support points of \ccVar, i.e.\ $|S|$.}
if \ccVar\ is defined, $-1$ otherwise.}
\ccMemberFunction{ const CGAL_Point_2<R>& point( int i) const;}{ \ccMemberFunction{ const CGAL_Point_2<R>& point( int i) const;}{
returns the \ccStyle{i}'th point of \ccVar. Between two update returns the \ccStyle{i}-th point of \ccVar. Between two insert
operations any call to \ccVar\ccStyle{.point(i)} with the same operations any call to \ccStyle{\ccVar.point(i)} with the same
\ccStyle{i} returns the same point. \ccStyle{i} returns the same point.
\ccPrecond $0 \leq \ccStyle{i} < \ccVar\ccStyle{.number_of_points()}$.} \ccPrecond $0 \leq i <$ \ccStyle{\ccVar.number_of_points()}.}
\ccMemberFunction{ const CGAL_Point_2<R>& support_point( int i) const;}{ \ccMemberFunction{ const CGAL_Point_2<R>& support_point( int i) const;}{
returns the \ccStyle{i}'th support point of \ccVar. Between returns the \ccStyle{i}-th support point of \ccVar. Between two
two update operations any call to insert operations any call to \ccStyle{\ccVar.support_point(i)}
\ccVar\ccStyle{.support_point(i)} with the same \ccStyle{i} with the same \ccStyle{i} returns the same point.
returns the same point. \ccPrecond $0 \leq i <$ \ccStyle{\ccVar.number_of_support_points()}.}
\ccPrecond $0 \leq \ccStyle{i} <
\ccVar\ccStyle{.number_of_support_points()}$.}
\ccMemberFunction{ const CGAL_Point_2<R>& operator [] ( int i) const;}{ \ccMemberFunction{ const CGAL_Point_2<R>& operator [] ( int i) const;}{
returns \ccVar\ccStyle{.point( i)}.} returns \ccStyle{\ccVar.point(i)}.}
\ccMemberFunction{ CGAL_Circle_2<R> circle( ) const;}{ \ccMemberFunction{ const CGAL_Circle_2<R>& circle( ) const;}{
returns an oriented circle with same center $c$ and same returns an oriented circle with same center $c$ and same
squared radius $r$ as \ccVar\ and positive orientation. If squared radius $r$ as \ccVar\ and positive orientation.
\ccVar\ is the empty set, $c$ is undefined und $r$ is set to \ccPrecond \ccStyle{\ccVar.is_empty()} = \ccStyle{false}.}
zero. If \ccVar\ contains exactly one point $p$, $c$ is set to
$p$ and $r$ is set to zero.
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ CGAL_Bbox_2 bbox( ) const;}{ \ccMemberFunction{ CGAL_Bbox_2 bbox( ) const;}{
returns a bounding box containing \ccVar. returns a bounding box containing \ccVar.
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.} \ccPrecond \ccStyle{\ccVar.is_empty()} = \ccStyle{false}.}
\ccHeading{Update operations} \ccHeading{Update operations}
New points can be added to an existing $\ccVar$, allowing to build
$mc(P)$ incrementally, e.g.\ if $P$ is not known in advance. Compared
to the direct creation of $mc(P)$, this is not much slower, because
the construction method is incremental itself.
\ccMemberFunction{ void insert( const CGAL_Point_2<R>& p);}{ \ccMemberFunction{ void insert( const CGAL_Point_2<R>& p);}{
inserts \ccStyle{p} in \ccVar\ and recomputes the smallest inserts \ccStyle{p} in \ccVar\ and recomputes the smallest
enclosing circle. enclosing circle.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ void reserve( int n);}{ \ccMemberFunction{ void reserve( int n);}{
reserves storage for at least \ccStyle{n} points in \ccVar. reserves storage for at least \ccStyle{n} points in \ccVar.
It can be used, if the number of insert operations is known in It can be used, if the number of insert operations is known in
advance. advance.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccUnchecked
\ccHidden
\ccMemberFunction{ void reset( );}{
resets \ccVar\ to $\textit{mc}(\emptyset,\emptyset)$,
i.e.\ to the empty set.
\ccPostcond \ccVar\ccStyle{.is_empty()}.}
\ccHeading{Tests} \ccHeading{Check operation}
\ccMemberFunction{ bool check( bool verbose = false) const;}{
checks \ccVar\ for consistency. It returns \ccStyle{true}, iff
(a) \ccVar\ contains all points of its defining set $P$, (b)
\ccVar\ is the smallest circle spanned by its support set $S$,
and (c) $S$ is minimal, i.e. no support point is redundant. If
\ccStyle{verbose} is \ccStyle{true}, error messages are
written to standard error stream.}
\ccHeading{Predicates}
The following predicates imitate the corresponding ones of the class
\ccStyle{CGAL_Circle_2<R>}, with the exception of \ccStyle{is_empty()}
which is not present in \ccStyle{CGAL_Circle_2<R>}, because objects of
this class cannot be empty. By definition, an empty
\ccClassTemplateName\ has no boundary and no bounded side, i.e.\ its
unbounded side equals the whole plane $\E_2$.
\ccMemberFunction{ CGAL_Bounded_side \ccMemberFunction{ CGAL_Bounded_side
bounded_side( const CGAL_Point_2<R>& p) const;}{ bounded_side( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{CGAL_ON_BOUNDED_SIDE}, returns \ccStyle{CGAL_ON_BOUNDED_SIDE},
\ccStyle{CGAL_ON_BOUNDARY}, or \ccStyle{CGAL_ON_BOUNDARY}, or
\ccStyle{CGAL_ON_UNBOUNDED_SIDE} iff \ccStyle{p} lies inside, \ccStyle{CGAL_ON_UNBOUNDED_SIDE} iff \ccStyle{p} lies inside,
on the boundary, or outside of \ccVar, respectively. on the boundary, or outside of \ccVar, respectively.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool has_on_bounded_side( const CGAL_Point_2<R>& p) const;}{ \ccMemberFunction{ bool has_on_bounded_side( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{true}, iff \ccStyle{p} lies inside \ccVar. returns \ccStyle{true}, iff \ccStyle{p} lies inside \ccVar.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool has_on_boundary( const CGAL_Point_2<R>& p) const;}{ \ccMemberFunction{ bool has_on_boundary( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{true}, iff \ccStyle{p} lies on the boundary returns \ccStyle{true}, iff \ccStyle{p} lies on the boundary
of \ccVar. of \ccVar.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool \ccMemberFunction{ bool
has_on_unbounded_side( const CGAL_Point_2<R>& p) const;}{ has_on_unbounded_side( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{true}, iff \ccStyle{p} lies outside of \ccVar. returns \ccStyle{true}, iff \ccStyle{p} lies outside of \ccVar.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool is_empty( ) const;}{ \ccMemberFunction{ bool is_empty( ) const;}{
returns \ccStyle{true}, iff \ccVar\ is empty.} returns \ccStyle{true}, iff \ccVar\ is empty (this implies
degeneracy).}
\ccMemberFunction{ bool is_degenerate( ) const;}{ \ccMemberFunction{ bool is_degenerate( ) const;}{
returns \ccStyle{true}, iff \ccVar\ is degenerate.} returns \ccStyle{true}, iff \ccVar\ is degenerate.}
\ccMemberFunction{ bool is_undefined( ) const;}{
returns \ccStyle{true}, iff \ccVar\ is undefined.} \ccImplementation
We implement the algorithm of Welzl, with move-to-front
heuristic~\cite{Welzl}. If randomization is chosen, the creation time
is almost always linear in the number of points. Access operations and
predicates take constant time, inserting a point might take up to
linear time, but substantially less than computing the new smallest
enclosing circle from scratch. For the member function \ccStyle{reserve}
see the container \ccStyle{vector} from STL~\cite{STL}.
\ccExample
To illustrate the creation of \ccClassTemplateName\ and to show that
randomization can be useful in certain cases, we give an example.
\begin{cprog}
#include <CGAL/Integer.h>
#include <CGAL/Homogeneous.h>
#include <CGAL/Min_circle_2.h>
typedef CGAL_Homogeneous<integer> R;
typedef CGAL_Point_2<R> Point;
typedef CGAL_Min_circle_2<R> Min_circle;
int n = 1000;
Point* P = new Point[ n];
for ( int i = 0; i < n; ++i)
P[ i] = Point( (i%2 == 0 ? i : -i), 0);
/* (0,0), (-1,0), (2,0), (-3,0), ... */
Min_circle mc1( P, P+n); /* very slow */
Min_circle mc2( P, P+n, true); /* fast */
\end{cprog}
\end{ccClassTemplate} \end{ccClassTemplate}

View File

@ -2,7 +2,7 @@
% The CGAL Reference Manual % The CGAL Reference Manual
% Section: 2D Smallest Enclosing Circle % Section: 2D Smallest Enclosing Circle
% ----------------------------------------------------------------------------- % -----------------------------------------------------------------------------
% file : Min_circle_2.tex % file : spec/Min_circle_2.tex
% author: Bernd Gärtner, Sven Schönherr (sven@inf.fu-berlin.de) % author: Bernd Gärtner, Sven Schönherr (sven@inf.fu-berlin.de)
% $Id$ % $Id$
% ============================================================================= % =============================================================================
@ -12,32 +12,34 @@
\ccDefinition \ccDefinition
An object of the class \ccClassTemplateName\ is the unique smallest An object of the class \ccClassTemplateName\ is the unique circle of
enclosing circle of a set of points in two-dimensional euclidean space smallest area enclosing a finite set of points in two-dimensional
$\E_2$. For point sets $P$ and $B$ we denote by $\textit{mc}(P,B)$ euclidean space $\E_2$. For a point set $P$ we denote by $mc(P)$ the
the smallest circle that contains all points of $P$ and has (at least) smallest circle that contains all points of $P$. Note that $mc(P)$ can
the points of $B$ on the boundary. Note that $\textit{mc}(P,B)$ can be be degenerate, i.e.\ $P=$\ccTexHtml{$\emptyset$}{&Oslash;} if
degenerate, i.e.\ $\textit{mc}(P,B) = \emptyset$ if $P \cup B = $P=$\ccTexHtml{$\emptyset$}{&Oslash;} and $mc(P)=\{p\}$ if $P=\{p\}$.
\emptyset$ and $\textit{mc}(P,B) = \{p\}$ if $P \cup B = p$. If $B
\neq \emptyset$ then $\textit{mc}(P,B)$ may be undefined, i.e.\ there
is no circle containing $P$ with $B$ on the boundary.
The smallest enclosing circle of a point set $P$ is determined by at An inclusion-minimal subset $S$ of $P$ with $mc(S)=mc(P)$ is called
most three points on the boundary. A minimal subset $S$ of $P$ with a {\em support set}, the points in $S$ are the {\em support points}.
$\textit{mc}(S,\emptyset) = \textit{mc}(P,\emptyset)$ is called a A support set has size at most three, and all its points lie on the
\emph{support set}, the points in $S$ are the \emph{support points}. boundary of $mc(P)$.
Note that in general the set $S$ is not unique.
The underlying algorithm can cope with all kinds of input, e.g.\ one If $mc(P)$ has more than three points on the boundary,
or both of the point sets $P$ or $B$ may be empty, $B$ may contain neither the support set nor its size are necessarily unique.
more than three points, or some points may occure more than once in
$P$ or $B$. The algorithm computes a support set $S$, which remains
fixed until the next update operation.
The underlying algorithm can cope with all kinds of input, e.g.\
$P$ may be empty or points may occur more than once. The algorithm
computes a support set $S$ which remains fixed until the next insert
operation.
\ccCreation \ccCreation
\ccCreationVariable{min_circle} \ccCreationVariable{min_circle}
A \ccClassTemplateName\ object can be created from an arbitrary point
set $P$ and by specialized construction methods expecting no, one, two
or three points as arguments. The latter methods can be useful for
reconstructing $mc(P)$ from a given support set $S$ of $P$.
\ccSetThreeColumns{CGAL_Bounded_side}{}{ \ccSetThreeColumns{CGAL_Bounded_side}{}{
returns \ccStyle{CGAL_ON_BOUNDED_SIDE}, \ccStyle{CGAL_ON_BOUNDARY},} returns \ccStyle{CGAL_ON_BOUNDED_SIDE}, \ccStyle{CGAL_ON_BOUNDARY},}
\ccPropagateThreeToTwoColumns \ccPropagateThreeToTwoColumns
@ -46,161 +48,180 @@ fixed until the next update operation.
\ccConstructor{ CGAL_Min_circle_2( );}{ \ccConstructor{ CGAL_Min_circle_2( );}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to $\textit{mc}(\emptyset,\emptyset)$, It is initialized to
i.e.\ to the empty set. $mc($\ccTexHtml{$\emptyset$}{&Oslash;}$)$, the empty set.
\ccPostcond \ccVar\ccStyle{.is_degenerate()}.} \ccPostcond \ccStyle{\ccVar.is_empty()} = \ccStyle{true}.}
\ccHidden \ccHidden
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Min_circle_2<R>& min_circle2);}{ \ccConstructor{ CGAL_Min_circle_2( const CGAL_Min_circle_2<R>&);}{
copy constructor.} copy constructor.}
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p);}{ \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to $\textit{mc}(\emptyset,\{\ccStyle{p}\})$, It is initialized to $mc(\{p\})$, the set $\{p\}$.
i.e.\ to the set $\{\ccStyle{p}\}$. \ccPostcond \ccStyle{\ccVar.is_degenerate()} = \ccStyle{true}.}
\ccPostcond \ccVar\ccStyle{.is_degenerate()}.}
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1, \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1,
const CGAL_Point_2<R>& p2);}{ const CGAL_Point_2<R>& p2);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to It is initialized to $mc(\{p1,p2\})$, the circle with diameter
$\textit{mc}(\emptyset,\{\ccStyle{p1},\ccStyle{p2}\})$, i.e.\ equal to the segment connecting $p1$ and $p2$.}
to the circle with diameter
$\overline{\ccStyle{p1}\ccStyle{p2}}$, if $\ccStyle{p1} \neq
\ccStyle{p2}$, or to the set $\{\ccStyle{p1}\}$ otherwise.}
\ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1, \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>& p1,
const CGAL_Point_2<R>& p2, const CGAL_Point_2<R>& p2,
const CGAL_Point_2<R>& p3);}{ const CGAL_Point_2<R>& p3);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. introduces a variable \ccVar\ of type \ccClassTemplateName.
It is initialized to $\textit{mc}(\emptyset, It is initialized to $mc(\{p1,p2,p3\})$.}
\{\ccStyle{p1},\ccStyle{p2},\ccStyle{p3}\})$, i.e.\ to the
unique circle with \ccStyle{p1}, \ccStyle{p2} and \ccStyle{p3}
on the boundary, if it exists. Otherwise \ccVar\ is
undefined.}
\ccConstructor{ CGAL_Min_circle_2( forward_iterator< CGAL_Point_2<R> > first, \ccConstructor{ CGAL_Min_circle_2( const CGAL_Point_2<R>* first,
forward_iterator< CGAL_Point_2<R> > last, const CGAL_Point_2<R>* last,
bool randomize = false);}{ bool randomize = false);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. It introduces a variable \ccVar\ of type \ccClassTemplateName. It
is initialized to $\textit{mc}(P,\emptyset)$ with $P$ being is initialized to $mc(P)$ with $P$ being the set of points in
the set of points in the range the range [\ccStyle{first},\ccStyle{last}). If
$[\ccStyle{first},\ccStyle{last})$. If \ccStyle{randomize} is \ccStyle{randomize} is \ccStyle{true}, a random permutation of
\ccStyle{true}, a random permutation of $P$ is computed in $P$ is computed in advance. Usually, this will not be
advance.} necessary, however, the algorithm's efficiency depends on the
order in which the points are processed, and a bad order might
\ccConstructor{ CGAL_Min_circle_2( forward_iterator< CGAL_Point_2<R> > p_first, lead to extremely poor performance (see example below).}
forward_iterator< CGAL_Point_2<R> > p_last,
forward_iterator< CGAL_Point_2<R> > b_first,
forward_iterator< CGAL_Point_2<R> > b_last,
bool randomize = false);}{
introduces a variable \ccVar\ of type \ccClassTemplateName. It
is initialized to $\textit{mc}(P,B)$ (if it exists, to
undefined otherwise) with $P$ being the set of points in the
range $[\ccStyle{p_first},\ccStyle{p_last})$ and $B$ being the
set of points in the range
$[\ccStyle{b_first},\ccStyle{b_last})$. If \ccStyle{randomize}
is \ccStyle{true}, a random permutation of $P$ is computed in
advance.}
\ccHidden \ccHidden
\ccMemberFunction{ const Min_circle_2<R>& \ccMemberFunction{ CGAL_Min_circle_2<R>&
operator = ( const Min_circle_2<R>& min_circle2);}{ operator = ( const CGAL_Min_circle_2<R>&);}{
assignment operator.} assignment operator.}
\ccHeading{Access operations} \ccHeading{Access operations}
\ccMemberFunction{ int number_of_points( ) const;}{ \ccMemberFunction{ int number_of_points( ) const;}{
returns the number of points of \ccVar, i.e.\ $|P|+|B|$.} returns the number of points of \ccVar, i.e.\ $|P|$.}
\ccMemberFunction{ int number_of_support_points( ) const;}{ \ccMemberFunction{ int number_of_support_points( ) const;}{
returns the number of support points of \ccVar, i.e.\ $|S|$, returns the number of support points of \ccVar, i.e.\ $|S|$.}
if \ccVar\ is defined, $-1$ otherwise.}
\ccMemberFunction{ const CGAL_Point_2<R>& point( int i) const;}{ \ccMemberFunction{ const CGAL_Point_2<R>& point( int i) const;}{
returns the \ccStyle{i}'th point of \ccVar. Between two update returns the \ccStyle{i}-th point of \ccVar. Between two insert
operations any call to \ccVar\ccStyle{.point(i)} with the same operations any call to \ccStyle{\ccVar.point(i)} with the same
\ccStyle{i} returns the same point. \ccStyle{i} returns the same point.
\ccPrecond $0 \leq \ccStyle{i} < \ccVar\ccStyle{.number_of_points()}$.} \ccPrecond $0 \leq i <$ \ccStyle{\ccVar.number_of_points()}.}
\ccMemberFunction{ const CGAL_Point_2<R>& support_point( int i) const;}{ \ccMemberFunction{ const CGAL_Point_2<R>& support_point( int i) const;}{
returns the \ccStyle{i}'th support point of \ccVar. Between returns the \ccStyle{i}-th support point of \ccVar. Between two
two update operations any call to insert operations any call to \ccStyle{\ccVar.support_point(i)}
\ccVar\ccStyle{.support_point(i)} with the same \ccStyle{i} with the same \ccStyle{i} returns the same point.
returns the same point. \ccPrecond $0 \leq i <$ \ccStyle{\ccVar.number_of_support_points()}.}
\ccPrecond $0 \leq \ccStyle{i} <
\ccVar\ccStyle{.number_of_support_points()}$.}
\ccMemberFunction{ const CGAL_Point_2<R>& operator [] ( int i) const;}{ \ccMemberFunction{ const CGAL_Point_2<R>& operator [] ( int i) const;}{
returns \ccVar\ccStyle{.point( i)}.} returns \ccStyle{\ccVar.point(i)}.}
\ccMemberFunction{ CGAL_Circle_2<R> circle( ) const;}{ \ccMemberFunction{ const CGAL_Circle_2<R>& circle( ) const;}{
returns an oriented circle with same center $c$ and same returns an oriented circle with same center $c$ and same
squared radius $r$ as \ccVar\ and positive orientation. If squared radius $r$ as \ccVar\ and positive orientation.
\ccVar\ is the empty set, $c$ is undefined und $r$ is set to \ccPrecond \ccStyle{\ccVar.is_empty()} = \ccStyle{false}.}
zero. If \ccVar\ contains exactly one point $p$, $c$ is set to
$p$ and $r$ is set to zero.
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ CGAL_Bbox_2 bbox( ) const;}{ \ccMemberFunction{ CGAL_Bbox_2 bbox( ) const;}{
returns a bounding box containing \ccVar. returns a bounding box containing \ccVar.
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.} \ccPrecond \ccStyle{\ccVar.is_empty()} = \ccStyle{false}.}
\ccHeading{Update operations} \ccHeading{Update operations}
New points can be added to an existing $\ccVar$, allowing to build
$mc(P)$ incrementally, e.g.\ if $P$ is not known in advance. Compared
to the direct creation of $mc(P)$, this is not much slower, because
the construction method is incremental itself.
\ccMemberFunction{ void insert( const CGAL_Point_2<R>& p);}{ \ccMemberFunction{ void insert( const CGAL_Point_2<R>& p);}{
inserts \ccStyle{p} in \ccVar\ and recomputes the smallest inserts \ccStyle{p} in \ccVar\ and recomputes the smallest
enclosing circle. enclosing circle.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ void reserve( int n);}{ \ccMemberFunction{ void reserve( int n);}{
reserves storage for at least \ccStyle{n} points in \ccVar. reserves storage for at least \ccStyle{n} points in \ccVar.
It can be used, if the number of insert operations is known in It can be used, if the number of insert operations is known in
advance. advance.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccUnchecked
\ccHidden
\ccMemberFunction{ void reset( );}{
resets \ccVar\ to $\textit{mc}(\emptyset,\emptyset)$,
i.e.\ to the empty set.
\ccPostcond \ccVar\ccStyle{.is_empty()}.}
\ccHeading{Tests} \ccHeading{Check operation}
\ccMemberFunction{ bool check( bool verbose = false) const;}{
checks \ccVar\ for consistency. It returns \ccStyle{true}, iff
(a) \ccVar\ contains all points of its defining set $P$, (b)
\ccVar\ is the smallest circle spanned by its support set $S$,
and (c) $S$ is minimal, i.e. no support point is redundant. If
\ccStyle{verbose} is \ccStyle{true}, error messages are
written to standard error stream.}
\ccHeading{Predicates}
The following predicates imitate the corresponding ones of the class
\ccStyle{CGAL_Circle_2<R>}, with the exception of \ccStyle{is_empty()}
which is not present in \ccStyle{CGAL_Circle_2<R>}, because objects of
this class cannot be empty. By definition, an empty
\ccClassTemplateName\ has no boundary and no bounded side, i.e.\ its
unbounded side equals the whole plane $\E_2$.
\ccMemberFunction{ CGAL_Bounded_side \ccMemberFunction{ CGAL_Bounded_side
bounded_side( const CGAL_Point_2<R>& p) const;}{ bounded_side( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{CGAL_ON_BOUNDED_SIDE}, returns \ccStyle{CGAL_ON_BOUNDED_SIDE},
\ccStyle{CGAL_ON_BOUNDARY}, or \ccStyle{CGAL_ON_BOUNDARY}, or
\ccStyle{CGAL_ON_UNBOUNDED_SIDE} iff \ccStyle{p} lies inside, \ccStyle{CGAL_ON_UNBOUNDED_SIDE} iff \ccStyle{p} lies inside,
on the boundary, or outside of \ccVar, respectively. on the boundary, or outside of \ccVar, respectively.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool has_on_bounded_side( const CGAL_Point_2<R>& p) const;}{ \ccMemberFunction{ bool has_on_bounded_side( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{true}, iff \ccStyle{p} lies inside \ccVar. returns \ccStyle{true}, iff \ccStyle{p} lies inside \ccVar.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool has_on_boundary( const CGAL_Point_2<R>& p) const;}{ \ccMemberFunction{ bool has_on_boundary( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{true}, iff \ccStyle{p} lies on the boundary returns \ccStyle{true}, iff \ccStyle{p} lies on the boundary
of \ccVar. of \ccVar.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool \ccMemberFunction{ bool
has_on_unbounded_side( const CGAL_Point_2<R>& p) const;}{ has_on_unbounded_side( const CGAL_Point_2<R>& p) const;}{
returns \ccStyle{true}, iff \ccStyle{p} lies outside of \ccVar. returns \ccStyle{true}, iff \ccStyle{p} lies outside of \ccVar.}
\ccPrecond $\ccVar\ccStyle{.is_undefined()} = \ccStyle{false}$.}
\ccMemberFunction{ bool is_empty( ) const;}{ \ccMemberFunction{ bool is_empty( ) const;}{
returns \ccStyle{true}, iff \ccVar\ is empty.} returns \ccStyle{true}, iff \ccVar\ is empty (this implies
degeneracy).}
\ccMemberFunction{ bool is_degenerate( ) const;}{ \ccMemberFunction{ bool is_degenerate( ) const;}{
returns \ccStyle{true}, iff \ccVar\ is degenerate.} returns \ccStyle{true}, iff \ccVar\ is degenerate.}
\ccMemberFunction{ bool is_undefined( ) const;}{
returns \ccStyle{true}, iff \ccVar\ is undefined.} \ccImplementation
We implement the algorithm of Welzl, with move-to-front
heuristic~\cite{Welzl}. If randomization is chosen, the creation time
is almost always linear in the number of points. Access operations and
predicates take constant time, inserting a point might take up to
linear time, but substantially less than computing the new smallest
enclosing circle from scratch. For the member function \ccStyle{reserve}
see the container \ccStyle{vector} from STL~\cite{STL}.
\ccExample
To illustrate the creation of \ccClassTemplateName\ and to show that
randomization can be useful in certain cases, we give an example.
\begin{cprog}
#include <CGAL/Integer.h>
#include <CGAL/Homogeneous.h>
#include <CGAL/Min_circle_2.h>
typedef CGAL_Homogeneous<integer> R;
typedef CGAL_Point_2<R> Point;
typedef CGAL_Min_circle_2<R> Min_circle;
int n = 1000;
Point* P = new Point[ n];
for ( int i = 0; i < n; ++i)
P[ i] = Point( (i%2 == 0 ? i : -i), 0);
/* (0,0), (-1,0), (2,0), (-3,0), ... */
Min_circle mc1( P, P+n); /* very slow */
Min_circle mc2( P, P+n, true); /* fast */
\end{cprog}
\end{ccClassTemplate} \end{ccClassTemplate}