mirror of https://github.com/CGAL/cgal
439 lines
13 KiB
C++
439 lines
13 KiB
C++
// Copyright (c) 2005 Tel-Aviv University (Israel).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
// the terms of the Q Public License version 1.0.
|
|
// See the file LICENSE.QPL distributed with CGAL.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
//
|
|
//
|
|
// Author(s) : Ron Wein <wein@post.tau.ac.il>
|
|
// Efi Fogel <efif@post.tau.ac.il>
|
|
#ifndef CGAL_ARR_CURVE_DATA_TRAITS_2_H
|
|
#define CGAL_ARR_CURVE_DATA_TRAITS_2_H
|
|
|
|
/*! \file
|
|
* Definition of the Arr_curve_data_traits_2<> class template.
|
|
*/
|
|
|
|
#include<CGAL/Arr_traits_2/Curve_data_aux.h>
|
|
#include<list>
|
|
|
|
CGAL_BEGIN_NAMESPACE
|
|
|
|
/*! \class
|
|
* A generic traits class for maintaining an arrangement of curves that have
|
|
* an extra data field. This traits class is templated with an ordinary traits
|
|
* class, which is also used as a based traits class to inherit from.
|
|
* It can attach data objects to Curve_2 and to X_monotone_curve_2 objects
|
|
* (possibly of two different types).
|
|
* The data field is updated when the curves are converted from Curve_2 to
|
|
* X_monotone_curve_2, and when the X_monotone_curve_2 curves are split.
|
|
* When two x-monotone curves overlap, the data field to be associated with
|
|
* the overlapping subcurve is obtained from the merge functor.
|
|
* All other functors are inherited from the base ordinary traits class.
|
|
*/
|
|
template <class Traits_, class XMonotoneCurveData_, class Merge_,
|
|
class CurveData_ = XMonotoneCurveData_,
|
|
class Convert_ = _Default_convert_func<CurveData_,
|
|
XMonotoneCurveData_> >
|
|
class Arr_curve_data_traits_2 : public Traits_
|
|
{
|
|
public:
|
|
|
|
typedef Traits_ Base_traits_2;
|
|
typedef XMonotoneCurveData_ X_monotone_curve_data;
|
|
typedef Merge_ Merge;
|
|
typedef CurveData_ Curve_data;
|
|
typedef Convert_ Convert;
|
|
|
|
typedef typename Base_traits_2::Curve_2 Base_curve_2;
|
|
typedef typename Base_traits_2::X_monotone_curve_2 Base_x_monotone_curve_2;
|
|
typedef typename Base_traits_2::Point_2 Point_2;
|
|
|
|
typedef typename Base_traits_2::Has_left_category Has_left_category;
|
|
typedef typename Base_traits_2::Has_merge_category Base_has_merge_category;
|
|
typedef Tag_true Has_merge_category;
|
|
|
|
// Representation of a curve with an addtional data field:
|
|
typedef _Curve_data_ex<Base_curve_2, Curve_data> Curve_2;
|
|
|
|
// Representation of an x-monotone curve with an addtional data field:
|
|
typedef _Curve_data_ex<Base_x_monotone_curve_2,
|
|
X_monotone_curve_data> X_monotone_curve_2;
|
|
|
|
public:
|
|
|
|
/// \name Construction.
|
|
//@{
|
|
|
|
/*! Default constructor. */
|
|
Arr_curve_data_traits_2 ()
|
|
{}
|
|
|
|
/*! Constructor from a base-traits class. */
|
|
Arr_curve_data_traits_2 (const Base_traits_2& traits) :
|
|
Base_traits_2 (traits)
|
|
{}
|
|
//@}
|
|
|
|
/// \name Overriden functors.
|
|
//@{
|
|
|
|
class Make_x_monotone_2
|
|
{
|
|
private:
|
|
Base_traits_2 *base;
|
|
|
|
public:
|
|
|
|
/*! Constructor. */
|
|
Make_x_monotone_2 (Base_traits_2 *_base) :
|
|
base (_base)
|
|
{}
|
|
|
|
/*!
|
|
* Cut the given curve into x-monotone subcurves and insert them to the
|
|
* given output iterator. As segments are always x_monotone, only one
|
|
* x-monotone curve will be contained in the iterator.
|
|
* \param cv The curve.
|
|
* \param oi The output iterator, whose value-type is X_monotone_curve_2.
|
|
* \return The past-the-end iterator.
|
|
*/
|
|
template<class OutputIterator>
|
|
OutputIterator operator() (const Curve_2& cv, OutputIterator oi)
|
|
{
|
|
// Make the original curve x-monotone.
|
|
std::list<CGAL::Object> base_objects;
|
|
|
|
base->make_x_monotone_2_object() (cv,
|
|
std::back_inserter (base_objects));
|
|
|
|
// Attach the data to each of the resulting x-monotone curves.
|
|
typename std::list<CGAL::Object>::const_iterator it;
|
|
const Base_x_monotone_curve_2 *base_x_curve;
|
|
X_monotone_curve_data xdata = Convert()(cv.data());
|
|
|
|
for (it = base_objects.begin(); it != base_objects.end(); ++it)
|
|
{
|
|
base_x_curve = object_cast<Base_x_monotone_curve_2> (&(*it));
|
|
if (base_x_curve != NULL)
|
|
{
|
|
// Current object is an x-monotone curve: Attach data to it.
|
|
*oi = make_object (X_monotone_curve_2 (*base_x_curve,
|
|
xdata));
|
|
}
|
|
else
|
|
{
|
|
// Current object is an isolated point: Leave it as is.
|
|
CGAL_assertion (object_cast<Point_2> (&(*it)) != NULL);
|
|
*oi = *it;
|
|
}
|
|
++oi;
|
|
}
|
|
|
|
return (oi);
|
|
}
|
|
};
|
|
|
|
/*! Get a Make_x_monotone_2 functor object. */
|
|
Make_x_monotone_2 make_x_monotone_2_object ()
|
|
{
|
|
return Make_x_monotone_2 (this);
|
|
}
|
|
|
|
class Split_2
|
|
{
|
|
private:
|
|
Base_traits_2 *base;
|
|
|
|
public:
|
|
|
|
/*! Constructor. */
|
|
Split_2 (Base_traits_2 *_base) :
|
|
base (_base)
|
|
{}
|
|
|
|
/*!
|
|
* Split a given x-monotone curve at a given point into two sub-curves.
|
|
* \param cv The curve to split
|
|
* \param p The split point.
|
|
* \param c1 Output: The left resulting subcurve (p is its right endpoint).
|
|
* \param c2 Output: The right resulting subcurve (p is its left endpoint).
|
|
* \pre p lies on cv but is not one of its end-points.
|
|
*/
|
|
void operator() (const X_monotone_curve_2& cv, const Point_2 & p,
|
|
X_monotone_curve_2& c1, X_monotone_curve_2& c2)
|
|
{
|
|
// Split the original curve.
|
|
base->split_2_object() (cv, p,
|
|
c1, c2);
|
|
|
|
// Attach data to the split curves.
|
|
c1.set_data (cv.data());
|
|
c2.set_data (cv.data());
|
|
|
|
return;
|
|
}
|
|
};
|
|
|
|
/*! Get a Split_2 functor object. */
|
|
Split_2 split_2_object ()
|
|
{
|
|
return Split_2 (this);
|
|
}
|
|
|
|
class Intersect_2
|
|
{
|
|
private:
|
|
Base_traits_2 *base;
|
|
|
|
public:
|
|
|
|
/*! Constructor. */
|
|
Intersect_2 (Base_traits_2 *_base) :
|
|
base (_base)
|
|
{}
|
|
|
|
/*!
|
|
* Find the intersections of the two given curves and insert them to the
|
|
* given output iterator. As two segments may itersect only once, only a
|
|
* single will be contained in the iterator.
|
|
* \param cv1 The first curve.
|
|
* \param cv2 The second curve.
|
|
* \param oi The output iterator.
|
|
* \return The past-the-end iterator.
|
|
*/
|
|
template<class OutputIterator>
|
|
OutputIterator operator() (const X_monotone_curve_2& cv1,
|
|
const X_monotone_curve_2& cv2,
|
|
OutputIterator oi)
|
|
{
|
|
// Use the base functor to obtain all intersection objects.
|
|
std::list<CGAL::Object> base_objects;
|
|
|
|
base->intersect_2_object() (cv1, cv2,
|
|
std::back_inserter (base_objects));
|
|
|
|
// Stop if the list is empty:
|
|
if (base_objects.empty())
|
|
return (oi);
|
|
|
|
// Go over all intersection objects and prepare the output.
|
|
typename std::list<CGAL::Object>::const_iterator it;
|
|
const Base_x_monotone_curve_2 *base_cv;
|
|
|
|
for (it = base_objects.begin(); it != base_objects.end(); ++it)
|
|
{
|
|
if ((base_cv = object_cast<Base_x_monotone_curve_2> (&(*it))) != NULL)
|
|
{
|
|
// The current intersection object is an overlapping x-monotone
|
|
// curve: Merge the data fields of both intersecting curves and
|
|
// associate the result with the overlapping curve.
|
|
X_monotone_curve_2 cv (*base_cv,
|
|
Merge() (cv1.data(), cv2.data()));
|
|
|
|
*oi = make_object (cv);
|
|
}
|
|
else
|
|
{
|
|
// The current intersection object is an intersection point:
|
|
// Copy it as is.
|
|
*oi = *it;
|
|
}
|
|
++oi;
|
|
}
|
|
|
|
return (oi);
|
|
}
|
|
};
|
|
|
|
/*! Get an Intersect_2 functor object. */
|
|
Intersect_2 intersect_2_object ()
|
|
{
|
|
return Intersect_2 (this);
|
|
}
|
|
|
|
class Are_mergeable_2
|
|
{
|
|
private:
|
|
const Base_traits_2 *base;
|
|
|
|
public:
|
|
|
|
/*! Constructor. */
|
|
Are_mergeable_2 (const Base_traits_2 *_base) :
|
|
base (_base)
|
|
{}
|
|
|
|
/*!
|
|
* Check whether it is possible to merge two given x-monotone curves.
|
|
* \param cv1 The first curve.
|
|
* \param cv2 The second curve.
|
|
* \return (true) if the two curves are mergeable; (false) otherwise.
|
|
*/
|
|
bool operator() (const X_monotone_curve_2& cv1,
|
|
const X_monotone_curve_2& cv2) const
|
|
{
|
|
return (_are_mergeable_base_imp (cv1, cv2,
|
|
Base_has_merge_category()));
|
|
}
|
|
|
|
private:
|
|
|
|
/*!
|
|
* Implementation of the base predicate in case the HasMerge tag is true.
|
|
*/
|
|
bool _are_mergeable_base_imp (const X_monotone_curve_2& cv1,
|
|
const X_monotone_curve_2& cv2,
|
|
Tag_true) const
|
|
{
|
|
// In case the two base curves are not mergeable, the extended curves
|
|
// are not mergeable as well.
|
|
if (! (base->are_mergeable_2_object() (cv1, cv2)))
|
|
return (false);
|
|
|
|
// In case the two base curves are mergeable, check that they have the
|
|
// same data fields.
|
|
return (cv1.data() == cv2.data());
|
|
}
|
|
|
|
/*!
|
|
* Implementation of the base predicate in case the HasMerge tag is false.
|
|
*/
|
|
bool _are_mergeable_base_imp (const X_monotone_curve_2& ,
|
|
const X_monotone_curve_2& ,
|
|
Tag_false) const
|
|
{
|
|
// Curve merging is not supported:
|
|
return (false);
|
|
}
|
|
};
|
|
|
|
/*! Get an Are_mergeable_2 functor object. */
|
|
Are_mergeable_2 are_mergeable_2_object () const
|
|
{
|
|
return Are_mergeable_2 (this);
|
|
}
|
|
|
|
class Merge_2
|
|
{
|
|
private:
|
|
Base_traits_2 *base;
|
|
|
|
public:
|
|
|
|
/*! Constructor. */
|
|
Merge_2 (Base_traits_2 *_base) :
|
|
base (_base)
|
|
{}
|
|
|
|
/*!
|
|
* Merge two given x-monotone curves into a single curve (segment).
|
|
* \param cv1 The first curve.
|
|
* \param cv2 The second curve.
|
|
* \param c Output: The merged curve.
|
|
* \pre The two curves are mergeable.
|
|
*/
|
|
void operator() (const X_monotone_curve_2& cv1,
|
|
const X_monotone_curve_2& cv2,
|
|
X_monotone_curve_2& c)
|
|
{
|
|
// The function is implemented based on the base Has_merge category.
|
|
_merge_imp (cv1, cv2, c, Base_has_merge_category());
|
|
}
|
|
|
|
private:
|
|
|
|
/*!
|
|
* Implementation of the operator() in case the HasMerge tag is true.
|
|
*/
|
|
void _merge_imp (const X_monotone_curve_2& cv1,
|
|
const X_monotone_curve_2& cv2,
|
|
X_monotone_curve_2& c,
|
|
Tag_true)
|
|
{
|
|
// Merge the two base curve.
|
|
Base_x_monotone_curve_2 base_cv;
|
|
|
|
base->merge_2_object() (cv1, cv2,
|
|
base_cv);
|
|
|
|
// Attach data from one of the curves.
|
|
CGAL_precondition (cv1.data() == cv2.data());
|
|
|
|
c = X_monotone_curve_2 (base_cv, cv1.data());
|
|
return;
|
|
}
|
|
|
|
/*!
|
|
* Implementation of the operator() in case the HasMerge tag is false.
|
|
*/
|
|
void _merge_imp (const X_monotone_curve_2& ,
|
|
const X_monotone_curve_2& ,
|
|
X_monotone_curve_2& ,
|
|
Tag_false) const
|
|
{
|
|
// This function should never be called!
|
|
CGAL_assertion_msg (false,
|
|
"Merging curves is not supported.");
|
|
}
|
|
};
|
|
|
|
/*! Get a Merge_2 functor object. */
|
|
Merge_2 merge_2_object ()
|
|
{
|
|
return Merge_2 (this);
|
|
}
|
|
|
|
class Construct_x_monotone_curve_2
|
|
{
|
|
private:
|
|
const Base_traits_2 *base;
|
|
|
|
public:
|
|
|
|
/*! Constructor. */
|
|
Construct_x_monotone_curve_2 (const Base_traits_2 *_base) :
|
|
base (_base)
|
|
{}
|
|
|
|
/*!
|
|
* Return an x-monotone curve connecting the two given endpoints.
|
|
* \param p The first point.
|
|
* \param q The second point.
|
|
* \pre p and q must not be the same.
|
|
* \return An x-monotone curve connecting p and q.
|
|
*/
|
|
X_monotone_curve_2 operator() (const Point_2& p,
|
|
const Point_2& q) const
|
|
{
|
|
Base_x_monotone_curve_2 base_cv =
|
|
base->construct_x_monotone_curve_2_object() (p, q);
|
|
|
|
return (X_monotone_curve_2 (base_cv, X_monotone_curve_data()));
|
|
}
|
|
};
|
|
|
|
/*! Get a Construct_x_monotone_curve_2 functor object. */
|
|
Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const
|
|
{
|
|
return Construct_x_monotone_curve_2 (this);
|
|
}
|
|
//@}
|
|
|
|
};
|
|
|
|
CGAL_END_NAMESPACE
|
|
|
|
#endif
|
|
|