I have an application where I place several curves in my scene. I was looking for an easy way to detect if the user pressed on the line. boundingRect() and intersects() were too inaccurate when I was having multiple lines drawn. So I made this function, which works like a dream except when the lines are vertical.
selectionMargin is a global variable set by the user (default = 0.5). It adjusts the margin for how accurate the selection check should be. Names are based on the linear function for each subline, y = ax + b. Pos is the position from the mousePressEvent.
bool GraphApp::pointInPath(QPainterPath path, QPointF pos)
{
qreal posY = pos.y();
qreal posX = pos.x();
for (int i = 0; i < path.elementCount()-1; ++i) {
if (posX < path.elementAt(i + 1).x && posX > path.elementAt(i).x) {
qreal dy = path.elementAt(i + 1).y - path.elementAt(i).y;
qreal dx = path.elementAt(i + 1).x - path.elementAt(i).x;
qreal a = dy / dx;
qreal b = path.elementAt(i).y - (path.elementAt(i).x * a);
if (selectionMargin == 0.0)
selectionMargin = 0.5;
qreal lowerBound = (a * posX + b) + selectionMargin;
qreal upperBound = (a * posX + b) - selectionMargin;
if (posY < lowerBound && posY > upperBound)
return true;
}
}
return false;
}
So it seems like this function returns false when I send a mousePressEvent from the area coverd by the vertical lines. My first thought is the if-sentence:
if (posX < path.elementAt(i + 1).x && posX > path.elementAt(i).x)
Any other ideas for how I can implement this without the if-sentence?
I have also seen other people struggling with finding a nice way to check if a QPainterPath contains a point without the boundingRect() and intersects() functions, so this is maybe to use for other people as well :)
EDIT: As far as I know, contains() uses boundingRect(). So I would not see that as a proper solution