I have an application where I put some curves in my scene. I was looking for an easy way to determine if a user is clicked on a line. boundingRect()
and intersects()
were too inaccurate when I was drawing multiple lines. So I made this function that works like a dream, except that 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 is. Names are based on a linear function for each subline, y = ax + b
. Pos is a position from 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; }
It seems like this function returns false when I send a mousePressEvent from the area covered by vertical lines. My first thought is an if statement:
if (posX < path.elementAt(i + 1).x && posX > path.elementAt(i).x)
Any other ideas on how I can implement this without an if clause?
I also saw how other people tried their best to find a good way to check if QPainterPath
contains a point without the boundingRect()
and intersects()
functions, so this can be used for other people as well :)
EDIT: As far as I know, contains()
uses boundingRect()
. Therefore, I would not see this as the right decision
source share