Finding the coordinates on an edge of a square

I wrote a calculation that finds coordinates on an edge of a square, but it came out as a really long nested tangle of conditions. After some reduction and finding common pieces I arrived at this example:

// targetX, targetY, sourceX, sourceY are provided as parameters
// and are markers for the centers of the two locations connecting
let tx;
let ty;
const dx = targetX - sourceX;
const dy = targetY - sourceY;
const adjY = (radius * Math.tan(Math.atan2(dy, dx)));
const adjX = (radius / Math.tan(Math.atan2(dy, dx)));
if (Math.abs(adjY) <= radius) { // A
if (targetX <= sourceX) { // B
} else {
}
} else if (targetY <= sourceY) { // C
} else {
}

Moving several of the conditions into the lines themselves was possible using ternary operators. But now I'm stuck, so how do I reduce the conditions even further?

I thought of using boolean logic gate reduction techniques, like Karnaugh maps, but fail to find a way to map that process to my problem.

Other solutions involving different math are welcome as well.

The problem is finding the new target X and Y so that they meet the edge of the target rectangle instead of its center. I think the solution is a little simplier

const dx = targetX - sourceX;
const dy = targetY - sourceY;
const scale = Math.hypot(dx, dy) / Math.hypot(radius,radius * (Math.abs(dy / dx) < 1 ? dy / dx : dx / dy));
const tx = targetX - dx / scale;
const ty = targetY - dy / scale;

If it is just the boundary of the box you are after. The only comparison is to find out which part of the box the line ends on, top/bottom or left/right the rest works by preserving dx and dy's sign. It also works if dx or dy is zero.

The only thing I am not sure of is if the offset is from the target, if so I would change to

const dx = sourceX - targetX;
const dy = sourceY - targetY;
const scale = Math.hypot(dx, dy) / Math.hypot(radius,radius * (Math.abs(dy / dx) < 1 ? dy / dx : dx / dy));
const tx = targetX + dx / scale;
const ty = targetY + dy / scale;
• The first option (with the subtraction) works flawlessly! Thank you very much. A much more elegant solution than my own. – Evgeny Jan 21 '17 at 15:22
• Went into working code at github.com/kesor/vue-ccpm/commit/a3f6b87b – Evgeny Jan 22 '17 at 4:11

What you need is to extract some values into variables.

First of all, you are always using Math.abs(adjX) <= radius ? adjX : radius for both X and Y so those can be extracted into changeX or changeY.

Next, you are either doing + or - which can be changed into using a multiplier that is either $1$ or $-1$.

And as a last step, the multiplier can be set using the conditional ternary operator.

Then what you end up with is this:

let tx;
let ty;
const dx = targetX - sourceX;
const dy = targetY - sourceY;
const adjY = (radius * Math.tan(Math.atan2(dy, dx)));
const adjX = (radius / Math.tan(Math.atan2(dy, dx)));