Bug report #12392

QgsRubberBand not fully refreshing

Added by Anatoliy Golubev over 4 years ago. Updated over 4 years ago.

Status:Closed
Priority:Normal
Assignee:Sandro Santilli
Category:Map Canvas
Affected QGIS version:2.8.1 Regression?:No
Operating System: Easy fix?:No
Pull Request or Patch supplied:Yes Resolution:
Crashes QGIS or corrupts data:No Copied to github as #:20566

Description

QgsRubberBand items sometimes not refreshing properly when another map
canvas item (QgsVertexMarker) intersects them. This happens with 2.8,
in 2.6.1 works as expected.

See: https://www.dropbox.com/s/4egl61juue9ewop/rubberband.png?dl=0 as
illustration

How to reproduce:
1. Open empty project (epsg:4326)
2. Execute this script in python console:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.gui import *
from qgis.core import *

mCursor = QgsVertexMarker(iface.mapCanvas())
mCursor.setIconType(QgsVertexMarker.ICON_BOX)
mCursor.setIconSize(20)
mCursor.setZValue(5)

points = [[QgsPoint(0, 0), QgsPoint(20, 30), QgsPoint(0, 60)]]

rb = QgsRubberBand(iface.mapCanvas(), True)
rb.setToGeometry(QgsGeometry.fromPolygon(points), None)
rb.setColor(QColor(125, 125, 0))
rb.show()

def changeCursorPos(p):
    mCursor.setCenter(p)

iface.mapCanvas().xyCoordinates.connect(changeCursorPos)

3. Move mouse cursor over rubber band.
You can erase rubber band from bottom to some upper point.

Tested on win7 32bit

rubberband2.png (167 KB) Anatoliy Golubev, 2015-03-25 05:27 AM

Associated revisions

Revision a844bfa1
Added by Sandro Santilli over 4 years ago

Recompute rubberband extent on zoom/pan

Fix #12392
Includes testcase

Revision 37171dc0
Added by Sandro Santilli over 4 years ago

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)

History

#1 Updated by Anatoliy Golubev over 4 years ago

ups...code should be:
points = [ [QgsPoint(0, 0), QgsPoint(20, 30), QgsPoint(0, 60)] ]

#2 Updated by Anatoliy Golubev over 4 years ago

  • Assignee set to Sandro Santilli

I found that this bug was introduced in d7269595

Sandro, can you look at it?

#3 Updated by Sandro Santilli over 4 years ago

it looks like it's failing to update the lower and right sides.
Your script did not work here: TypeError: QgsGeometry.fromPolygon(unknown-type): argument 1 has unexpected type 'tuple'

Any way to reproduce this with some core tool ?

Or (even better), could you provide an automated test to include in the suite ?

#4 Updated by Anatoliy Golubev over 4 years ago

This script works fine in 2.8.1 (redmine eat double brackets)

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.gui import *
from qgis.core import *

mCursor = QgsVertexMarker(iface.mapCanvas())
mCursor.setIconType(QgsVertexMarker.ICON_BOX)
mCursor.setIconSize(20)
mCursor.setZValue(5)

points = [ [QgsPoint(0, 0), QgsPoint(20, 30), QgsPoint(0, 60)] ]

rb = QgsRubberBand(iface.mapCanvas(), True)
rb.setToGeometry(QgsGeometry.fromPolygon(points), None)
rb.setColor(QColor(125, 125, 0))
rb.show()

def changeCursorPos(p):
    mCursor.setCenter(p)

iface.mapCanvas().xyCoordinates.connect(changeCursorPos)

#5 Updated by Sandro Santilli over 4 years ago

iface.mapCanvas().xyCoordinates.connect(changeCursorPos)    
  File "<input>", line 4
    iface.mapCanvas().xyCoordinates.connect(changeCursorPos)
        ^
SyntaxError: invalid syntax

#6 Updated by Anatoliy Golubev over 4 years ago

I get this syntax error when there are some spaces between "mCursor.setCenter(p) and iface. iface should not be in changeCursorPos function.
You can try copy all code except last line, and then copy last line.

See attached screenshot

#7 Updated by Sandro Santilli over 4 years ago

Got it, I need to enter an additional empty line to signal end of "changeCursorPos" function (in the python console) -- trying

#8 Updated by Nyall Dawson over 4 years ago

Sandro - you probably need to override the boundingRect method in QgsRubberBand to return the correct rubber band bounds. It would seem the base implementation of this method is returning a rect which is too small for the rubber band. That would account for this behaviour...

#9 Updated by Sandro Santilli over 4 years ago

I actually wonder if QgsMapCanvasItem::boundingRect is correct, in that it assumes the bounding rectangle always starts at the upper-left corner. Reading the code it looks like "mItemSize" should be correct (it's set by QgsMapCanvasItem::setRect) but boundingRect does not take mRect in consideration at all!

#10 Updated by Sandro Santilli over 4 years ago

I've added debugging output in 2.6 and 2.8 branches to see what's going on.
First of all I noticed that even with an empty project, the QgsRubberBand::boundingRect (I added an override there, just for the sake of printing a debugging output) gets called for every pan and zoom.

Second, with the python code above, moving the rubberband around the canvas does not change the returned "boundingRect" which seems to only depend on scale. I continue to think it's always been bogus somehow...

#11 Updated by Sandro Santilli over 4 years ago

Oops, sorry, only now I realize that the "rubberband" in the test is the triangle, not the cursor. It makes sense for it to not change when moving the cursor. Looking better now :)

#12 Updated by Sandro Santilli over 4 years ago

Ok now I confirm that no matter where I pan (moving the rubberband triangle around the screen) the boundingRect (with 2.6) always reports the same value, which is only dependent on zoom/size-of-rubberband, and always starts with -1,-1.

For example
at scale 1:140,273,942:
src/gui/qgsrubberband.cpp: 522: (boundingRect) XXX rect is -1.0000000000000000,-1.0000000000000000 : 45.7176168480304597,135.0688211983073757

#13 Updated by Sandro Santilli over 4 years ago

Alright one difference is that while in 2.6 the rectangle size updates with scale, in master it seems to be fixed.
updateRect is called once at rubberband creation time in both cases. Dunno what else is supposed to change mItemSize

#14 Updated by Sandro Santilli over 4 years ago

QgsMapCanvasItem::updatePosition calls setRect again in 2.6. In master qgsrubberband overrides updatePosition to do nothing, thus the mItemSize does not change.

#15 Updated by Anatoliy Golubev over 4 years ago

QgsRubberBand::updateRect calls QgsMapCanvasItem::setRect too

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

Maybe thats the point? Why should we subtract r.height()*res from r.yMinimum()?

#16 Updated by Sandro Santilli over 4 years ago

updateRect call to setRect is ok, I think.

I confirm dropping the override fixes this bug. But it's to be checked what else (if anything) breaks.
I think it's better to have an automated test for this bug before fixing it. If not else if any other breackage comes out the fix for that won't re-introduce this.

Do you think you can provide an automated test for this, Anatoliy ?

#17 Updated by Anatoliy Golubev over 4 years ago

Dont know how to automate it, sorry.

#18 Updated by Sandro Santilli over 4 years ago

Theres a tests/src/gui/testqgsrubberband.cpp file you could start from

#19 Updated by Anatoliy Golubev over 4 years ago

Ok, Im look at it

#20 Updated by Sandro Santilli over 4 years ago

A fix is available here: https://github.com/qgis/QGIS/pull/1968
Adding your test there would be useful, before merging.

#21 Updated by Sandro Santilli over 4 years ago

  • Target version set to Version 2.8.2
  • % Done changed from 0 to 90

#22 Updated by Sandro Santilli over 4 years ago

  • Pull Request or Patch supplied changed from No to Yes

#23 Updated by Sandro Santilli over 4 years ago

  • Status changed from Open to Closed

#24 Updated by Sandro Santilli over 4 years ago

  • Status changed from Closed to Reopened

reopened as the fix needs to be backported to 2.8 branch

#25 Updated by Sandro Santilli over 4 years ago

  • Tag set to rotation

Also, I'd like a confirmation from the reporter about effectiveness of the fix (currently in master)

#26 Updated by Anatoliy Golubev over 4 years ago

Tested master on debian, it seems ok, refreshing works fine.

#27 Updated by Sandro Santilli over 4 years ago

  • Status changed from Reopened to Closed

Also available in: Atom PDF