Skip to content
Advertisement

Line is detected as diagonal of rectangle while using collidepoint function in pygame

I am working on a graph based project. I am drawing lines to represent the edges. My goal is to change color of line when I click on the specific line. the problem is pygame treats line as diagonal of virtual rectangle. so when even if I don’t click on the line but the mouse position is in the projected area of the virtual rectangle, the event is detected as collision while using collidepoint(). I want to detect this only when the mouse is clicked on actual line only.

I am new to pygame, so let me know if there is other function or library that I can use. This is the example code of my project.

JavaScript

Advertisement

Answer

pygame.draw.line returns a pygame.Rect object that defines the axis aligned bounding rectangle surrounding the line. collidepoint test if a point is in a rectangle.


You have to use a different approach. Write a function that computes the shortest distance of a point to a line:

dist = abs(dot(normalized(NV), P - LP)), where NV is the normal vector to the line, LP is a point on the line and P is the point whose distance needs to be calculated.

JavaScript
JavaScript

The same function with the use of pygame.math.Vector2:

JavaScript

Test whether the mouse pointer is in the rectangle defined by the line and whether the distance is less than half the line width:

JavaScript

Explanation:

I’ve used the Dot product distance from the point to the line.. In general The Dot product of 2 vectors is equal the cosine of the angle between the 2 vectors multiplied by the magnitude (length) of both vectors.

JavaScript

This follows, that the Dot product of 2 Unit vectors is equal the cosine of the angle between the 2 vectors, because the length of a unit vector is 1.

JavaScript

Therefore the Dot product of the normalized normal vector to the line (NV) and a vector from a point on the line (LP) to the point whose distance must be calculated (P) is the shortest distance of the point to the line.


Minimal example:

JavaScript
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement