Compute shortest distance between point and a rectangle I want to compute the shortest distance between a position (x,y) and a rectangular box defined by (x_min, y_min) and (x_max, y_max). See the picture below with some examples. I know that in two dimensions there are 9 cases I have to take into account.



Since this part of my code is used very often, I would like to know what is the fastest possible way to do that? Here is what I have done so far:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;math.h&gt;

#define sqr(x) ((x)*(x))

double distanceBoxParticle2D(double x, double y, double x_min, double y_min, double x_max, double y_max);

int main(){
    double x = -6;
    double y = -6;
    double x_min = -5;
    double x_max = 5;
    double y_min = -5;
    double y_max = 5;

    double distance = distanceBoxParticle2D(x, y, x_min, y_min, x_max, y_max);
    printf("distance = %f\n", distance);

}

double distanceBoxParticle2D(double x, double y, double x_min, double y_min, double x_max, double y_max){
    double r = 0;

    if(x &lt; x_min){
        if(y &lt; y_min){
            return r = sqrt( sqr(x_min-x) + sqr(y_min-y) );
        }else if(y &gt; y_max){
            return r = sqrt( sqr(x_min-x) + sqr(y_max-y) );
        }else if((y &gt;= y_min) &amp;&amp; (y &lt;= y_max)){
            return r = x_min - x;
        }
    }else{
        if((x &gt; x_min) &amp;&amp; (x &lt; x_max)){
            if(y &lt; y_min){
                return r = y_min - y;
            }else if(y &gt; y_max){
                return r = y - y_max;
            }
        }else{
            if(x &gt; x_max){
                if(y &lt; y_min){
                    return r = sqrt( sqr(x_max-x) + sqr(y_min-y) );
                }else if(y &gt; y_max){
                    return r = sqrt( sqr(x_max-x) + sqr(y_max-y) );
                }else if((y &gt;= y_min) &amp;&amp; (y &lt;= y_max)){
                    return r = x - x_max;
                }
            }
        }
    }

    return r = 0; // if (x,y) is inside of the box
}


The example is only for two dimensions. Later I want to do the same in 3D. There I have to consider 27 cases, which is a lot. Is there any smart and fast solution for this case or do I have to hard-code every case?
Bug

If either x == x_min or x == x_max, your function will return 0 even if the point is outside of the rectangle.  This is because none of your if statements included the case where x == x_min or x == x_max, so the flow falls through to the end of the function where you return 0.

Extraneous variable

Your function has a variable r that is set but never used.  You should remove that variable so that lines like this:


        return r = x_min - x;



can turn into this:

        return x_min - x;


Extraneous third comparison

Consider this chain of three if statements:


    if(y &lt; y_min){
        return r = sqrt( sqr(x_min-x) + sqr(y_min-y) );
    }else if(y &gt; y_max){
        return r = sqrt( sqr(x_min-x) + sqr(y_max-y) );
    }else if((y &gt;= y_min) &amp;&amp; (y &lt;= y_max)){
        return r = x_min - x;
    }



The point can either be above the rectangle, below the rectangle, or within the rectangle.  If the point is neither above nor below the rectangle, then it must be within the rectangle.  Therefore, the third comparison can be removed, like this:

    if(y &lt; y_min){
        return r = sqrt( sqr(x_min-x) + sqr(y_min-y) );
    }else if(y &gt; y_max){
        return r = sqrt( sqr(x_min-x) + sqr(y_max-y) );
    }else{
        return r = x_min - x;
    }


Rewrite

In this rewrite, I defined a HYPOT macro to simplify the expression that you use 4 times.  I also modified the indentation so that each case would be at the same indentation level.  Lastly, I reordered the if statements so the order would be "below, inside, above" instead of "below, above, inside", although the order really doesn't matter.  This rewrite was a tiny bit faster (2%) than the original code, possibly due to removing the extraneous third comparisons mentioned above.

#define HYPOT(x, y) sqrt(sqr(x) + sqr(y))

double distanceBoxParticle2D(double x, double y, double x_min, double y_min,
        double x_max, double y_max)
{
    if (x &lt; x_min) {
        if (y &lt; y_min)
            return HYPOT(x_min-x, y_min-y);
        else if (y &lt;= y_max)
            return x_min - x;
        else
            return HYPOT(x_min-x, y_max-y);
    } else if (x &lt;= x_max) {
        if (y &lt; y_min)
            return y_min - y;
        else if (y &lt;= y_max)
            return 0;
        else
            return y - y_max;
    } else {
        if (y &lt; y_min)
            return HYPOT(x_max-x, y_min-y);
        else if (y &lt;= y_max)
            return x - x_max;
        else
            return HYPOT(x_max-x, y_max-y);
    }
}


Here is a more concise variant you might prefer:

double distanceBoxParticle2D(double x, double y, double x_min, double y_min,
        double x_max, double y_max)
{
    if (x &lt; x_min) {
        if (y &lt;  y_min) return HYPOT(x_min-x, y_min-y);
        if (y &lt;= y_max) return x_min - x;
                        return HYPOT(x_min-x, y_max-y);
    } else if (x &lt;= x_max) {
        if (y &lt;  y_min) return y_min - y;
        if (y &lt;= y_max) return 0;
                        return y - y_max;
    } else {
        if (y &lt;  y_min) return HYPOT(x_max-x, y_min-y);
        if (y &lt;= y_max) return x - x_max;
                        return HYPOT(x_max-x, y_max-y);
    }
}