Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QRectF::contains() returns unexpected/unacceptable result
Forum Updated to NodeBB v4.3 + New Features

QRectF::contains() returns unexpected/unacceptable result

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 4 Posters 1.3k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #1

    Qt 6.4.2 supplied with Ubuntu 24.04, gcc 13.2.0.

    bool QRectF::contains(const QRectF &rectangle) const returns false when the rectangle passed to it has height or width of 0/0.0 but it is contained within the instance rectangle. While bool QRect::contains(const QRect &rectangle, bool proper = false) const (note this is QRect in place of QRectF) 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 false
    

    Last line's final output of false for contains() is both unexpected and to me unacceptable. All the more so since the QRect instead of QRectF version returns true for contains().

    I have existing code which may receive an enclosed/inner rectangle with 0 height or width. I do not want to go testing for isEmpty() everywhere I want to call contains(), and I do not see why I should have to, in the QRectF case 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.0 is right or wrong or perhaps treats it as 0.0000000001 or 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?

    1 Reply Last reply
    0
    • C ChrisW67

      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 false in 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.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #4

      @ChrisW67
      Going to raise a Qt bug, I did a search on that site. And found https://bugreports.qt.io/browse/QTBUG-30456

      QRectF::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 QRectF but not to a QRect is 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....

      SGaistS 1 Reply Last reply
      2
      • C Offline
        C Offline
        ChrisW67
        wrote on last edited by
        #2

        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 false in 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.

        JonBJ 2 Replies Last reply
        2
        • C ChrisW67

          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 false in 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.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #3

          @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 call contains(), and that only if I happen to be using a QRectF (e.g. function return result) where I might just have happily used a QRect and 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....

          1 Reply Last reply
          0
          • C ChrisW67

            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 false in 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.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #4

            @ChrisW67
            Going to raise a Qt bug, I did a search on that site. And found https://bugreports.qt.io/browse/QTBUG-30456

            QRectF::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 QRectF but not to a QRect is 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....

            SGaistS 1 Reply Last reply
            2
            • JonBJ JonB has marked this topic as solved on
            • JonBJ JonB

              @ChrisW67
              Going to raise a Qt bug, I did a search on that site. And found https://bugreports.qt.io/browse/QTBUG-30456

              QRectF::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 QRectF but not to a QRect is 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....

              SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #5

              @JonB It's a good occasion to submit a documentation patch to raise the awareness for everybody :-)

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by
                #6

                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.

                Asking a question about code? http://eel.is/iso-c++/testcase/

                JonBJ 1 Reply Last reply
                1
                • jeremy_kJ jeremy_k

                  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.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #7

                  @jeremy_k
                  Yes, and it says exactly the same for QRect::isValid(), yet that does not have the "special" code for returning false from contains() etc. which QRectF does 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_kJ 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @jeremy_k
                    Yes, and it says exactly the same for QRect::isValid(), yet that does not have the "special" code for returning false from contains() etc. which QRectF does 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_kJ Offline
                    jeremy_kJ Offline
                    jeremy_k
                    wrote on last edited by jeremy_k
                    #8

                    @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. ;-)

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    JonBJ 1 Reply Last reply
                    0
                    • jeremy_kJ jeremy_k

                      @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. ;-)

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #9

                      @jeremy_k said in QRectF::contains() returns unexpected/unacceptable result:

                      Surely you understand that "not defined" does not mean that its behavior is what you want, expect, or have witnessed in another instance.

                      Did I not write exactly that?

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved