2
$\begingroup$

This is kind of a geometrical question. For my program I want to compute the minimal distance $r$ from a given point to the cube. Here is a drawing which shows what I mean:

enter image description here

I have two vectors $\vec{p}$ and $\vec{q}$ which indicate the position of my two points. Point $p$ can be anywhere outside the cube. Point $q$ is exactly in the middle of the cube. The distance from point $q$ to the cubes surface is always $d$. I can easily compute $R$ which is the distance from point $q$ to point $p$. But what I need is the minimal distance $r$ from point $p$ to the cube. I am sure that I have to distinguish several cases depending on where point $p$ is located. I think there are three cases:

1) The minimal distance $r$ from point $p$ is to the edge of the cube (as drawn in the picture)

2) The minimal distance $r$ from point $p$ is to the corner of the cube

3) The minimal distance $r$ from point $p$ is to the surface of the cube

After hours of trying to find a nice solution I hope someone can give me a hint.

  • 0
    So what is your problem now. I think your 3 cases are the correct way to go. You can split 3D into $6$ versions of case $3$, $8$ versions of case $1$ and $8$ versions of case $2$. For each version of a case, you know parametric equation of the object on the cube (surface, corner$\approx$point, edge$\approx$line) and you calculate distance?2017-02-07
  • 0
    @Jan That seems like a lot of cases. Since my program computes this a million times, I think this would be highly inefficient. So I hoped there is a better way to do that.2017-02-07
  • 0
    If the cube is axis aligned, there might be tricks to make the calculations easier. Otherwise, there's not much that you can do. However, speed depends on *how* you calculate the distances. Also, is the cube fixed or does it change?2017-02-07
  • 1
    Well a lot of cases, not really. You choose out of 22 cases determined by simple expressions and then you calculate one distance. Can you change your problem? What you are trying to do would be trivial for ball.2017-02-07
  • 0
    @Michael Burr: The cube is axis aligned but not fixed. The cube can be everywhere and can have any size. But point $p$ is always outside.2017-02-07
  • 0
    @Jan Unfortunately I can not use a sphere / circle. It has to be a cube. But how would I start then?2017-02-07
  • 0
    Another idea that might not work for you (if you give us more context we might be able to judge). Continuing on the ball idea. If you need upper and lower bound on the distance, you calculate distance to the ball which has your cube inside and the distance to the ball which is inside your cube.2017-02-07
  • 0
    In your question, the point $q$ plays no role. Is it worth to mention it ?2017-02-07

2 Answers 2

4

For an axis aligned cube, there are nice tricks. Consider, for example, the axis aligned cube with corners $(\pm 1,\pm 1,\pm 1)$ (after a scaling and a shift, everything reduces to this case).

For a point $(x,y,z)$:

  • If $|x|\leq 1$, $|y|\leq 1$ and $|z|>1$, then the distance is $|z|-1$ (the face is closest).

  • If $|x|\leq 1$, $|y|>1$, and $|z|>1$, then the distance is $\sqrt{(|y|-1)^2+(|z|-1)^2}$ (the edge is closest).

  • If $|x|>1$, $|y|>1$, and $|z|>1$, then the distance is $\sqrt{(|x|-1)^2+(|y|-1)^2+(|z|-1)^2}$ (the vertex is closest).

All other cases are similar. To visualize what is going on, draw a square, but extend the edges into (infinite) lines. This breaks up the space outside the box into $8$ regions, all points in each region are closest to the same edge or point. Now, doing the same thing in three dimensions results in $26$ regions and you need to figure out which region you're in.

Pseudocode:

 if |x|<=1
 {
      if |y|<=1
           d=|z|-1
      else
      {
           if |z|<=1
                 d=|y|-1
           else
                 d=sqrt((|y|-1)^2+(|z|-1)^2)
      }
 }
 else
 {
      if |y|<=1
      {
           if |z|<=1
                d=|x|-1
           else
                d=sqrt((|x|-1)^2+(|z|-1)^2)
      }
      else
           if |z|<=1
                d=sqrt((|x|-1)^2+(|y|-1)^2)
           else
                d=sqrt((|x|-1)^2+(|y|-1)^2+(|z|-1)^2)
      }
 }

