mirror of https://github.com/CGAL/cgal
372 lines
9.7 KiB
C++
372 lines
9.7 KiB
C++
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgBoundingVolumes
|
|
|
|
An object of the class `Min_circle_2` is the unique circle of smallest area
|
|
enclosing a finite (multi)set of points in two-dimensional Euclidean
|
|
space \f$ \E^2\f$. For a point set \f$ P\f$ we denote by \f$ mc(P)\f$ the smallest circle
|
|
that contains all points of \f$ P\f$. Note that \f$ mc(P)\f$ can be
|
|
degenerate,
|
|
i.e. \f$ mc(P)=\emptyset\f$ if
|
|
\f$ P=\emptyset\f$ and \f$ mc(P)=\{p\}\f$ if
|
|
\f$ P=\{p\}\f$.
|
|
|
|
An inclusion-minimal subset \f$ S\f$ of \f$ P\f$ with \f$ mc(S)=mc(P)\f$ is called a
|
|
<I>support set</I>,
|
|
the points in \f$ S\f$ are the <I>support points</I>. A support set has size at
|
|
most three, and all its points lie on the boundary of \f$ mc(P)\f$. In general,
|
|
neither the support set nor its size are necessarily unique.
|
|
|
|
The underlying algorithm can cope with all kinds of input, e.g. \f$ P\f$ may be
|
|
empty or points may occur more than once. The algorithm computes a support
|
|
set \f$ S\f$ which remains fixed until the next insert or clear operation.
|
|
|
|
<B>Please note:</B> This class is (almost) obsolete. The class
|
|
`CGAL::Min_sphere_of_spheres_d<Traits>` solves a more general problem
|
|
and is faster then `Min_circle_2` even if used only for points in two
|
|
dimensions as input. Most importantly,
|
|
`CGAL::Min_sphere_of_spheres_d<Traits>` has
|
|
a specialized implementation for floating-point arithmetic which
|
|
ensures correct results in a large number of cases (including
|
|
highly degenerate ones). In contrast, `Min_circle_2` is not tuned for
|
|
floating-point computations. The only advantage of
|
|
`Min_circle_2` over `CGAL::Min_sphere_of_spheres_d<Traits>` is that the
|
|
former can deal with points in homogeneous coordinates, in which
|
|
case the algorithm is division-free. Thus, `Min_circle_2` might still
|
|
be an option in case your input number type cannot (efficiently)
|
|
divide.
|
|
|
|
|
|
\tparam Traits must be a model for `MinCircle2Traits`.
|
|
|
|
We provide the model `CGAL::Min_circle_2_traits_2` using the
|
|
two-dimensional \cgal kernel.
|
|
|
|
\sa `CGAL::Min_ellipse_2<Traits>`
|
|
\sa `CGAL::Min_sphere_d<Traits>`
|
|
\sa `CGAL::Min_sphere_of_spheres_d<Traits>`
|
|
\sa `CGAL::Min_circle_2_traits_2<K>`
|
|
\sa `MinCircle2Traits`
|
|
|
|
### Implementation ###
|
|
|
|
We implement the incremental algorithm of Welzl, with move-to-front
|
|
heuristic \cite w-sedbe-91a. The whole implementation is described
|
|
in \cite cgal:gs-seceg-98.
|
|
|
|
If randomization is
|
|
chosen, the creation time is almost always linear in the number of points.
|
|
Access functions 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. The clear operation and the check
|
|
for validity each takes linear time.
|
|
|
|
### Example ###
|
|
|
|
To illustrate the creation of `Min_circle_2` and to show that
|
|
randomization can be useful in certain cases, we give an example.
|
|
|
|
\cgalexample{Min_circle_2/min_circle_2.cpp}
|
|
|
|
*/
|
|
template< typename Traits >
|
|
class Min_circle_2 {
|
|
public:
|
|
|
|
/// \name Types
|
|
/// @{
|
|
|
|
/*!
|
|
typedef to `Traits::Point `.
|
|
*/
|
|
typedef Hidden_type Point ;
|
|
|
|
/*!
|
|
typedef to `Traits::Circle`.
|
|
*/
|
|
typedef Hidden_type Circle;
|
|
|
|
/*!
|
|
|
|
non-mutable model of the \stl concept <I>BidirectionalIterator</I>
|
|
with value type `Point`. Used to access the points
|
|
of the smallest enclosing circle.
|
|
*/
|
|
typedef Hidden_type Point_iterator;
|
|
|
|
/*!
|
|
|
|
non-mutable model of the \stl concept <I>RandomAccessIterator</I>
|
|
with value type `Point`. Used to access the support points
|
|
of the smallest enclosing circle.
|
|
*/
|
|
typedef Hidden_type Support_point_iterator;
|
|
|
|
/// @}
|
|
|
|
/// \name Creation
|
|
/// A `Min_circle_2` object can be created from an arbitrary point set
|
|
/// \f$ P\f$ and by specialized construction methods expecting no,
|
|
/// one, two or three points as arguments. The latter methods can be
|
|
/// useful for reconstructing \f$ mc(P)\f$ from a given support set
|
|
/// \f$ S\f$ of \f$ P\f$.
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
initializes `min_circle` to \f$ mc(P)\f$ with \f$ P\f$ being the set of points
|
|
in the range [`first`,`last`). If `randomize` is
|
|
`true`, a random permutation of \f$ P\f$ is computed in
|
|
advance, using the random numbers generator `random`.
|
|
Usually, this will not be necessary, however, the algorithm's
|
|
efficiency depends on the order in which the points are
|
|
processed, and a bad order might lead to extremely poor
|
|
performance (see example below).
|
|
\requires The value type of `first` and `last` is `Point`.
|
|
*/
|
|
template < class InputIterator >
|
|
Min_circle_2( InputIterator first,
|
|
InputIterator last,
|
|
bool randomize,
|
|
Random& random = CGAL::default_random,
|
|
const Traits& traits = Traits() );
|
|
|
|
/*!
|
|
|
|
initializes `min_circle` to
|
|
\f$ mc(\emptyset)\f$, the empty set.
|
|
\post `min_circle.is_empty()` = `true`.
|
|
*/
|
|
Min_circle_2( const Traits& traits = Traits());
|
|
|
|
/*!
|
|
|
|
initializes `min_circle` to \f$ mc(\{p\})\f$, the set \f$ \{p\}\f$.
|
|
\post `min_circle.is_degenerate()` = `true`.
|
|
*/
|
|
Min_circle_2( const Point& p,
|
|
const Traits& traits = Traits());
|
|
|
|
/*!
|
|
|
|
initializes `min_circle` to \f$ mc(\{p1,p2\})\f$, the circle with diameter
|
|
equal to the segment connecting \f$ p1\f$ and \f$ p2\f$.
|
|
*/
|
|
Min_circle_2( const Point& p1,
|
|
const Point& p2,
|
|
const Traits& traits = Traits());
|
|
|
|
/*!
|
|
|
|
initializes `min_circle` to \f$ mc(\{p1,p2,p3\})\f$.
|
|
*/
|
|
Min_circle_2( const Point& p1,
|
|
const Point& p2,
|
|
const Point& p3,
|
|
const Traits& traits = Traits());
|
|
|
|
/// @}
|
|
|
|
/// \name Access Functions
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
returns the number of points of `min_circle`, i.e. \f$ |P|\f$.
|
|
*/
|
|
int number_of_points( ) const;
|
|
|
|
/*!
|
|
|
|
returns the number of support points of `min_circle`, i.e. \f$ |S|\f$.
|
|
*/
|
|
int number_of_support_points( ) const;
|
|
|
|
/*!
|
|
|
|
returns an iterator referring to the first point of `min_circle`.
|
|
*/
|
|
Point_iterator points_begin() const;
|
|
|
|
/*!
|
|
|
|
returns the corresponding past-the-end iterator.
|
|
*/
|
|
Point_iterator points_end() const;
|
|
|
|
/*!
|
|
|
|
returns an iterator referring to the first support point of `min_circle`.
|
|
*/
|
|
Support_point_iterator support_points_begin() const;
|
|
|
|
/*!
|
|
|
|
returns the corresponding past-the-end iterator.
|
|
*/
|
|
Support_point_iterator support_points_end() const;
|
|
|
|
/*!
|
|
|
|
returns the `i`-th support point of `min_circle`. Between two
|
|
modifying operations (see below) any call to
|
|
`min_circle.support_point(i)` with the same `i` returns
|
|
the same point.
|
|
\pre \f$ 0 \leq i< \f$ `min_circle.number_of_support_points()`.
|
|
*/
|
|
const Point& support_point( int i) const;
|
|
|
|
/*!
|
|
|
|
returns the current circle of `min_circle`.
|
|
*/
|
|
const Circle& circle( ) const;
|
|
|
|
/// @}
|
|
|
|
/// \name Predicates
|
|
/// By definition, an empty `Min_circle_2` has no boundary and no
|
|
/// bounded side, i.e. its unbounded side equals the whole space \f$
|
|
/// \E^2\f$.
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
returns `CGAL::ON_BOUNDED_SIDE`,
|
|
`CGAL::ON_BOUNDARY`, or
|
|
`CGAL::ON_UNBOUNDED_SIDE` iff `p` lies properly
|
|
inside, on the boundary of, or properly outside of `min_circle`, resp.
|
|
*/
|
|
CGAL::Bounded_side
|
|
bounded_side( const Point& p) const;
|
|
|
|
/*!
|
|
|
|
returns `true`, iff `p` lies properly inside `min_circle`.
|
|
*/
|
|
bool has_on_bounded_side( const Point& p) const;
|
|
|
|
/*!
|
|
|
|
returns `true`, iff `p` lies on the boundary
|
|
of `min_circle`.
|
|
*/
|
|
bool has_on_boundary( const Point& p) const;
|
|
|
|
/*!
|
|
|
|
returns `true`, iff `p` lies properly outside of `min_circle`.
|
|
*/
|
|
bool has_on_unbounded_side( const Point& p) const;
|
|
|
|
/*!
|
|
|
|
returns `true`, iff `min_circle` is empty (this implies
|
|
degeneracy).
|
|
*/
|
|
bool is_empty( ) const;
|
|
|
|
/*!
|
|
|
|
returns `true`, iff `min_circle` is degenerate,
|
|
i.e. if `min_circle` is empty or equal to a single point, equivalently
|
|
if the number of support points is less than 2.
|
|
*/
|
|
bool is_degenerate( ) const;
|
|
|
|
/// @}
|
|
|
|
/// \name Modifiers
|
|
/// New points can be added to an existing `min_circle`, allowing to
|
|
/// build \f$ mc(P)\f$ incrementally, e.g. if \f$ P\f$ is not known in
|
|
/// advance. Compared to the direct creation of \f$ mc(P)\f$, this is
|
|
/// not much slower, because the construction method is incremental
|
|
/// itself.
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
inserts `p` into `min_circle` and recomputes the smallest
|
|
enclosing circle.
|
|
*/
|
|
void insert( const Point& p);
|
|
|
|
/*!
|
|
|
|
inserts the points in the range [`first`,`last`)
|
|
into `min_circle` and recomputes the smallest enclosing circle by
|
|
calling `insert(p)` for each point `p` in
|
|
[`first`,`last`).
|
|
\requires The value type of `first` and `last` is `Point`.
|
|
*/
|
|
template < class InputIterator >
|
|
void insert( InputIterator first,
|
|
InputIterator last );
|
|
|
|
/*!
|
|
|
|
deletes all points in `min_circle` and sets `min_circle` to the empty set.
|
|
\post `min_circle.is_empty()` = `true`.
|
|
*/
|
|
void clear( );
|
|
|
|
/// @}
|
|
|
|
/// \name Validity Check
|
|
/// An object `min_circle` is valid, iff <UL> <LI>`min_circle`
|
|
/// contains all points of its defining set \f$ P\f$, <LI>`min_circle`
|
|
/// is the smallest circle spanned by its support set \f$ S\f$, and
|
|
/// <LI>\f$ S\f$ is minimal, i.e. no support point is redundant. </UL>
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
returns `true`, iff `min_circle` is valid. If `verbose`
|
|
is `true`, some messages concerning the performed checks
|
|
are written to standard error stream. The second parameter
|
|
`level` is not used, we provide it only for consistency
|
|
with interfaces of other classes.
|
|
*/
|
|
bool is_valid( bool verbose = false,
|
|
int level = 0 ) const;
|
|
|
|
/// @}
|
|
|
|
/// \name Miscellaneous
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
returns a const reference to the traits class object.
|
|
*/
|
|
const Traits& traits( ) const;
|
|
|
|
/// @}
|
|
|
|
}; /* end Min_circle_2 */
|
|
|
|
/*!
|
|
|
|
writes `min_circle` to output stream `os`.
|
|
\requires The output operator is defined for `Point` (and for `Circle`, if pretty printing is used).
|
|
\relates Min_circle_2
|
|
*/
|
|
std::ostream&
|
|
operator << ( std::ostream& os,
|
|
const Min_circle_2<Traits>& min_circle);
|
|
|
|
/*!
|
|
|
|
reads `min_circle` from input stream `is`.
|
|
\requires The input operator is defined for `Point`.
|
|
\relates Min_circle_2
|
|
*/
|
|
std::istream&
|
|
operator >> ( std::istream& is,
|
|
Min_circle_2<Traits> min_circle&);
|
|
|
|
|
|
} /* end namespace CGAL */
|