# 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;
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;

let multiplier;
multiplier = targetX <= sourceX ? 1 : -1;
} else {
multiplier = targetY <= sourceY ? 1 : -1;
}
tx2 = targetX + multiplier * changeX;
ty2 = targetY + multiplier * changeY;

• Need to change last lines to not mix arithmetic operators. Placing bracers around the multiplication. – Evgeny Jan 21 '17 at 12:22
• @Evgeny Multiplication takes precedence before addition, so no braces needed. – Simon Forsberg Jan 21 '17 at 12:46
• Yes it works. But a good practice, to avoid human error when changing code later, is not to mix arithmetic operators. – Evgeny Jan 21 '17 at 12:52
• @Evgeny That's your preference, personally I don't worry about mixing addition and multiplication like that. If it makes you feel any better, you could do multiplier * changeX + targetX – Simon Forsberg Jan 21 '17 at 12:55