mirror of https://github.com/CGAL/cgal
Added support for vertical curves and overlapping curves.
This commit is contained in:
parent
85f34687a0
commit
2f1daf97d2
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -152,7 +152,9 @@ public:
|
|||
if ( r == LARGER ) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
// r = EQUAL
|
||||
return ( c1->getId() < c2->getId() );
|
||||
}
|
||||
|
||||
void setReference(Point_2 point) {
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue