diff --git a/src/lib/marble/ClipPainter.cpp b/src/lib/marble/ClipPainter.cpp --- a/src/lib/marble/ClipPainter.cpp +++ b/src/lib/marble/ClipPainter.cpp @@ -16,13 +16,14 @@ #include "MarbleDebug.h" +#include namespace Marble { class ClipPainterPrivate { - public: +public: explicit ClipPainterPrivate( ClipPainter * parent ); ClipPainter * q; @@ -36,6 +37,13 @@ qreal m_top; qreal m_bottom; + QPointF m_topLeft; + QPointF m_topRight; + QPointF m_bottomRight; + QPointF m_bottomLeft; + + QPolygonF m_viewport; + // Used in the paint process of vectors.. int m_currentSector; int m_previousSector; @@ -43,9 +51,14 @@ // int m_debugNodeCount; QPointF m_currentPoint; - QPointF m_previousPoint; + QPointF m_previousPoint; + + bool m_clippedTwice; + inline int sector( const QPointF & point ) const; + inline int borderSector( const QPointF & point ) const; + inline bool isClockwise(const QPointF& pointA, const QPointF& pointB) const; inline QPointF clipTop( qreal m, const QPointF & point ) const; inline QPointF clipLeft( qreal m, const QPointF & point ) const; @@ -54,7 +67,7 @@ inline void initClipRect(); - inline void clipPolyObject ( const QPolygonF & sourcePolygon, + inline void clipPolyObject ( const QPolygonF & sourcePolygon, QVector & clippedPolyObjects, bool isClosed ); @@ -62,8 +75,8 @@ QVector & clippedPolyObjects, bool isClosed ); inline void clipOnce( QPolygonF & clippedPolyObject, - QVector & clippedPolyObjects, - bool isClosed ); + QVector & clippedPolyObjects, + bool isClosed ); inline void clipOnceCorner( QPolygonF & clippedPolyObject, QVector & clippedPolyObjects, const QPointF& corner, @@ -74,12 +87,15 @@ const QPointF& point, bool isClosed ) const; + inline void clipPolygon( QPolygonF & clippedPolyObject, + QVector & clippedPolyObjects, + bool isClosed ); - void labelPosition(const QPolygonF& polygon, QVector& labelNodes, - LabelPositionFlags labelPositionFlags); + void labelPosition( const QPolygonF & polygon, QVector& labelNodes, + LabelPositionFlags labelPositionFlags); bool pointAllowsLabel( const QPointF& point ); - QPointF interpolateLabelPoint( const QPointF& previousPoint, + QPointF interpolateLabelPoint( const QPointF& previousPoint, const QPointF& currentPoint, LabelPositionFlags labelPositionFlags ); @@ -92,6 +108,77 @@ int m_debugPolygonsLevel; }; +class Point { +public: + Point(const QPointF& point) : m_point(point), + m_isEntering(false), m_isLeaving(false), + m_nextBasePolygonPoint(nullptr), m_nextClipPolygonPoint(nullptr), + m_processed(false) + {} + + Point(const QPointF& point, bool isEntering, bool isLeaving) : m_point(point), + m_isEntering(isEntering), m_isLeaving(isLeaving), + m_nextBasePolygonPoint(nullptr), m_nextClipPolygonPoint(nullptr), + m_processed(false) + {} + + bool isEntering() const + { + return m_isEntering; + } + + bool isLeaving() const + { + return m_isLeaving; + } + + bool isProcessed() const + { + return m_processed; + } + + const QPointF& point() const + { + return m_point; + } + + const QSharedPointer& nextClipPolygonPoint() const + { + return m_nextClipPolygonPoint; + } + + const QSharedPointer& nextBasePolygonPoint() const + { + return m_nextBasePolygonPoint; + } + + void setNextClipPolygonPoint(const QSharedPointer& nextPoint) + { + this->m_nextClipPolygonPoint = nextPoint; + } + + void setNextBasePolygonPoint(const QSharedPointer& nextPoint) + { + this->m_nextBasePolygonPoint = nextPoint; + } + + void setProcessed(bool processed) + { + this->m_processed = processed; + } + +private: + + QPointF m_point; + bool m_isEntering; + bool m_isLeaving; + + QSharedPointer m_nextBasePolygonPoint; + QSharedPointer m_nextClipPolygonPoint; + + bool m_processed; +}; + } using namespace Marble; @@ -135,13 +222,13 @@ void ClipPainter::drawPolygon ( const QPolygonF & polygon, Qt::FillRule fillRule ) { - if ( d->m_doClip ) { + if ( d->m_doClip ) { d->initClipRect(); QVector clippedPolyObjects; d->clipPolyObject( polygon, clippedPolyObjects, true ); - foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) { + foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) { if ( clippedPolyObject.size() > 2 ) { // mDebug() << "Size: " << clippedPolyObject.size(); if (d->m_debugPolygonsLevel) { @@ -193,7 +280,7 @@ d->clipPolyObject( polygon, clippedPolyObjects, false ); - foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) { + foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) { if ( clippedPolyObject.size() > 1 ) { if (d->m_debugPolygonsLevel) { QPen pen = QPainter::pen(); @@ -236,8 +323,8 @@ } } -void ClipPainter::drawPolyline(const QPolygonF & polygon, QVector& labelNodes, - LabelPositionFlags positionFlags) +void ClipPainter::drawPolyline( const QPolygonF & polygon, QVector& labelNodes, + LabelPositionFlags positionFlags) { if ( d->m_doClip ) { d->initClipRect(); @@ -245,7 +332,7 @@ d->clipPolyObject( polygon, clippedPolyObjects, false ); - foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) { + foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) { if (d->m_debugPolygonsLevel) { QPen pen = QPainter::pen(); QPen originalPen = pen; @@ -288,8 +375,8 @@ } } -void ClipPainterPrivate::labelPosition(const QPolygonF & polygon, QVector& labelNodes, - LabelPositionFlags labelPositionFlags) +void ClipPainterPrivate::labelPosition( const QPolygonF & polygon, QVector& labelNodes, + LabelPositionFlags labelPositionFlags) { bool currentAllowsLabel = false; @@ -316,7 +403,7 @@ if ( currentAllowsLabel ) { // As polygon.size() > 0 it's ensured that it-1 exists. QPointF node = interpolateLabelPoint( polygon.at( it -1 ), polygon.at( it ), - labelPositionFlags ); + labelPositionFlags ); if ( node != QPointF( -1.0, -1.0 ) ) { labelNodes << node; } @@ -336,7 +423,7 @@ if ( currentAllowsLabel ) { QPointF node = interpolateLabelPoint( polygon.at( it + 1 ), polygon.at( it ), - labelPositionFlags ); + labelPositionFlags ); if ( node != QPointF( -1.0, -1.0 ) ) { labelNodes << node; } @@ -349,7 +436,7 @@ bool ClipPainterPrivate::pointAllowsLabel( const QPointF& point ) { - if ( point.x() > m_labelAreaMargin && point.x() < q->viewport().width() - m_labelAreaMargin + if ( point.x() > m_labelAreaMargin && point.x() < q->viewport().width() - m_labelAreaMargin && point.y() > m_labelAreaMargin && point.y() < q->viewport().height() - m_labelAreaMargin ) { return true; } @@ -365,7 +452,7 @@ if ( labelPositionFlags.testFlag( IgnoreXMargin ) ) { return QPointF( -1.0, -1.0 ); } - return QPointF( m_labelAreaMargin, + return QPointF( m_labelAreaMargin, previousPoint.y() + ( m_labelAreaMargin - previousPoint.x() ) * m ); } else if ( previousPoint.x() >= q->viewport().width() - m_labelAreaMargin ) { @@ -373,27 +460,27 @@ return QPointF( -1.0, -1.0 ); } return QPointF( q->viewport().width() - m_labelAreaMargin, - previousPoint.y() - - ( previousPoint.x() - q->viewport().width() + m_labelAreaMargin ) * m ); + previousPoint.y() - + ( previousPoint.x() - q->viewport().width() + m_labelAreaMargin ) * m ); } if ( previousPoint.y() <= m_labelAreaMargin ) { if ( labelPositionFlags.testFlag( IgnoreYMargin ) ) { return QPointF( -1.0, -1.0 ); } - return QPointF( previousPoint.x() + ( m_labelAreaMargin - previousPoint.y() ) / m, + return QPointF( previousPoint.x() + ( m_labelAreaMargin - previousPoint.y() ) / m, m_labelAreaMargin ); - } + } else if ( previousPoint.y() >= q->viewport().height() - m_labelAreaMargin ) { if ( labelPositionFlags.testFlag( IgnoreYMargin ) ) { return QPointF( -1.0, -1.0 ); } - return QPointF( previousPoint.x() - - ( previousPoint.y() - q->viewport().height() + m_labelAreaMargin ) / m, - q->viewport().height() - m_labelAreaMargin ); + return QPointF( previousPoint.x() - + ( previousPoint.y() - q->viewport().height() + m_labelAreaMargin ) / m, + q->viewport().height() - m_labelAreaMargin ); } -// mDebug() << Q_FUNC_INFO << "Previous and current node position are allowed!"; + // mDebug() << Q_FUNC_INFO << "Previous and current node position are allowed!"; return QPointF( -1.0, -1.0 ); } @@ -404,10 +491,16 @@ m_right(0.0), m_top(0.0), m_bottom(0.0), + m_topLeft(QPointF()), + m_topRight(QPointF()), + m_bottomRight(QPointF()), + m_bottomLeft(QPointF()), + m_viewport(QPolygonF()), m_currentSector(4), m_previousSector(4), m_currentPoint(QPointF()), - m_previousPoint(QPointF()), + m_previousPoint(QPointF()), + m_clippedTwice(false), m_labelAreaMargin(10.0), m_debugPolygonsLevel(0) { @@ -416,12 +509,21 @@ void ClipPainterPrivate::initClipRect () { - qreal penHalfWidth = q->pen().widthF() / 2.0 + 1.0; + // qreal penHalfWidth = q->pen().widthF() / 2.0 + 1.0; + + // Only for testing purposes + m_left = 20; + m_right = (qreal)(q->device()->width()) - 20; + m_top = 20; + m_bottom = (qreal)(q->device()->height()) - 20; - m_left = -penHalfWidth; - m_right = (qreal)(q->device()->width()) + penHalfWidth; - m_top = -penHalfWidth; - m_bottom = (qreal)(q->device()->height()) + penHalfWidth; + m_topLeft = QPointF(m_left, m_top); + m_topRight = QPointF(m_right, m_top); + m_bottomRight = QPointF(m_right, m_bottom); + m_bottomLeft = QPointF(m_left, m_bottom); + + m_viewport.clear(); + m_viewport << m_topLeft << m_topRight << m_bottomRight << m_bottomLeft; } qreal ClipPainterPrivate::_m( const QPointF & start, const QPointF & end ) @@ -429,12 +531,12 @@ qreal divisor = end.x() - start.x(); if ( std::fabs( divisor ) < 0.000001 ) { // this is in screencoordinates so the difference - // between 0, 0.000001 and -0.000001 isn't visible at all + // between 0, 0.000001 and -0.000001 isn't visible at all divisor = 0.000001; } - return ( end.y() - start.y() ) - / divisor; + return ( end.y() - start.y() ) + / divisor; } @@ -487,17 +589,71 @@ // By adding xSector and ySector we get a // sector number of the values shown in the ASCII-art graph above. return ySector + xSector; +} +// Determines that the point on which border or corner is exactly on, 4 otherwise. +int ClipPainterPrivate::borderSector( const QPointF & point ) const +{ + if(point.x() == m_left) { + return 3; + } else if (point.x() == m_right) { + return 5; + } else if (point.y() == m_top) { + return 1; + } else if (point.y() == m_bottom) { + return 7; + } else { + return sector(point); + } } -void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon, +bool ClipPainterPrivate::isClockwise(const QPointF& pointA, const QPointF& pointB) const +{ + QPointF middlePoint((m_left + m_right)/2.0, -(m_top + m_bottom)/2.0); + + QPointF vecA(QPointF(pointA.x(), -pointA.y()) - middlePoint); + QPointF vecB(QPointF(pointB.x(), -pointB.y()) - middlePoint); + + qreal angle = atan2(vecA.x()*vecB.y() - vecB.x()*vecA.y(), vecA.x()*vecB.x() + vecA.y()*vecB.y()) * RAD2DEG; + mDebug() << "isClockwise angle:" << angle; + return angle < 0; +} + +void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon, QVector & clippedPolyObjects, bool isClosed ) { - // mDebug() << "ClipPainter enabled." ; + QList> basePolygon; + QList> clipPolygon; + QList> intersections; + + QList> intersectionsTop; + QList> intersectionsRight; + QList> intersectionsBottom; + QList> intersectionsLeft; + + auto appendToIntersectionKind = [&](QSharedPointer& intersection) { + switch(borderSector(intersection->point())) { + case 1: + intersectionsTop << intersection; + break; + case 3: + intersectionsLeft << intersection; + break; + case 5: + intersectionsRight << intersection; + break; + case 7: + intersectionsBottom << intersection; + break; + default: break; + } + }; - // Only create a new polyObject as soon as we know for sure that - // the current point is on the screen. + bool intersectionAdded = false; + + // Only create a new polyObject as soon as we know for sure that + // the current point is on the screen. QPolygonF clippedPolyObject = QPolygonF(); const QVector::const_iterator itStartPoint = polygon.constBegin(); @@ -510,6 +666,9 @@ bool processingLastNode = false; + mDebug() << "\n"; + mDebug() << "New polygon, size:" << polygon.size(); + while ( itPoint != itEndPoint ) { m_currentPoint = (*itPoint); // mDebug() << "m_currentPoint.x()" << m_currentPoint.x() << "m_currentPOint.y()" << m_currentPoint.y(); @@ -522,6 +681,9 @@ if ( isClosed ) { m_previousPoint = polygon.last(); + QSharedPointer firstPoint = QSharedPointer(new Point(m_currentPoint)); + basePolygon << firstPoint; + // Figure out the sector of the previous point. m_previousSector = sector( m_previousPoint ); } @@ -538,29 +700,78 @@ // only one interpolation for both cases. clipOnce( clippedPolyObject, clippedPolyObjects, isClosed ); - } - else { + + if(isClosed) { + + if(!clippedPolyObject.isEmpty()) { + + QSharedPointer intersection = QSharedPointer(new Point(clippedPolyObject.last(), m_currentSector == 4, m_previousSector == 4)); + intersections << intersection; + basePolygon.last()->setNextBasePolygonPoint(intersection); + + QSharedPointer nextPoint = QSharedPointer(new Point(m_currentPoint)); + basePolygon << nextPoint; + intersections.last()->setNextBasePolygonPoint(nextPoint); + + appendToIntersectionKind(intersection); + + intersectionAdded = true; + } + } + } else { // This case mostly deals with lines that reach from one // sector that is located off screen to another one that - // is located off screen. In this situation the line + // is located off screen. In this situation the line // can get clipped once, twice, or not at all. + m_clippedTwice = false; clipMultiple( clippedPolyObject, clippedPolyObjects, isClosed ); + + if(isClosed && m_clippedTwice) { + mDebug() << "Clipped twice"; + QPointF firstAddedPoint = clippedPolyObject.at(clippedPolyObject.size()-2); + QPointF secondAddedPoint = clippedPolyObject.last(); + + int firstAddedPointSector = borderSector(firstAddedPoint); + int secondAddedPointSector = borderSector(secondAddedPoint); + + QSharedPointer intersectionFirst = QSharedPointer(new Point(firstAddedPoint, firstAddedPointSector == m_previousSector, firstAddedPointSector == m_currentSector)); + intersections << intersectionFirst; + QSharedPointer intersectionSecond = QSharedPointer(new Point(secondAddedPoint, secondAddedPointSector == m_previousSector, secondAddedPointSector == m_currentSector)); + intersections << intersectionSecond; + + basePolygon.last()->setNextBasePolygonPoint(intersectionFirst); + intersectionFirst->setNextBasePolygonPoint(intersectionSecond); + QSharedPointer nextPoint = QSharedPointer(new Point(m_currentPoint)); + basePolygon << nextPoint; + intersectionSecond->setNextBasePolygonPoint(basePolygon.last()); + + appendToIntersectionKind(intersectionFirst); + + appendToIntersectionKind(intersectionSecond); + + intersectionAdded = true; + } } m_previousSector = m_currentSector; } - // If the current point is onscreen, just add it to our final polygon. - if ( m_currentSector == 4 ) { - - clippedPolyObject << m_currentPoint; -#ifdef MARBLE_DEBUG - ++(m_debugNodeCount); -#endif + if (isClosed) { + if(!intersectionAdded) { + QSharedPointer nextPoint = QSharedPointer(new Point(m_currentPoint)); + if(!basePolygon.isEmpty()) { + basePolygon.last()->setNextBasePolygonPoint(nextPoint); + } + basePolygon << nextPoint; + } else { + intersectionAdded = false; + } } m_previousPoint = m_currentPoint; - + if(m_currentSector == 4) { + clippedPolyObject << m_currentPoint; + } // Now let's handle the case where we have a (closed) polygon and where the // last point of the polyline is outside the viewport and the start point // is inside the viewport. This needs special treatment @@ -575,10 +786,114 @@ } } - // Only add the pointer if there's node data available. - if ( !clippedPolyObject.isEmpty() ) { + if(isClosed) { + if(!basePolygon.isEmpty()) { + basePolygon.last()->setNextBasePolygonPoint(basePolygon.first()); + } + + if(!intersections.isEmpty()) { + + mDebug() << "intersections count:" << intersections.size(); + mDebug() << "intersectionsTop count:" << intersectionsTop.size(); + mDebug() << "intersectionsRight count:" << intersectionsRight.size(); + mDebug() << "intersectionsBottom count:" << intersectionsBottom.size(); + mDebug() << "intersectionsLeft count:" << intersectionsLeft.size(); + + + clippedPolyObjects.clear(); + clippedPolyObject = QPolygonF(); + + std::sort(intersectionsTop.begin(), intersectionsTop.end(), [](QSharedPointer& A, QSharedPointer& B) { + return A->point().x() < B->point().x(); + }); + + std::sort(intersectionsRight.begin(), intersectionsRight.end(), [](QSharedPointer& A, QSharedPointer& B) { + return A->point().y() < B->point().y(); + }); + + std::sort(intersectionsBottom.begin(), intersectionsBottom.end(), [](QSharedPointer& A, QSharedPointer& B) { + return B->point().x() < A->point().x(); + }); + + std::sort(intersectionsLeft.begin(), intersectionsLeft.end(), [](QSharedPointer& A, QSharedPointer& B) { + return B->point().y() < A->point().y(); + }); + + clipPolygon << QSharedPointer(new Point(m_topLeft)) << intersectionsTop << + QSharedPointer(new Point(m_topRight)) << intersectionsRight << + QSharedPointer(new Point(m_bottomRight)) << intersectionsBottom << + QSharedPointer(new Point(m_bottomLeft)) << intersectionsLeft; + + for(int i = 0; i < clipPolygon.size() - 1; ++i) { + clipPolygon[i]->setNextClipPolygonPoint(clipPolygon[i+1]); + } + clipPolygon.last()->setNextClipPolygonPoint(clipPolygon.first()); + + bool iterateBasePolygon = false; + + for(const auto& intersection : intersections) { + if(intersection->isEntering() && !intersection->isProcessed()) { + iterateBasePolygon = true; + + QSharedPointer it = intersection; + clippedPolyObject << it->point(); + it->setProcessed(true); + + do { + if(iterateBasePolygon) { + it = it->nextBasePolygonPoint(); + if(it->isLeaving()) { + iterateBasePolygon = false; + it->setProcessed(true); + } else if(it->isEntering()) { + it->setProcessed(true); + } + } else { + it = it->nextClipPolygonPoint(); + if(it->isEntering()) { + iterateBasePolygon = true; + it->setProcessed(true); + } else if(it->isLeaving()) { + it->setProcessed(true); + } + } + clippedPolyObject << it->point(); + + // To avoid crashes. + // Needs to be investigated + if(clippedPolyObject.size() > basePolygon.size()) { + mDebug() << "Something went wrong, exiting current clipping loop..."; + break; + } + + } while(clippedPolyObject.first() != clippedPolyObject.last()); + + clippedPolyObjects << clippedPolyObject; + clippedPolyObject = QPolygonF(); + } + } + } + else { + if(polygon.boundingRect().contains(m_viewport.boundingRect())) { + clippedPolyObjects.clear(); + clippedPolyObject = m_viewport; + } + } + } + + if(!clippedPolyObject.isEmpty()) { clippedPolyObjects << clippedPolyObject; } + +} + +void ClipPainterPrivate::clipPolygon( QPolygonF & clippedPolyObject, + QVector & clippedPolyObjects, + bool isClosed ) +{ + Q_UNUSED(clippedPolyObject) + Q_UNUSED(clippedPolyObjects) + Q_UNUSED(isClosed) } @@ -589,9 +904,11 @@ Q_UNUSED( clippedPolyObjects ) Q_UNUSED( isClosed ) - // Take care of adding nodes in the image corners if the iterator + // Take care of adding nodes in the image corners if the iterator // traverses off screen sections. + int numAddedPoints = 0; + qreal m = _m( m_previousPoint, m_currentPoint ); switch ( m_currentSector ) { @@ -603,13 +920,19 @@ if ( pointRight.y() > m_top ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; } - if ( pointTop.x() >= m_left && pointTop.x() < m_right ) + if ( pointTop.x() >= m_left && pointTop.x() < m_right ) { clippedPolyObject << pointTop; - if ( pointLeft.y() > m_top ) + numAddedPoints++; + } + if ( pointLeft.y() > m_top ) { clippedPolyObject << pointLeft; + numAddedPoints++; + } } else if ( m_previousSector == 7 ) { QPointF pointBottom = clipBottom( m, m_previousPoint ); @@ -618,13 +941,19 @@ if ( pointBottom.x() > m_left ) { clippedPolyObject << pointBottom; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; } - if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom ) + if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; - if ( pointTop.x() > m_left ) + numAddedPoints++; + } + if ( pointTop.x() > m_left ) { clippedPolyObject << pointTop; + numAddedPoints++; + } } else if ( m_previousSector == 8 ) { QPointF pointBottom = clipBottom( m, m_previousPoint ); @@ -632,22 +961,35 @@ QPointF pointTop = clipTop( m, m_currentPoint ); QPointF pointLeft = clipLeft( m, m_currentPoint ); - if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) + if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; - if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; - if ( pointTop.x() > m_left && pointTop.x() < m_right ) + numAddedPoints++; + } + if ( pointTop.x() > m_left && pointTop.x() < m_right ) { clippedPolyObject << pointTop; - if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; - - if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom ) + numAddedPoints++; + } + + if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom ) { clippedPolyObject << QPointF( m_left, m_bottom ); - if ( pointTop.x() >= m_right && pointRight.y() <= m_top ) + numAddedPoints++; + } + if ( pointTop.x() >= m_right && pointRight.y() <= m_top ) { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; + } } clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; break; case 1: @@ -657,11 +999,15 @@ if ( pointLeft.y() > m_top ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; } - if ( pointTop.x() > m_left ) + if ( pointTop.x() > m_left ) { clippedPolyObject << pointTop; + numAddedPoints++; + } } else if ( m_previousSector == 5 ) { QPointF pointRight = clipRight( m, m_previousPoint ); @@ -669,44 +1015,62 @@ if ( pointRight.y() > m_top ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; } - if ( pointTop.x() < m_right ) + if ( pointTop.x() < m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; + } } else if ( m_previousSector == 6 ) { QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_previousPoint ); QPointF pointTop = clipTop( m, m_currentPoint ); - if ( pointBottom.x() > m_left ) + if ( pointBottom.x() > m_left ) { clippedPolyObject << pointBottom; - if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; + } if ( pointTop.x() > m_left ) { clippedPolyObject << pointTop; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; } } else if ( m_previousSector == 7 ) { clippedPolyObject << clipBottom( m, m_previousPoint ); + numAddedPoints++; clippedPolyObject << clipTop( m, m_currentPoint ); + numAddedPoints++; } else if ( m_previousSector == 8 ) { QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_previousPoint ); QPointF pointTop = clipTop( m, m_currentPoint ); - if ( pointBottom.x() < m_right ) + if ( pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; - if ( pointRight.y() > m_top && pointRight.y() <= m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() > m_top && pointRight.y() <= m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; + } if ( pointTop.x() < m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; } } break; @@ -719,13 +1083,19 @@ if ( pointLeft.y() > m_top ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; } - if ( pointTop.x() > m_left && pointTop.x() <= m_right ) + if ( pointTop.x() > m_left && pointTop.x() <= m_right ) { clippedPolyObject << pointTop; - if ( pointRight.y() > m_top ) + numAddedPoints++; + } + if ( pointRight.y() > m_top ) { clippedPolyObject << pointRight; + numAddedPoints++; + } } else if ( m_previousSector == 7 ) { QPointF pointBottom = clipBottom( m, m_previousPoint ); @@ -734,13 +1104,19 @@ if ( pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; } - if ( pointRight.y() >= m_top && pointRight.y() < m_bottom ) + if ( pointRight.y() >= m_top && pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; - if ( pointTop.x() < m_right ) + numAddedPoints++; + } + if ( pointTop.x() < m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; + } } else if ( m_previousSector == 6 ) { QPointF pointBottom = clipBottom( m, m_previousPoint ); @@ -748,22 +1124,35 @@ QPointF pointTop = clipTop( m, m_currentPoint ); QPointF pointRight = clipRight( m, m_previousPoint ); - if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) + if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; - if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; - if ( pointTop.x() > m_left && pointTop.x() < m_right ) + numAddedPoints++; + } + if ( pointTop.x() > m_left && pointTop.x() < m_right ) { clippedPolyObject << pointTop; - if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; - - if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom ) + numAddedPoints++; + } + + if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom ) { clippedPolyObject << QPointF( m_right, m_bottom ); - if ( pointTop.x() <= m_left && pointLeft.y() <= m_top ) + numAddedPoints++; + } + if ( pointTop.x() <= m_left && pointLeft.y() <= m_top ) { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; + } } clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; break; case 3: @@ -771,24 +1160,32 @@ QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_currentPoint ); - if ( pointBottom.x() > m_left ) + if ( pointBottom.x() > m_left ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } if ( pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; } } else if ( m_previousSector == 1 ) { QPointF pointTop = clipTop( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_currentPoint ); - if ( pointTop.x() > m_left ) + if ( pointTop.x() > m_left ) { clippedPolyObject << pointTop; + numAddedPoints++; + } if ( pointLeft.y() > m_top ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; } } else if ( m_previousSector == 8 ) { @@ -796,33 +1193,47 @@ QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_currentPoint ); - if ( pointRight.y() < m_bottom ) + if ( pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; - if ( pointBottom.x() > m_left && pointBottom.x() <= m_right ) + numAddedPoints++; + } + if ( pointBottom.x() > m_left && pointBottom.x() <= m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } if ( pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; } } else if ( m_previousSector == 5 ) { clippedPolyObject << clipRight( m, m_previousPoint ); + numAddedPoints++; clippedPolyObject << clipLeft( m, m_currentPoint ); + numAddedPoints++; } else if ( m_previousSector == 2 ) { QPointF pointRight = clipRight( m, m_previousPoint ); QPointF pointTop = clipTop( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_currentPoint ); - if ( pointRight.y() > m_top ) + if ( pointRight.y() > m_top ) { clippedPolyObject << pointRight; - if ( pointTop.x() > m_left && pointTop.x() <= m_right ) + numAddedPoints++; + } + if ( pointTop.x() > m_left && pointTop.x() <= m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; + } if ( pointLeft.y() > m_top ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; } } break; @@ -832,24 +1243,32 @@ QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_currentPoint ); - if ( pointBottom.x() < m_right ) + if ( pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } if ( pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; } } else if ( m_previousSector == 1 ) { QPointF pointTop = clipTop( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_currentPoint ); - if ( pointTop.x() < m_right ) + if ( pointTop.x() < m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; + } if ( pointRight.y() > m_top ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; } } else if ( m_previousSector == 6 ) { @@ -857,33 +1276,47 @@ QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_currentPoint ); - if ( pointLeft.y() < m_bottom ) + if ( pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; - if ( pointBottom.x() >= m_left && pointBottom.x() < m_right ) + numAddedPoints++; + } + if ( pointBottom.x() >= m_left && pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } if ( pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; } } else if ( m_previousSector == 3 ) { clippedPolyObject << clipLeft( m, m_previousPoint ); + numAddedPoints++; clippedPolyObject << clipRight( m, m_currentPoint ); + numAddedPoints++; } else if ( m_previousSector == 0 ) { QPointF pointLeft = clipLeft( m, m_previousPoint ); QPointF pointTop = clipTop( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_currentPoint ); - if ( pointLeft.y() > m_top ) + if ( pointLeft.y() > m_top ) { clippedPolyObject << pointLeft; - if ( pointTop.x() >= m_left && pointTop.x() < m_right ) + numAddedPoints++; + } + if ( pointTop.x() >= m_left && pointTop.x() < m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; + } if ( pointRight.y() > m_top ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; } } break; @@ -896,13 +1329,19 @@ if ( pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; } - if ( pointBottom.x() >= m_left && pointBottom.x() < m_right ) + if ( pointBottom.x() >= m_left && pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; - if ( pointLeft.y() < m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; + } } else if ( m_previousSector == 1 ) { QPointF pointTop = clipTop( m, m_previousPoint ); @@ -911,13 +1350,19 @@ if ( pointTop.x() > m_left ) { clippedPolyObject << pointTop; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; } - if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom ) + if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom ) { clippedPolyObject << pointLeft; - if ( pointBottom.x() > m_left ) + numAddedPoints++; + } + if ( pointBottom.x() > m_left ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } } else if ( m_previousSector == 2 ) { QPointF pointTop = clipTop( m, m_currentPoint ); @@ -925,22 +1370,35 @@ QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_currentPoint ); - if ( pointTop.x() > m_left && pointTop.x() < m_right ) + if ( pointTop.x() > m_left && pointTop.x() < m_right ) { clippedPolyObject << pointTop; - if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; - if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) + numAddedPoints++; + } + if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; - if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; - - if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom ) + numAddedPoints++; + } + + if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom ) { clippedPolyObject << QPointF( m_right, m_bottom ); - if ( pointTop.x() <= m_left && pointLeft.y() <= m_top ) + numAddedPoints++; + } + if ( pointTop.x() <= m_left && pointLeft.y() <= m_top ) { clippedPolyObject << QPointF( m_left, m_top ); + numAddedPoints++; + } } clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; break; case 7: @@ -950,11 +1408,15 @@ if ( pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; } - if ( pointBottom.x() > m_left ) + if ( pointBottom.x() > m_left ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } } else if ( m_previousSector == 5 ) { QPointF pointRight = clipRight( m, m_previousPoint ); @@ -962,44 +1424,62 @@ if ( pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; } - if ( pointBottom.x() < m_right ) + if ( pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } } else if ( m_previousSector == 0 ) { QPointF pointTop = clipTop( m, m_previousPoint ); QPointF pointLeft = clipLeft( m, m_previousPoint ); QPointF pointBottom = clipBottom( m, m_currentPoint ); - if ( pointTop.x() > m_left ) + if ( pointTop.x() > m_left ) { clippedPolyObject << pointTop; - if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; + } if ( pointBottom.x() > m_left ) { clippedPolyObject << pointBottom; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; } } else if ( m_previousSector == 1 ) { clippedPolyObject << clipTop( m, m_previousPoint ); + numAddedPoints++; clippedPolyObject << clipBottom( m, m_currentPoint ); + numAddedPoints++; } else if ( m_previousSector == 2 ) { QPointF pointTop = clipTop( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_previousPoint ); QPointF pointBottom = clipBottom( m, m_currentPoint ); - if ( pointTop.x() < m_right ) + if ( pointTop.x() < m_right ) { clippedPolyObject << pointTop; - if ( pointRight.y() >= m_top && pointRight.y() < m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() >= m_top && pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; + } if ( pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; } } break; @@ -1012,13 +1492,19 @@ if ( pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_left, m_bottom ); + numAddedPoints++; } - if ( pointBottom.x() > m_left && pointBottom.x() <= m_right ) + if ( pointBottom.x() > m_left && pointBottom.x() <= m_right ) { clippedPolyObject << pointBottom; - if ( pointRight.y() < m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; + numAddedPoints++; + } } else if ( m_previousSector == 1 ) { QPointF pointTop = clipTop( m, m_previousPoint ); @@ -1027,13 +1513,19 @@ if ( pointTop.x() < m_right ) { clippedPolyObject << pointTop; + numAddedPoints++; } else { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; } - if ( pointRight.y() > m_top && pointRight.y() <= m_bottom ) + if ( pointRight.y() > m_top && pointRight.y() <= m_bottom ) { clippedPolyObject << pointRight; - if ( pointBottom.x() < m_right ) + numAddedPoints++; + } + if ( pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; + numAddedPoints++; + } } else if ( m_previousSector == 0 ) { QPointF pointTop = clipTop( m, m_currentPoint ); @@ -1041,33 +1533,50 @@ QPointF pointBottom = clipBottom( m, m_previousPoint ); QPointF pointRight = clipRight( m, m_previousPoint ); - if ( pointTop.x() > m_left && pointTop.x() < m_right ) + if ( pointTop.x() > m_left && pointTop.x() < m_right ) { clippedPolyObject << pointTop; - if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) + numAddedPoints++; + } + if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) { clippedPolyObject << pointLeft; - if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) + numAddedPoints++; + } + if ( pointBottom.x() > m_left && pointBottom.x() < m_right ) { clippedPolyObject << pointBottom; - if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) + numAddedPoints++; + } + if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) { clippedPolyObject << pointRight; - - if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom ) + numAddedPoints++; + } + + if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom ) { clippedPolyObject << QPointF( m_left, m_bottom ); - if ( pointTop.x() >= m_right && pointRight.y() <= m_top ) + numAddedPoints++; + } + if ( pointTop.x() >= m_right && pointRight.y() <= m_top ) { clippedPolyObject << QPointF( m_right, m_top ); + numAddedPoints++; + } } clippedPolyObject << QPointF( m_right, m_bottom ); + numAddedPoints++; break; default: - break; + break; + } + + if(numAddedPoints == 2) { + m_clippedTwice = true; } } void ClipPainterPrivate::clipOnceCorner( QPolygonF & clippedPolyObject, QVector & clippedPolyObjects, const QPointF& corner, - const QPointF& point, + const QPointF& point, bool isClosed ) const { Q_UNUSED( clippedPolyObjects ) @@ -1100,7 +1609,8 @@ // Disappearing clippedPolyObject << point; if ( !isClosed ) { - clippedPolyObjects << clippedPolyObject; + clippedPolyObjects << clippedPolyObject; + clippedPolyObject = QPolygonF(); } } } @@ -1115,7 +1625,7 @@ // Calculating the slope. qreal m = _m( m_previousPoint, m_currentPoint ); - // Calculate in which sector the end of the line is located that is off screen + // Calculate in which sector the end of the line is located that is off screen int offscreenpos = ( m_currentSector == 4 ) ? m_previousSector : m_currentSector; // "Rise over run" for all possible situations . @@ -1165,7 +1675,7 @@ clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_right, m_bottom ), point, isClosed ); break; default: - break; + break; } } diff --git a/src/lib/marble/GeoPainter.cpp b/src/lib/marble/GeoPainter.cpp --- a/src/lib/marble/GeoPainter.cpp +++ b/src/lib/marble/GeoPainter.cpp @@ -202,7 +202,7 @@ { const bool antialiased = mapQuality == HighQuality || mapQuality == PrintQuality; setRenderHint( QPainter::Antialiasing, antialiased ); - ClipPainter::setScreenClip(false); + ClipPainter::setScreenClip(true); }