Also as @YvesDaoust mentions in the comments, this can be rewritten as $$ \sqrt{\max\{0,|x|-1\}^2+\max\{0,|y|-1\}^2+\max\{0,|z|-1\}^2} $$ although, after unpacking the maximums, you get, essentially, the series of inequalities above.

  • 1
    And for a non-axis-aligned cube, and a point $K$ whose distance you want to measure, pick any vertex $P$ and the three adjacent vertices $A,B,C$, and compute $u = A-P, v = B-P, w = C - P$, and $X = K - P$. Let $s = \|u\|$. Compute $x = (X \cdot u)/s; y = (X \cdot v)/s; z = (X \cdot w)/s$. Apply the result above to find a distance $d$; the correct overall value is $ds$.2017-02-07
  • 0
    @JohnHughes Sure, that will work. I was just going for a simple description that could be adapted to other situations.2017-02-07
  • 0
    Completely right; I just figured that getting the generalization right can be a little messy: do you divide by the edge length or multiply? Do you divide by the *square* of the edge-length? Every time I do this, I mess up at least one thing, so I figured I'd throw in a little help. (Or perhaps mess it up again!)2017-02-07
  • 0
    @John Hughes Could you visualize that? I do not see how that works.2017-02-07
  • 0
    @MichaelBurr Does that mean, that I have to run through your three cases 26 times or do I have to check for every point ($x,y,z$) those three points only a single time after scaling and shifting?2017-02-07
  • 0
    What @JohnHughes is doing is changing the coordinates of the space so that the cube becomes axis aligned.2017-02-07
  • 1
    You don't need to run through $26$ cases each time, it's several nested if statements and a lot can be collapsed. The key is that you're doing comparisons instead of square root calculations, which are much faster.2017-02-07
  • 0
    I agree with your discussion, but I disagree with the distance formulas. For a point in the first octant, the squared distance to the corner $(1,1,1)$ is $(x-1)^2+(y-1)^2+(z-1)^2$, the squared distance to the edge $(1,1,z)$ is $(x-1)^2+(y-1)^2$ and to the face $(1,y,z)$, $(x-1)^2$.2017-02-07
  • 0
    @YvesDaoust Yes, you're right. Bad morning for me2017-02-07
  • 2
    Can be written in a very compact (though not optimal) way: √(max(0, |x| - 1)² + max(0, |y| - 1)² + max(0, |z| - 1)²)2017-02-07
  • 0
    @MichaelBurr I do not understand *(after a scaling and a shift, everything reduces to this case)*. Since I have a point $p$ and a box do I scale and shift both? Or only the box? How would (±1,±1,±1) change for a box of diameter $d$ at the position (1,2,3). Would it be (1±d,2±d,3±d)? How would the point ($x,y,z$) change if it were at position (-1,-2,-3)? Any help would be really great!2017-02-07
  • 0
    If you have a box with center $(1,2,3)$, then subtract $(1,2,3)$ from everything and you'll move the box to be centered at the origin. Then, if $d$ is the length of a side of a box, divide the coordinates of the shifted point by $d/2$. This gets you to a box with corners $(\pm 1,\pm 1,\pm 1)$.2017-02-07
0

Formulation as QP: $$ \min \{ x^\top Q x + c^\top x \mid Ax \le b \} $$ where $$ d(x,p)^2 = (x-p)^2 = x^2 - 2 x^\top p + p^2 $$ so $$ Q = I \quad c = -2p $$ and we minimize $d(x,p)^2 - p^2$. Further we have six half-spaces $$ n_i^\top x \le d_i $$ where the $n_i$ are unit normal vectors of the planes through the facets and the $d_i$ is the (signed distance) of the plane to the origin. We have $n_i = - n_j$ for opposite facets.