Trivial Programming: Calculating a Shortened Line Between 2 Points

I had a conversation with a coworker a month ago on how to draw a line connecting from 1 point to the mouse pointer, without underlaying on the mouse cursor forcing it to be selected. The math behind it is rather trivial, since you just need to convert cartesian to polar coordinates, decrease the polar distance by a set amount, and convert back to cartesian coordinates. However, it's come to my realization that not everyone recalls how to perform polar coordinate conversion, so this article is about programmatically accomplish this for a 2 point line, where the 2nd point needs to be shortened so the mouse cursor doesn't hover over the line it's dragging.

How to Calculate A Shortened Position Between 2 Points

This is a simple function if you don't care about the logic and just want something working written in TypeScript.

Assume xA and yA are the (x, y) values of point A, and xB and yB are the (x, y) values of point B. Also assume that point B is our mouse pointer position and point A is where our line is anchored to.

function calculateShortedPointBFromPointA(xA: number, yA: number, xB: number, yB: number) : number[] {
    const angle = Math.atan2(xB - xA, yB - yA);
    // Pythagorean Theorem!
    const distance = Math.sqrt((yB - yA)^2 + (xB - xA)^2); 

    // Pixel distance away from mouse pointer. 
    const desiredDistance = distance - 10; 

    const xPositionForB = (desiredDistance * Math.cos(angle)) + xA;
    const yPositionForB = (desiredDistance * Math.sin(angle)) + yA;

    return [xPositionForB, yPositionForB];
}

WARNING: I didn't test the code if it actually runs. I'm just parroting off memory, so there might be some bugs with the implementation.

How It Works

I converted a line from Cartesian Coordinates to Polar Coordinates. Cartesian coordinates is represented in pairs. Polar is represented in , where is the distance from the center and is the angle from the polar axis. (The polar axis varies based off the orientation of your graph, so you'll need to experiment a bit to figure it out.)

To convert from Cartesian to Polar, you simply need to find the angle and distance of your line. This can easily be accomplished using and Pythagorean Theorem.

and

With the angle and distance, we simply need to subtract distance by a magic number. Lets just say or something, whatever number distance that fits your circumstance from the mouse pointer. Lets call this new value .

Then we simply need to reconvert back into cartesian coordinates.

Now should be the new coordinates you set for the end of your line to prevent overlay.

What is atan2? Why not use atan instead?

If you recall from our problem, we're trying to calculate

However, notice immediately that when , the value is undefined. When is 0, that means the line is either going vertically straight up or vertically straight down.

Furthermore, recall that has a domain between . Everytime it goes beyond these boundaries, it jumps to either infinitely positive or infinitely negative, depending on which boundary you jump through. If you tried plugging in the tan into your graph, you'll see the angle value jumps weirdly whenever you cross the border where . You need to handle specific quadrant cases by adding or subtracting by depending on if you're in quadrant 3 or quadrant 4 of the unit circle in order to maintain a full consistency.

atan2 handles these holes in the tan algorithm. This Wikipedia article goes into more detail

Why subtract the Distance by A Set Pixel Distance? Should I Multiply It Instead?

The size of the mouse pointer is usually set. Subtracting by a set number usually makes the line maintain a consistent distance from the pointer, while a multiplicative scaling would increase the distance as you go further away, making it look off.

← Back to home