Here is a single formula that avoids all the case logic. (I happen to be working in JS right now, so here's a JS implementation). Let rect = {max:{x:_, y:_}, min:{x:_, y:_}}
and p={x:_, y:_}
function distance(rect, p) {
var dx = Math.max(rect.min.x - p.x, 0, p.x - rect.max.x);
var dy = Math.max(rect.min.y - p.y, 0, p.y - rect.max.y);
return Math.sqrt(dx*dx + dy*dy);
}
Explanation:
This breaks down the problem into calculating the x distance dx
and the y distance dy
. It then uses distance formula.
For calculating dx
, here is how that works. (dy
is analogous)
Look at the tuple being provided to the max function: (min-p, 0, p-max)
. Let's designate this tuple (a,b,c)
.
If p is left of min, then we have p < min < max, which means the tuple will evaluate to (+,0,-)
, and so the max function will correctly return a = min - p
.
If p is between min and max, then we have min < p < max, which means the tuple will evaluate to (-,0,-)
. So again, the max function will correctly return b = 0
.
Lastly, if p is to the right of max, then we have, min < max < p, and the tuple evaluates to (-,0,+)
. Once again, Math.max correctly returns c = p - max
.
So it turns out all the case logic is taken care of by Math.max, which leads to a nice 3-line, control-flow-free function.