Skip to content

Commit 37171dc

Browse files
author
Sandro Santilli
committed
Fix QgsRubberBand refresh
- Fixes invalid calculation of rubberband boundingRect - Scales icon and pen width with rubberband when computing rect - Recompute rubberband extent on zoom/pan Fix #12392 Includes testcase (backport of master commits d43d8bf 84d47c9 a844bfa)
1 parent da527e7 commit 37171dc

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

src/gui/qgsrubberband.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@ void QgsRubberBand::updateRect()
535535

536536
const QgsMapToPixel& m2p = *( mMapCanvas->getCoordinateTransform() );
537537

538-
qreal w = ( mIconSize - 1 ) / 2 + mPen.width();
538+
qreal res = m2p.mapUnitsPerPixel();
539+
qreal w = ( ( mIconSize - 1 ) / 2 + mPen.width() ) / res;
539540

540541
QgsRectangle r;
541542
for ( int i = 0; i < mPoints.size(); ++i )
@@ -547,14 +548,22 @@ void QgsRubberBand::updateRect()
547548
QgsPoint p( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
548549
p = m2p.transform( p );
549550
QgsRectangle rect( p.x() - w, p.y() - w, p.x() + w, p.y() + w );
550-
r.combineExtentWith( &rect );
551+
552+
if ( r.isEmpty() )
553+
{
554+
// Get rectangle of the first point
555+
r = rect;
556+
}
557+
else
558+
{
559+
r.combineExtentWith( &rect );
560+
}
551561
}
552562
}
553563

554564
// This is an hack to pass QgsMapCanvasItem::setRect what it
555565
// expects (encoding of position and size of the item)
556566
QgsPoint topLeft = m2p.toMapPoint( r.xMinimum(), r.yMinimum() );
557-
double res = m2p.mapUnitsPerPixel();
558567
QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res );
559568

560569
setRect( rect );
@@ -563,7 +572,12 @@ void QgsRubberBand::updateRect()
563572

564573
void QgsRubberBand::updatePosition( )
565574
{
566-
// nothing to do here...
575+
// re-compute rectangle
576+
// See http://hub.qgis.org/issues/12392
577+
// NOTE: could be optimized by saving map-extent
578+
// of rubberband and simply re-projecting
579+
// that to device-rectange on "updatePosition"
580+
updateRect();
567581
}
568582

569583
void QgsRubberBand::setTranslationOffset( double dx, double dy )

tests/src/gui/testqgsrubberband.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class TestQgsRubberband : public QObject
4545
void cleanup(); // will be called after every testfunction.
4646

4747
void testAddSingleMultiGeometries(); //test for #7728
48+
void testBoundingRect(); //test for #12392
4849

4950
private:
5051
QgsMapCanvas* mCanvas;
@@ -107,10 +108,53 @@ void TestQgsRubberband::testAddSingleMultiGeometries()
107108
QVERIFY( mRubberband->numberOfVertices() == 15 );
108109
}
109110

110-
QTEST_MAIN( TestQgsRubberband )
111-
#include "testqgsrubberband.moc"
112111

112+
void TestQgsRubberband::testBoundingRect()
113+
{
114+
QSizeF mapSize = mCanvas->mapSettings().outputSize();
115+
116+
// Set extent to match canvas size.
117+
// This is to ensure a 1:1 scale
118+
mCanvas->setExtent( QgsRectangle( QRectF(
119+
QPointF(0,0), mapSize
120+
) ) );
121+
QCOMPARE( mCanvas->mapUnitsPerPixel (), 1.0 );
122+
123+
// Polygon extent is 10,10 to 30,30
124+
QSharedPointer<QgsGeometry> geom( QgsGeometry::fromWkt(
125+
"POLYGON((10 10,10 30,30 30,30 10,10 10))"
126+
) );
127+
mRubberband = new QgsRubberBand( mCanvas, mPolygonLayer->geometryType() );
128+
mRubberband->setIconSize( 5 ); // default, but better be explicit
129+
mRubberband->setWidth( 1 ); // default, but better be explicit
130+
mRubberband->addGeometry( geom.data(), mPolygonLayer );
131+
132+
// 20 pixels for the extent + 3 for pen & icon per side + 2 of padding
133+
QCOMPARE( mRubberband->boundingRect(), QRectF(QPointF(-1,-1),QSizeF(28,28)) );
134+
QCOMPARE( mRubberband->pos(), QPointF(
135+
// 10 for extent minx - 3 for pen & icon
136+
7,
137+
// 30 for extent maxy - 3 for pen & icon
138+
mapSize.height() - 30 - 3
139+
) );
140+
141+
mCanvas->setExtent( QgsRectangle( QRectF(
142+
QPointF(0,0), mapSize/2
143+
) ) );
144+
145+
// 40 pixels for the extent + 6 for pen & icon per side + 2 of padding
146+
QCOMPARE( mRubberband->boundingRect(), QRectF(QPointF(-1,-1),QSizeF(54,54)) );
147+
QCOMPARE( mRubberband->pos(), QPointF(
148+
// 10 for extent minx - 3 for pen & icon
149+
7 * 2,
150+
// 30 for extent maxy - 3 for pen & icon
151+
mapSize.height() - ( 30 + 3 ) * 2
152+
) );
153+
154+
}
113155

114156

157+
QTEST_MAIN( TestQgsRubberband )
158+
#include "testqgsrubberband.moc"
115159

116160

0 commit comments

Comments
 (0)