# Checking if an xy position is within a rectangular bounds

This is pretty straightforward, but is there a better way to do this?

function isWithinBounds(obj, pos) {
var oXmin, oXmax, oYmin, oYmax;
if (obj.startPos.x < obj.endPos.x) {
oXmin = obj.startPos.x;
oXmax = obj.endPos.x;
}
else {
oXmin = obj.endPos.x;
oXmax = obj.startPos.x
}

if (obj.startPos.y < obj.endPos.y) {
oYmin = obj.startPos.y;
oYmax = obj.endPos.y;
}
else {
oYmin = obj.endPos.y;
oYmax = obj.startPos.y;
}

return (pos.x > oXmin && pos.x < oXmax && pos.y > oYmin && pos.y < oYmax);

}


There is. You can use Math.min and Math.max to determine which is the smaller end and the larger end. This way, you avoid the if statements.

function isWithinBounds(obj, pos) {
var oXmin = Math.min(obj.startPos.x, obj.endPos.x);
var oXmax = Math.max(obj.startPos.x, obj.endPos.x);
var oYmin = Math.min(obj.startPos.y, obj.endPos.y);
var oYmax = Math.max(obj.startPos.y, obj.endPos.y);
return ( oXmin < pos.x && pos.x < oXmax && oYmin < pos.y && pos.y < oYmax);
}


• Function signature :

since you are checking if a point is within a rectangle, your function signature is too vague, it would be better called isPointInRect. obviously if it is meant to be a method shared by circles, polygons, ... the name is fine.
But as your question is written i'd change the signature and add a comment to precise the strict inclusion, and have arguments ordered like in english :

// Returns if the point is strictly within the rect.
function isPointInRect(pt, rect) {


• DRY / cache your property access :

You should notice at the first glance that you are using again and again the same properties, and writing the same things : it hinders both readability and performances.

You should at least cache startPos, endPos, ptX, ptY :

var startPos = rect.startPos, endPos, rect.endPos;
var ptX = pt.x, ptY = pt.y;


And you might also want to cache startPos.x/y and endPos.x/y, but see the next point.

• Do not repeat computations :

It is most likely that there will be far more point test than rect change : but as you wrote the code, for each point testing you'll have to re-order the rect points.
I suggest that your Rect class already keeps your points or coordinates in the right order. So either have two topLeft, downRight points or left,right, top, down properties (or, the classics : x, y, width, height).

• exit the sooner you can :

Assuming that most point test will fail, you'd better write you last conditional the other way around to exit sooner:

return ! ( ptX <= rect.left || ... || ... || ... ) ;


// Returns if the point is strictly within the rect.
function isPointInRect(pt, rect) {
var ptX = pt.x, ptY = pt.y;
return ! ( ptX <= rect.left || ptX >= rect.right
||  ptY <= rect.top || ptY >= rect.down ) ;
}


(personaly i prefer the x/y/width/height version of the Rect, especially since Rect might extends Point :

// Returns if the point is strictly within the rect.
function isPointInRect(pt, rect) {
var dx = pt.x-rect.x, dy = pt.y-rect.y;
return ! ( dx <= 0 || dx >= rect.width
||  dy <= 0 || dy >= rect.height ) ;
}


)

I'd go with someone like this, which reduces the heart of the logic to a single declarative line (the one with the return statement):

function isWithinBounds(obj, pos) {
var xs = [obj.startPos.x, obj.endPos.x].sort(),
ys = [obj.startPos.y, obj.endPos.y].sort();
return contains(xs, pos.x) && contains(ys, pos.y);
function contains(arr, x) { return x > arr && x < arr }
}


Or if you want to avoid all repetition:

function isWithinBounds(obj, pos) {
var xs = boundsOf('x'), ys = boundsOf('y');
return contains(xs, pos.x) && contains(ys, pos.y);
function contains(arr, x) { return x > arr && x < arr }
function boundsOf(prop) { return [obj.startPos[prop], obj.endPos[prop]].sort() }
}


Though personally I prefer the first variation.

Have not checked to see if this function is faster:

function check(a, b, p) {
var f = b - a, g = b - p;
return (Math.abs(f) >= Math.abs(g)) && (Math.sign(f) === Math.sign(g));
}


To use the function do the following:

function isWithinBounds(obj, pos) {
return check(obj.startPos.x, obj.endPos.x, pos.x) &&
check(obj.startPos.y, obj.endPos.y, pos.y);
}


How Does It Work?

Since your rectangle is always upright, we can focus on just looking at one dimension at a time. The hard part is the fact that you only have two points on the rectangle and we do not know what is the top/right or bottom/left which is why you first figure out which one is greater. So, this attempt was to see if I could still figure out if was in between without actually checking which was top or bottom.

First we take a to be the start and b to be the end. Then we define f to be the difference between the two f = b - a. Also, let the value that we want to know if is between a and b be p. Then we can define g to be the difference between b and p, g = b - p.

So, we can represent all of the different cases a, b, and p can be placed.

|----a----p----b----|
|----b----p----a----|
|----b----a----p----|
|----p----a----b----|
|----a----b----p----|
|----p----b----a----|


Now let us also place the f and g values next to the different combinations.

                        f   g
|----a----p----b----|  +#  +# (|g| < |f|) true
|----b----p----a----|  -#  -# (|g| < |f|) true
|----b----a----p----|  -#  -# (|g| > |f|) false
|----p----a----b----|  +#  +# (|g| > |f|) false
|----a----b----p----|  +#  -# (|g| ? |f|) false
|----p----b----a----|  -#  +# (|g| ? |f|) false


As you can see, when |g| is smaller than |f| and the signs of g and f are the same then p is between a and b.