1

I have an mx3 array that is used to create a 3d model. Is there is a fast way to extract all the points that belong to a given plane using numpy or other python functions? The plane will take the Ax+By+Cz+D=0 form. I'm currently looping through all the points in the array to find the points that satisfy this equation.

plane1=[]
for i in pcd_array:
    if (normal_vector[0]*(i[0]-point1[0])+normal_vector[1]*(i[1]-point1[1])+normal_vector[2]*(i[2]-point1[2]))==0:
        plane1.append(i)

I'm wondering is there any numpythonic way to do it to make it faster?

hrokr
  • 3,276
  • 3
  • 21
  • 39
yihao ren
  • 369
  • 1
  • 4
  • 15
  • You know A, B, C, D? – anon01 Sep 21 '20 at 06:25
  • I assume that what you're doing here is calculating distances to the plane from a point? Put your vectors into a numpy array, calculate distances for all points as another numpy array and then filter for all points that have 0 distance. It will certainly be much faster than having hundreds of `if`s – NotAName Sep 21 '20 at 06:26

3 Answers3

2

Vectorization will be much faster. In the example below, all points below lie on integer values in the region -100 < x,y,z < 100. The matrix p contains one million points; we calculate all points that lie on a given plane (almost instantaneously):

# define 1M points at random:
p = np.random.randint(-100,100, size=(1000000,3))

# A,B,C (c0) are arbitrary values; define D so plane intersects first point:    
c0 = np.array([3,5,7])
D = -p[0].dot(c0) 

# return all points in plane Ax + By + Cz + D = 0
p_in_plane = p[p.dot(c0) + D == 0]
anon01
  • 10,618
  • 8
  • 35
  • 58
0

Does the following help? I'm assuming it is fast because it is not using any for loops. My answer is based on this

import numpy as np

mat  = np.arange(18).reshape(6,3)
mat[5,:] = [0,1,2]

aa   = 1
bb   = 2
cc   = 3
dd   = -8
mask = mat[:,0]*aa + mat[:,1]*bb + mat[:,2]*cc + dd == 0
selected = mat[mask,:]
NNN
  • 697
  • 1
  • 5
  • 15
0

Using numpy where to find all points that match a condition

Code

import numpy as np

def get_planer_indexes(pts, plane):
    '''
        :parm pts    - array of 3D points
        :param plane - coefficient of plane (i.e. A, B, C, D)
        :returns     - indexes of points which are in plance
    '''
    # Compute A*pt[0] + B*pt[1] + C*pt[3] + D for each point pt in pts
    # Checks that abs(...) is below threshold (1e-6) to allow for floating point error
    return np.where(np.abs(points.dot(plane[:3]) + plane[3]) <= 1e-6 )

Example Usage

#    Create 3 points which lie in a plane
P1 = [1, -2, 0]
P2 = [3, 1, 4]
P3 = [0, -1, 2]
planar_pts = np.array([P1, P2, P3])

# Plane that P1, P2, P3 lie within
plane = np.array([2, -8, 5, -18]) # i.e. A = 2, B = -8, C = 5, D = -18

# Random 3 D points (100 points)
rand_points = np.random.rand(100, 3)

#    Stack onto planar points
points = np.vstack((planar_pts, rand_points))

#    Shuffle the points (so planar points are in random locations)
np.random.shuffle(points)

#    Find planar points
indexes = get_planer_indexes(points, plane)
print(points[indexes])

Output

[[ 3.  1.  4.]
 [ 0. -1.  2.]
 [ 1. -2.  0.]]
DarrylG
  • 16,732
  • 2
  • 17
  • 23