PDA

View Full Version : Why isn't QPainterPath::intersects giving me the expected result?



blooglet
12th May 2011, 13:22
I made the following test code for the QPainterPath::intersects test function. I wanted a way to detect if a point is in the vicinity (let's say 2 pixels) of a line stored in a QPainterPath.


QPainterPath path;
path.moveTo(0, 0);
path.lineTo(0, -20);
path.lineTo(40, -20);
path.lineTo(40, -95);
int testX = 4;
int testY = -17;
QRectF rect(testX - 2, testY - 2, 4, 4);
bool intersects = path.intersects(rect);
qDebug() << "Intersects?" << ((intersects) ? "true" : "false");
qDebug() << "Rect: x =" << rect.x() << "| y =" << rect.y() << "| w =" << rect.width() << "| h =" << rect.height();

This produces the following output:

Intersects? true
Rect: x = 2 | y = -19 | w = 4 | h = 4

I'd expect the intersects function to return false in this case because no point in the rectangle overlaps with the drawn line. Am I using the function incorrectly?

koan
12th May 2011, 13:42
I think that your rectangle is top left -> bottom right = (2,-19) -> (6, -23) and therefore intersects at (2,-20) and (6,-20). I think you are assuming that from the start point of the rectangle it is drawn in a positive direction but Qt is drawing from a top down point of view.

MarekR22
12th May 2011, 14:14
But you point is inside! Take look on a shape! last sector intersects with second sector of path it looks like you mistyped a shape data.

blooglet
13th May 2011, 21:38
I think you are assuming that from the start point of the rectangle it is drawn in a positive direction but Qt is drawing from a top down point of view.

Wait... so a QRectF with x = 2, y = -19, w = 4 and h = 4 doesn't stretch to (6, -15) but rather (6, -23)? So the height is counted towards lower Y values? I'm confused.

wysota
13th May 2011, 22:27
Why guess? Draw both the path and the rect using QPainter and you'll see what gets drawn where.

blooglet
18th May 2011, 14:22
Here's the reference drawing I obtained.

http://i.imgur.com/1mZtC.png


QPainterPath path;
path.moveTo(0, 0);
path.lineTo(0, -20);
path.lineTo(40, -20);
path.lineTo(40, -95);
int testX = 4;
int testY = -17;
QRectF rect(testX - 2, testY - 2, 4, 4);
bool intersects = path.intersects(rect);
qDebug() << "Intersects?" << ((intersects) ? "true" : "false");
qDebug() << "Rect: x =" << rect.x() << "| y =" << rect.y() << "| w =" << rect.width() << "| h =" << rect.height();

scene->addPath(path);
scene->addRect(rect);


Intersects? true
Rect: x = 2 | y = -19 | w = 4 | h = 4

They don't intersect in the drawing, do they?

wysota
18th May 2011, 14:58
"It depends". If the path is treated as a closed path then they intersect. Try moving the rectangle to Y>0 (e.g. x=2, y=1, w=4, h=4) and see if it is still considered intersecting with the path.

blooglet
20th May 2011, 14:11
It appears that the rectangle is considered "not intersecting" when it is outside the bounding rectangle of the painter path. This is not the behavior I want. I want to check if the rectangle overlaps with the line. Am I using the wrong method?

wysota
20th May 2011, 14:32
The docs say:

Set operations on paths will treat the paths as areas. Non-closed paths will be treated as implicitly closed.

I don't think there is a method in QPainterPath that does directly what you want.

blooglet
22nd May 2011, 14:32
Does Qt provide a way to, given a path consisting of lines that isn't necessarily closed and a mouse coordinate, calculate if I clicked on the path? I then want to extend this concept to "in the vicinity of the path" by using a QRectF instead of a QPointF.

wysota
22nd May 2011, 15:58
This is a mathematical problem that can easily be solved without using any dedicated frameworks. Each line conforms to the ax+by+c = 0 equation. Using coordinates of ends of the lines you can calculate a, b and c and then it is easy to compute the solution by substituting x and y with coordinates of the point you wish to check for intersection. It is similar when talking about intersection of lines. And of course there is QLineF::intersect() to help you.