2

I am adding items on a QGraphicsScene. Once added, items may be further processed.

I would like to skip the items completely obscured by other items. It seems that there are several QGraphicsItems dedicated to this task.

Given two QGraphicsItem objects, in the shape of a rectangle, identical in size, only differing by color, and each with identical boundingRect(), each at exactly the same pos(), but with different zValue():

for(int i = 0; i < scene.items().size(); ++i)
{
    if(scene.items().at(i)->isObscured())
    {
        continue;
    }
    // do work
}

I also tried

    if(scene->items().at(i)->isObscured(scene->items().at(i)->boundingRect()))

Neither option skips the item that is not visible.

If I increase slightly the size of the rectangle on top, the isObscured function works (either version). But with identical shapes, one on top of the other, logically the bottom one would still be obscured...

Would a reasonable fix be to add 1 pixel on each side of the rectangle ? would that not lead to weird situations ?

How can I make items that are covered be skipped ?

This issue is even more complicated if one item is covered by several other items, neither of them fully covering the item.

Thalia
  • 13,637
  • 22
  • 96
  • 190

1 Answers1

0

If I increase slightly the size of the rectangle on top, the isObscured function works (either version). But with identical shapes, one on top of the other, logically the bottom one would still be obscured...

In the documentation for QGraphicsItem::isObscuredBy(QGraphicsItem* item), it states: -

The base implementation maps item's opaqueArea() to this item's coordinate system, and then checks if this item's boundingRect() is fully contained within the mapped shape.

Looking at opaque area and the mapped shape, this is related to the opaqueArea function which states: -

An area is opaque if it is filled using an opaque brush or color (i.e., not transparent).

With two identical items, it's not the area of the bounding rectangles that are compared, but the opaqueArea of the QGraphicsItem with the boundingRect of the other item.

If your two items are failing when they are the same, on top of each other but with different colour, then the returned opaqueArea for the first item is not matching the bounding rect of the second.

TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • So what can I do ? the two items are identical, in this test, with each having a solid brush rectangle painted on boundingRect() and no border. Enlarging items is not an option, this is supposed to be generic... – Thalia May 19 '15 at 14:30
  • Oh I see... `The default implementation returns an empty QPainterPath, indicating that this item is completely transparent.` That means I have to add an implementation of the `opaqueArea` to match the shape of the object ... But then how do I handle cases when the items do have a transparent brush, or combinations... – Thalia May 19 '15 at 14:34
  • As it states for isObscuredBy "You can reimplement this function to provide a custom algorithm for determining whether this item is obscured by item." – TheDarkKnight May 19 '15 at 15:18
  • 1
    I'm still unsure how to implement `isObscuredBy` - probably best to implement the `isObscure` version with the rectangle argument - but I see the problem - they perform a "<" not a "<=" type check. I just have to find how they implement it. Thank you. – Thalia May 19 '15 at 20:13
  • Simple detection of obscurity is fairly easy, as you can check if the bounding rect of an object is inside another bounding rect. It gets more complicated when you're checking shapes. It may be worth researching 2d collision detection to get an idea of what you may need to do. – TheDarkKnight May 20 '15 at 07:56