QRectF::contains() returns unexpected/unacceptable result
-
Qt 6.4.2 supplied with Ubuntu 24.04, gcc 13.2.0.
bool QRectF::contains(const QRectF &rectangle) const returns
falsewhen therectanglepassed to it has height or width of0/0.0but it is contained within the instance rectangle. While bool QRect::contains(const QRect &rectangle, bool proper = false) const (note this isQRectin place ofQRectF) actually returns the "correct"true.#include <QCoreApplication> #include <QDebug> #include <QRect> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QRect outer(50, 50, 100, 100); QRect inner(60, 60, 10, 1); qDebug() << inner.isNull() << inner.isEmpty() << outer.contains(inner); inner.setHeight(0); qDebug() << inner.isNull() << inner.isEmpty() << outer.contains(inner); QRectF outerF(50, 50, 100, 100); QRectF innerF(60, 60, 10, 1); qDebug() << innerF.isNull() << innerF.isEmpty() << outerF.contains(innerF); innerF.setHeight(0); qDebug() << innerF.isNull() << innerF.isEmpty() << outerF.contains(innerF); }Output:
false false true false true true false false true false true falseLast line's final output of
falseforcontains()is both unexpected and to me unacceptable. All the more so since theQRectinstead ofQRectFversion returnstrueforcontains().I have existing code which may receive an enclosed/inner rectangle with
0height or width. I do not want to go testing forisEmpty()everywhere I want to callcontains(), and I do not see why I should have to, in theQRectFcase only.I am aware that with floating point numbers tests for e.g. equality have to do "fuzzy" comparison. And maybe Qt internal code for
QRectF::contains()is using it. bool qFuzzyCompare(double p1, double p2)Note that comparing values where either p1 or p2 is 0.0 will not work, nor does comparing values where one of the values is NaN or infinity. If one of the values is always 0.0, use qFuzzyIsNull instead. If one of the values is likely to be 0.0, one solution is to add 1.0 to both values.
I am guessing this might be the cause of the "erroneous" result. But IMHO this is not my problem! It might be Qt's problem when comparing my rectangles, but should not be mine! And whether the "fuzzy" comparison on
0.0is right or wrong or perhaps treats it as0.0000000001or whatever STILL does not alter that that inner rectangle is wholly contained within the outer one anyway.....Do you find same behaviour on your Qt/compiler/platform? Comments? Is this a "bug"? Should
QRectF::contains()docs mention this if they are going to stick with current behaviour? -
A rectangle with zero width/height is a line. I am not entirely surprised that this degenerate case has ill-defined results.
QRect::contains()
QRectF::contains()The QRectF code has specific tests for zero dimensions and returns
falsein those cases (an exact condition). The same tests do not appear to be in the QRect code. There's no commentary as to why this might be. It may be as simple as maintaining compatibility with an implementation from the Qt dark ages.@ChrisW67
Going to raise a Qt bug, I did a search on that site. And found https://bugreports.qt.io/browse/QTBUG-30456QRectF::intersected()/intersects()/contains() works bad if one of rects has zero width and/or height
That is from 2013, Qt5.0.1. With "Resolution: Invalid" and reply
Looks to me like it's working as expected. A rectangle with zero width is not a rectangle.
And the OP's plea of
PLEASE describe this behavior in documentaion.
was apparently ignored.
I still believe this behaviour is at least "unhelpful", and the fact that this rule is applied explicitly to a
QRectFbut not to aQRectis at least "inconsistent".However I realise I will be peeing in the wind if I pursue this with devs, so I will leave it at that....
-
A rectangle with zero width/height is a line. I am not entirely surprised that this degenerate case has ill-defined results.
QRect::contains()
QRectF::contains()The QRectF code has specific tests for zero dimensions and returns
falsein those cases (an exact condition). The same tests do not appear to be in the QRect code. There's no commentary as to why this might be. It may be as simple as maintaining compatibility with an implementation from the Qt dark ages. -
A rectangle with zero width/height is a line. I am not entirely surprised that this degenerate case has ill-defined results.
QRect::contains()
QRectF::contains()The QRectF code has specific tests for zero dimensions and returns
falsein those cases (an exact condition). The same tests do not appear to be in the QRect code. There's no commentary as to why this might be. It may be as simple as maintaining compatibility with an implementation from the Qt dark ages.@ChrisW67
Hi Chris, thanks for answering. You say the same as I surmised. However, I believe the behaviour is nonetheless "wrong", in the sense that whichever way up you look at it the 0 width or height rectangle is still enclosed/contained within the outer one.In my case I did not know that the inner rectangle had shrunk to 0 width/height, but I had an assertion in the code because I knew that whatever dimensions it had it was inside the outer one. Till the code asserted on me. I really don't want to have to go put tests for
isEmpty()every time I want to callcontains(), and that only if I happen to be using aQRectF(e.g. function return result) where I might just have happily used aQRectand may not even have looked at which one is being used.I think I might go raise a "bug" report anyway and see what the devs have to say....
-
A rectangle with zero width/height is a line. I am not entirely surprised that this degenerate case has ill-defined results.
QRect::contains()
QRectF::contains()The QRectF code has specific tests for zero dimensions and returns
falsein those cases (an exact condition). The same tests do not appear to be in the QRect code. There's no commentary as to why this might be. It may be as simple as maintaining compatibility with an implementation from the Qt dark ages.@ChrisW67
Going to raise a Qt bug, I did a search on that site. And found https://bugreports.qt.io/browse/QTBUG-30456QRectF::intersected()/intersects()/contains() works bad if one of rects has zero width and/or height
That is from 2013, Qt5.0.1. With "Resolution: Invalid" and reply
Looks to me like it's working as expected. A rectangle with zero width is not a rectangle.
And the OP's plea of
PLEASE describe this behavior in documentaion.
was apparently ignored.
I still believe this behaviour is at least "unhelpful", and the fact that this rule is applied explicitly to a
QRectFbut not to aQRectis at least "inconsistent".However I realise I will be peeing in the wind if I pursue this with devs, so I will leave it at that....
-
J JonB has marked this topic as solved on
-
@ChrisW67
Going to raise a Qt bug, I did a search on that site. And found https://bugreports.qt.io/browse/QTBUG-30456QRectF::intersected()/intersects()/contains() works bad if one of rects has zero width and/or height
That is from 2013, Qt5.0.1. With "Resolution: Invalid" and reply
Looks to me like it's working as expected. A rectangle with zero width is not a rectangle.
And the OP's plea of
PLEASE describe this behavior in documentaion.
was apparently ignored.
I still believe this behaviour is at least "unhelpful", and the fact that this rule is applied explicitly to a
QRectFbut not to aQRectis at least "inconsistent".However I realise I will be peeing in the wind if I pursue this with devs, so I will leave it at that....
-
This behavior is documented in an indirect manner:
QRectf::isValid()A valid rectangle has a width() > 0 and height() > 0. Note that non-trivial operations like intersections are not defined for invalid rectangles.
-
This behavior is documented in an indirect manner:
QRectf::isValid()A valid rectangle has a width() > 0 and height() > 0. Note that non-trivial operations like intersections are not defined for invalid rectangles.
@jeremy_k
Yes, and it says exactly the same for QRect::isValid(), yet that does not have the "special" code for returning false fromcontains()etc. whichQRectFdoes have, and returns the "correct" true. But I realize that once the behaviour is called "undefined" in both cases then I cannot rely on whatever they might/might not return.I gave up on calling it a "bug" and have labelled it "inconsistent".
-
@jeremy_k
Yes, and it says exactly the same for QRect::isValid(), yet that does not have the "special" code for returning false fromcontains()etc. whichQRectFdoes have, and returns the "correct" true. But I realize that once the behaviour is called "undefined" in both cases then I cannot rely on whatever they might/might not return.I gave up on calling it a "bug" and have labelled it "inconsistent".
@JonB said in QRectF::contains() returns unexpected/unacceptable result:
@jeremy_k
Yes, and it says exactly the same for QRect::isValid()Surely you understand that "not defined" does not mean that its behavior is what you want, expect, or have witnessed in another instance. If not, I have an uninitialized pointer that you can borrow.Answered in the second half. You're still welcome to the pointer. ;-)
-
@JonB said in QRectF::contains() returns unexpected/unacceptable result:
@jeremy_k
Yes, and it says exactly the same for QRect::isValid()Surely you understand that "not defined" does not mean that its behavior is what you want, expect, or have witnessed in another instance. If not, I have an uninitialized pointer that you can borrow.Answered in the second half. You're still welcome to the pointer. ;-)