Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine a point is inside or outside a cube?

Tags:

c#

geometry

Given a cube with 8 vertex in 3D space. How could I determine the myPoint is inside or outside the cube?

cube[0] = (x0, y0, z0);
cube[1] = (x1, y1, z1);
cube[2] = (x2, y2, z2);
cube[3] = (x3, y3, z3);
cube[4] = (x4, y4, z4);
cube[5] = (x5, y5, z5);
cube[6] = (x6, y6, z6);
cube[7] = (x7, y7, z7);

myPoint = (x, y, z);

I am trying to implement this data filter technique in 3D

like image 325
jhyap Avatar asked Jan 10 '14 06:01

jhyap


1 Answers

Special Case #1 (Axis Aligned Cube):

As maxim1000's answer shows, you can simply check if X, Y, Z coordinates of the point in consideration lie in the minimum and maximum of the X, Y, Z coordinates of the Cube.

X_min <= X <= X_max and Y_min <= Y <= Y_max  and Z_min <= Z <= Z_max

If the aforementioned condition is satisfied then, the point lies inside the cube, otherwise it does not.

General Case (Oriented Cube):

There are two approaches to solve this. First one brings the point in the local coordinate system of the cube and apply the aforementioned Special Case. Second case works on the concept of the projection of the vector. First case is little more complex than the second as you need to calculate the rotation matrix which transforms the point from the world coordinate system into the Cube's local coordinate system. Consider the cube as show in the following figure.

enter image description here

For both the approaches we would need to derive some basic information from the cube representation. Let us fix origin in the local coordinate system of the cube at the bottom left corner of the cube; in this case, it is Point D. Now calculate the unit direction vectors in three dimensions and extent of the cube in those directions. It can be done as follows.

enter image description here

The Xlocal, Ylocal, and Zlocal are illustrated in the figure with Blue, Red, Green colors. And Xlength, Ylength, and Zlength are the extents along the axes.

Now lets get back to solving the problem.

Approach #1: Bring the point in consideration, in the local coordinate system of the Cube. To do that, we need to estimate the rotation matrix. Rotation matrix in this case is 3 x 3 matrix with Xlocal, Ylocal, and Zlocal as columns.

enter image description here

Using the rotation Matrix R, you can bring the point in the local coordinate system and then apply the special case of axis aligned cube.

Approach #2:

Construct the direction vector from the cube center to the point in consideration and project it onto each local axis and check if the projection spans beyond the extent of the cube along that axis. If the projection lies inside the extent along each axis, then point is inside, otherwise it is outside of the cube.

enter image description here

The center of the cube is I, as show in the figure. The direction vector from the center of the cube to the point P is V. The projection of the vector V on Xlocal, Ylocal, and Zlocal can be calculated as follows.

enter image description here

Now the point P is inside the cube only if all of the following conditions are satisfied.

enter image description here

Here's the quick implementation in python for the approach #2.

import numpy as np

def inside_test(points , cube3d):
    """
    cube3d  =  numpy array of the shape (8,3) with coordinates in the clockwise order. first the bottom plane is considered then the top one.
    points = array of points with shape (N, 3).

    Returns the indices of the points array which are outside the cube3d
    """
    b1,b2,b3,b4,t1,t2,t3,t4 = cube3d

    dir1 = (t1-b1)
    size1 = np.linalg.norm(dir1)
    dir1 = dir1 / size1

    dir2 = (b2-b1)
    size2 = np.linalg.norm(dir2)
    dir2 = dir2 / size2

    dir3 = (b4-b1)
    size3 = np.linalg.norm(dir3)
    dir3 = dir3 / size3

    cube3d_center = (b1 + t3)/2.0

    dir_vec = points - cube3d_center

    res1 = np.where( (np.absolute(np.dot(dir_vec, dir1)) * 2) > size1 )[0]
    res2 = np.where( (np.absolute(np.dot(dir_vec, dir2)) * 2) > size2 )[0]
    res3 = np.where( (np.absolute(np.dot(dir_vec, dir3)) * 2) > size3 )[0]

    return list( set().union(res1, res2, res3) )
like image 177
bhushan Avatar answered Oct 05 '22 12:10

bhushan