Added support for vertical curves and overlapping curves.

This commit is contained in:
Tali Zvi 2002-12-19 12:39:34 +00:00
parent 85f34687a0
commit 2f1daf97d2
4 changed files with 1024 additions and 616 deletions

View File

@ -29,7 +29,7 @@
#include <CGAL/Sweep_line_2/Sweep_line_subcurve.h>
#include <CGAL/Sweep_line_2/Sweep_line_functors.h>
#include <vector>
#include <list>
#include <set>
CGAL_BEGIN_NAMESPACE
@ -50,15 +50,19 @@ public:
typedef std::set<SubCurve*, StatusLineCurveLess> StatusLine;
typedef typename StatusLine::iterator StatusLineIter;
typedef std::list<Point_2> VerticalXPointList;
typedef VerticalXPointList::iterator VerticalXPointListIter;
typedef std::list<SubCurve *> VerticalCurveList;
typedef VerticalCurveList::iterator VerticalCurveListIter;
/*! Constructor */
Sweep_line_event(const Point_2 &point, Traits *traits) {
Sweep_line_event(const Point_2 &point, Traits *traits) :
m_point(point), m_traits(traits), m_isInitialized(false),
m_isInternalIntersectionPoint(false), m_containsOverlap(false)
{
m_leftCurves = new SubcurveContainer();
m_rightCurves = new SubcurveContainer();
m_point = point;
m_traits = traits;
m_isInitialized = false;
m_verticalCurve = 0;
m_isInternalIntersectionPoint = false;
}
/*! Destructor. Deletes the lists of curves, without deleting the
@ -72,7 +76,9 @@ public:
/*! Adds a new curve to the event. The curve is added only to the list/s
in which it is defined (left or/and right).
The event point has to be either the source or the target of the curve.
If the curve is vertical, it is added to the list of vertical curves.
Precondition: The event point has to be either the source or the
target of the curve.
@param curve a pointer to the curve.
*/
void addCurve(SubCurve *scurve)
@ -83,7 +89,7 @@ public:
if ( m_traits->curve_is_vertical(curve) )
{
m_verticalCurve = scurve;
m_verticalCurves.push_back(scurve);
} else
{
@ -92,7 +98,7 @@ public:
rel = &(target);
if ( m_traits->compare_x(m_point, *rel) == LARGER ) {
addCurveToLeft1(scurve);
addCurveToLeft(scurve, m_rightmostPointToLeft, true);
} else {
addCurveToRight(scurve);
}
@ -105,119 +111,127 @@ public:
If the curve is already in the list of curves, it is removed and
re-inserted. This way the curves remain sorted.
@param curve a pointer to the curve.
@pram ref a reference point to perform the compare by
@param isInitStage true when thie method is called at the
initialization stage (in which case some extra tests are performed).
*/
void addCurveToLeft(SubCurve *curve, const Point_2 &ref)
void addCurveToLeft(SubCurve *curve, const Point_2 &ref,
bool isInitStage=false)
{
if (m_leftCurves->empty())
m_leftCurves->push_back(curve);
else
if ( isInitStage )
{
SubCurveIter iter = m_leftCurves->begin();
while ( iter != m_leftCurves->end() ) {
if ( m_traits->curve_is_same((*iter)->getCurve(), curve->getCurve())) {
m_leftCurves->erase(iter);
break;
}
++iter;
}
iter = m_leftCurves->begin();
while ( iter != m_leftCurves->end() &&
m_traits->curve_compare_at_x_right(curve->getCurve(),
(*iter)->getCurve(),
ref)
== LARGER)
if ( !m_isInitialized )
{
++iter;
}
if ( curve->isSourceLeftToTarget())
m_rightmostPointToLeft = curve->getSource();
else
m_rightmostPointToLeft = curve->getTarget();
m_isInitialized = true;
} else {
UpdateRightmostPoint(curve);
}
} else if ( !curve->isEndPoint(m_point) ) {
if ( iter == m_leftCurves->end() ||
!m_traits->curve_is_same((*iter)->getCurve(), curve->getCurve()))
{
m_leftCurves->insert(iter, curve);
}
}
if ( !curve->isEndPoint(m_point) )
m_isInternalIntersectionPoint = true;
}
/*! Adds a new curve that is defined to the right of the event point.
The insertion is performed so that the curves remain srted by their Y
values to theright of the event.
If the curve is already in the list of curves, it is removed and
re-inserted. This way the curves remain sorted.
@param curve a pointer to the curve.
*/
void addCurveToLeft1(SubCurve *curve)
{
if ( !m_isInitialized )
{
if ( curve->isSourceLeftToTarget())
m_rightmostPointToLeft = curve->getSource();
else
m_rightmostPointToLeft = curve->getTarget();
m_isInitialized = true;
}
UpdateRightmostPoint(curve);
if (m_leftCurves->empty())
// now insert the curve at the right place...
if (m_leftCurves->empty()) {
m_leftCurves->push_back(curve);
else
{
SubCurveIter iter = m_leftCurves->begin();
while ( iter != m_leftCurves->end() ) {
if ( m_traits->curve_is_same((*iter)->getCurve(), curve->getCurve())) {
m_leftCurves->erase(iter);
break;
}
++iter;
}
iter = m_leftCurves->begin();
while ( iter != m_leftCurves->end() &&
m_traits->curve_compare_at_x_right(curve->getCurve(),
(*iter)->getCurve(),
m_rightmostPointToLeft)
== LARGER)
{
++iter;
}
if ( iter == m_leftCurves->end() ||
!m_traits->curve_is_same((*iter)->getCurve(), curve->getCurve()))
{
m_leftCurves->insert(iter, curve);
}
return;
}
SubCurveIter iter = m_leftCurves->begin();
const X_curve_2 &cv = curve->getCurve();
// look for the curve, and if exists, erase it.
while ( iter != m_leftCurves->end() ) {
if ( (*iter)->getId() == curve->getId()) {
m_leftCurves->erase(iter);
break;
}
++iter;
}
// insert the curve so that the list remains sorted...
Comparison_result res = SMALLER;
iter = m_leftCurves->begin();
while ( iter != m_leftCurves->end() &&
(res = m_traits->curve_compare_at_x_right(cv, (*iter)->getCurve(),
ref )) == LARGER)
++iter;
while ( iter != m_leftCurves->end() &&
res == EQUAL &&
curve->getId() > (*iter)->getId() )
{
m_containsOverlap = true;
++iter;
if ( iter == m_leftCurves->end())
break;
res = m_traits->curve_compare_at_x_right(cv, (*iter)->getCurve(), ref);
}
// insert the curve. If the curve is already in the list, it is not added
if ( iter == m_leftCurves->end() ||
(*iter)->getId() != curve->getId())
{
m_leftCurves->insert(iter, curve);
}
}
/*! Adds a new curve that is defined to the right of the event point.
The insertion is performed so that the curves remain srted by their Y
values to theright of the event.
The insertion is performed so that the curves remain sorted by their Y
values to the right of the event.
@param curve a pointer to the curve.
*/
void addCurveToRight(SubCurve *curve)
{
if (m_rightCurves->empty())
m_rightCurves->push_back(curve);
else
{
SubCurveIter iter = m_rightCurves->begin();
while ( iter != m_rightCurves->end() &&
m_traits->curve_compare_at_x_right(curve->getCurve(),
(*iter)->getCurve(),
m_point)
== LARGER)
{
++iter;
}
if ( iter == m_rightCurves->end() ||
!m_traits->curve_is_same((*iter)->getCurve(), curve->getCurve()))
{
m_rightCurves->insert(iter, curve);
}
}
if ( !curve->isEndPoint(m_point) )
m_isInternalIntersectionPoint = true;
if (m_rightCurves->empty()) {
m_rightCurves->push_back(curve);
return;
}
SubCurveIter iter = m_rightCurves->begin();
Comparison_result res;
while ( (res = m_traits->curve_compare_at_x_right(curve->getCurve(),
(*iter)->getCurve(),
m_point)) == LARGER)
{
++iter;
if ( iter == m_rightCurves->end()) {
m_rightCurves->insert(iter, curve);
return;
}
}
while ( res == EQUAL && curve->getId() > (*iter)->getId() )
{
m_containsOverlap = true;
++iter;
if ( iter == m_rightCurves->end() ) {
m_rightCurves->insert(iter, curve);
return;
}
res = m_traits->curve_compare_at_x_right(curve->getCurve(),
(*iter)->getCurve(),
m_point);
}
// insert the curve only if it is not already in...
if ( (*iter)->getId() != curve->getId()) {
m_rightCurves->insert(iter, curve);
}
}
/*! Returns an iterator to the first curve to the left of the event */
SubCurveIter leftCurvesBegin() {
@ -258,41 +272,109 @@ public:
return m_point;
}
bool doesContainVerticalCurve() {
return m_verticalCurve != 0;
}
SubCurve *getVerticalCurve() {
return m_verticalCurve;
/*!
@return returns true if at least one of the curves passign
through the event is vertical.
*/
bool doesContainVerticalCurve() const {
return !m_verticalCurves.empty();
}
void addVerticalCurveXPoint(const Point_2 &p) {
/*! eturns the list of vertical curves passing through the event point.
@return a reference to the list of curves.
*/
VerticalCurveList &getVerticalCurves() {
return m_verticalCurves;
}
/*! Insert a new intersection point on any of the vertical curves.
The list of points is sorted by their y values.
If the requireSort flag is true, the appripriate place in the list
is searched for. If not, the point is assumed to have the largest y
value, and is inserted at the end of the list.
If the pioint already exists, the point is nott inserted again.
@param p a reference to the point
@param requireSort false if the point is to be added at the end
of the list.
*/
void addVerticalCurveXPoint(const Point_2 &p, bool requireSort=false) {
if ( m_verticalCurveXPoints.empty() )
{
m_verticalCurveXPoints.push_back(p);
return;
}
if (!m_traits->point_is_same(p, m_verticalCurveXPoints.back())) {
m_verticalCurveXPoints.push_back(p);
if ( !requireSort )
{
if (!m_traits->point_is_same(p, m_verticalCurveXPoints.back())) {
m_verticalCurveXPoints.push_back(p);
}
} else
{
VerticalXPointListIter iter = m_verticalCurveXPoints.begin();
while ( iter != m_verticalCurveXPoints.end() )
{
if ( m_traits->compare_y(*iter, p) == SMALLER )
++iter;
else
break;
}
if ( iter == m_verticalCurveXPoints.end() )
m_verticalCurveXPoints.push_back(p);
else if (!m_traits->point_is_same(p, *iter)) {
m_verticalCurveXPoints.insert(iter, p);
}
}
}
std::list<Point_2> &getVerticalCurveXPointList() {
/*!
Returns a referece to the list of intersection points on the
vertical curves passign through the event. If no vertical curves
pass through the event or no intersection curves exist, the list
will be empty.
@return a reference to the list of points.
*/
VerticalXPointList &getVerticalXPointList() {
return m_verticalCurveXPoints;
}
bool isInternalIntersectionPoint() {
return m_isInternalIntersectionPoint;
}
/*! Mark the event as an intersection point at an interior of a curve.
*/
void markInternalIntersectionPoint() {
m_isInternalIntersectionPoint = true;
}
/*!
@return returns true if the event is an intersection point at the
interior of at least one of the curves passing throuogh the event
point.
*/
bool isInternalIntersectionPoint() const {
return m_isInternalIntersectionPoint;
}
/*!
@return true if the any two curves in the event overlap, false otherwise.
*/
bool doesContainOverlap() const {
return m_containsOverlap;
}
#ifndef NDEBUG
void Print();
void PrintVerticalXPoints();
#endif
private:
/*! Whenever a new curve is added to the event at the initialization
stage, the right most end point to the left of the event point is
updated.
Precondition: the event is either the source or destination of the curve.
@param curve a pointer to a new curve added to the event.
*/
void UpdateRightmostPoint(SubCurve *curve)
{
if ( curve->isSourceLeftToTarget())
@ -308,6 +390,9 @@ private:
}
}
/*! The point of the event */
Point_2 m_point;
/*! A pointer to a traits class */
Traits *m_traits;
@ -319,12 +404,9 @@ private:
to the right of the point */
SubcurveContainer *m_rightCurves;
/*! The point of the event */
Point_2 m_point;
/*! The rightmost curve-end point that is to the left of the event
/*! The rightmost curve end point that is to the left of the event
point. This point is used as a reference point when curves are compared
only when new curves are added at the initialization stage.
to the left of the event point.
*/
Point_2 m_rightmostPointToLeft;
@ -334,17 +416,22 @@ private:
*/
bool m_isInitialized;
/*! a pointer to a vertical curve going through this event */
SubCurve *m_verticalCurve;
/*! a list of vertical curves going through this event */
VerticalCurveList m_verticalCurves;
/*! a list of intersection points on the vertical curve */
std::list<Point_2> m_verticalCurveXPoints;
/*! a list of intersection points on the vertical curves */
VerticalXPointList m_verticalCurveXPoints;
/*! a flag that inidcates whether the event is an "interior" intersection
point.
point, or just an end point of all curves passing through it.
*/
bool m_isInternalIntersectionPoint;
/*! true if any two curves passing through the event overlap. */
bool m_containsOverlap;
#ifndef NDEBUG
public:
int id;
@ -352,6 +439,10 @@ public:
};
#ifndef NDEBUG
template<class SweepLineTraits_2>
void
@ -369,15 +460,30 @@ Print()
}
std::cout << std::endl;
std::cout << "\tRight curves: \n" ;
for ( SubCurveIter iter = m_rightCurves->begin() ;
iter != m_rightCurves->end() ; ++iter )
for ( SubCurveIter iter1 = m_rightCurves->begin() ;
iter1 != m_rightCurves->end() ; ++iter1 )
{
std::cout << "\t";
(*iter)->Print();
(*iter1)->Print();
std::cout << "\n";
}
std::cout << std::endl;
}
template<class SweepLineTraits_2>
void
Sweep_line_event<SweepLineTraits_2>::
PrintVerticalXPoints()
{
std::cout << "Vertical intersection points for " << m_point << ":\n";
std::list<Point_2>::iterator iter = m_verticalCurveXPoints.begin();
while ( iter != m_verticalCurveXPoints.end() )
{
std::cout << "\t" << *iter << "\n";
++iter;
}
}
#endif // NDEBUG
CGAL_END_NAMESPACE

View File

@ -152,7 +152,9 @@ public:
if ( r == LARGER ) {
return false;
}
return false;
// r = EQUAL
return ( c1->getId() < c2->getId() );
}
void setReference(Point_2 point) {

View File

@ -40,9 +40,14 @@ public:
typedef typename Traits::Curve_2 Curve_2;
typedef typename Traits::X_curve_2 X_curve_2;
Sweep_line_subcurve(X_curve_2 &curve, Point_2 *reference,
Sweep_line_subcurve(int id, X_curve_2 &curve, Point_2 *reference,
SweepLineTraits_2 *traits);
int getId() const {
return m_id;
}
/*!
@return a reference to the curve
*/
@ -50,11 +55,6 @@ public:
return m_curve;
}
//void setCurve(X_curve_2 &curve) {
//m_curve = curve;
//}
/*! @return the pointer to the reference point */
const Point_2 *getReferencePoint() const {
return m_referencePoint;
@ -96,6 +96,7 @@ public:
bool isSource(const Point_2 &p) {
return m_traits->point_is_same(p, m_source);
}
bool isTarget(const Point_2 &p) {
return m_traits->point_is_same(p, m_target);
}
@ -172,12 +173,25 @@ public:
return getLeftEnd();
}
// returns true if the point is in the range of the curve and is not
// one of its ends
bool isPointInRange(const Point_2 &p)
{
if ( m_traits->curve_get_point_status(m_curve, p) != Traits::ON_CURVE )
return false;
if ( isEndPoint(p) )
return false;
return true;
}
#ifndef NDEBUG
void Print() const;
#endif
private:
int m_id;
/*! a pointer to the traits object */
Traits *m_traits;
@ -206,16 +220,12 @@ private:
/*! the target of the curve */
Point_2 m_target;
public:
#ifndef NDEBUG
int id;
#endif
};
template<class SweepLineTraits_2>
inline Sweep_line_subcurve<SweepLineTraits_2>::
Sweep_line_subcurve(X_curve_2 &curve, Point_2 *reference,
SweepLineTraits_2 *traits) : m_traits(traits)
Sweep_line_subcurve(int id, X_curve_2 &curve, Point_2 *reference,
SweepLineTraits_2 *traits) : m_id(id), m_traits(traits)
{
m_curve = curve;
m_referencePoint = reference;
@ -254,7 +264,7 @@ void
Sweep_line_subcurve<SweepLineTraits_2>::
Print() const
{
std::cout << "Curve " << id << " (" << m_curve << ") "
std::cout << "Curve " << m_id << " (" << m_curve << ") "
<< "last P = (" << m_lastPoint << ")" << std::endl;
}

File diff suppressed because it is too large Load Diff