Selection Detection with Vector Math

I am currently working on making my own whiteboard program using Dear ImGui, and one of the features I had to implement was the ability to select objects on the whiteboard. Since ImGui does not offer click detections for custom shapes, I had to implement my own selection detection algorithm. With the help of some vector math and the Internet, it was actually quite straightforward.

Framing the Problem

Whether an object should be selected can be framed as asking how close a mouse click is to an object. If the distance is below a threshold, then we can consider the object to be selected.

Let’s reframe this question again in math. Consider a line (segment) b\textbf{b} with two points, v1v_1 and v2v_2, and point PP, where the mouse click happened. The problem is to find a point on b\textbf{b} that is closest to PP. Intuitively, that point can be found by drawing a perpendicular line from PP to b\textbf{b}, and the intersection point will be the closest point on b\textbf{b} to PP. The distance between the two points then becomes the closest distance between PP and b\textbf{b}. Below is an illustration of the problem:

an illustration of the selection detection problem

where:

  • PP is the point where the mouse click occurred;
  • b\textbf{b} is the line that can be selected; and
  • dd is the shortest distance between PP and b\textbf{b}.

Applying Vector Math

Notice how the letter b\textbf{b} is bolded. This means that the line is treated as a vector. Now, we introduce another vector a\textbf{a} from the beginning of b\textbf{b} to PP. Observe that the projection of a\textbf{a} onto b\textbf{b} projbaproj_{\textbf{b}}\textbf{a} points to the shortest point on bb from PP.

vector projection illustration

The projection is written as:

projba=abbb^proj_{\textbf{b}}\textbf{a} = \frac{\textbf{a}\cdot\textbf{b}}{||\textbf{b}||} \hat{\textbf{b}}

where

  • b||\textbf{b}|| is the magnitude of b\textbf{b}
  • b^\hat{\textbf{b}} is the unit vector of b\textbf{b}

Recall that the magnitude of a vector a\textbf{a} is defined as:

a=i=1nxi2||\textbf{a}|| = \sqrt{\sum_{i=1}^{n}x_i^2}

and its unit vector as:

a^=aa\hat{\textbf{a}} = \frac{\textbf{a}}{||\textbf{a}||}

for any finite n-dimensional vector aRn\textbf{a} \in \mathbb{R}^n.

Substituting into the projection formula, we get

projba=abbbbproj_{\textbf{b}}\textbf{a} = \frac{\textbf{a}\cdot\textbf{b}}{\textbf{b}\cdot\textbf{b}}\textbf{b}

Finding a\textbf{a} and b\textbf{b}

To find a\textbf{a}, we treat v1v_1 and PP as two vectors:

vector from starting point of b to P

Then, we subtract v1\textbf{v}_1 from P\textbf{P} using vector subtraction:

a=Pv1\textbf{a} = \textbf{P} - \textbf{v}_1

b\textbf{b} can be found in a similar fashion.

Finding the Intersection Point

Once the projection vector is found, we add it to v1\textbf{v}_1 to obtain the coordinates of the intersection point:

find intersection point

Computing the Shortest Distance

Finally, to find the shortest distance between PP and b\textbf{b}, we now have two choices:

  • Find the euclidean distance between PP and the intersection point
  • Perform vector subtraction between the two points, then find its magnitude.

In either case, we have successfully found the shortest distance between a point and a line segment!

Special Cases

There are two special cases that we have not considered:

  1. The projection of the point falls outside of b\textbf{b} to the left of it
  2. The projection of the point falls outside of b\textbf{b} to the right of it
special cases of the selection detection problem

In the first case, the dot product ab\textbf{a} \cdot \textbf{b} is less than zero. Therefore, if we find that the dot product is less than zero, we know that the closest point from PP to b\textbf{b} is the starting point of b\textbf{b}.

In the second case, the projection of a\textbf{a} onto b\textbf{b} is longer than b\textbf{b}. We can write this relation as:

projba>babb>bab>b2ab>bb\begin{align} ||proj_{\textbf{b}}\textbf{a}|| &> ||\textbf{b}|| \nonumber \\ \frac{\textbf{a}\cdot\textbf{b}}{||\textbf{b}||} &> ||\textbf{b}|| \nonumber \\ \textbf{a}\cdot\textbf{b} &> ||\textbf{b}||^2 \nonumber\\ \textbf{a}\cdot\textbf{b} &> \textbf{b}\cdot\textbf{b} \nonumber\\ \end{align}

Therefore, when bb\textbf{b}\cdot\textbf{b} is greater than ab\textbf{a}\cdot\textbf{b}, we know that we are in the second case, and we can infer that the end point of b\textbf{b} is the closest to PP.

Implementation Note

At the final step of finding the distance between a point and the intersection point, a square root is involved using either method. Since we only care about whether the distance meets a threshold and not the actual number, we can skip the square root calculation and compare it with the square of the threshold we want. For example, if we want the threshold to be 5px for an object to be considered selected, we compare the computation with 52=255^2 = 25.