繁体   English   中英

如何找到一条线与 numpy 网格生成的表面之间的交点?

[英]How to find intersection point between a line and numpy meshgrid generated surface?

我有一个使用 function 生成的表面,z = f(x,y),其中 x,y arrays 被传递到 numpy 网格以生成表面点。 从任意两个点,我使用线方程和平面方程来找到交点。 但是我的脚本找不到交集,特别是在我求解 t 的那一步。

3d 直线方程:t = x-xo/l = y-yo/m =z-zo/n 平面方程:ax+by+cz=d

我的测试脚本如下,仅生成 NaN 或 Inf。 我期望的 output 的值是我可以将其重新插入线方程以找到我的交点 (x,y,z)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# generate the surface
x = np.linspace(0,100,10)
y = np.linspace(0,100,10)
xv, yv = np.meshgrid(x,y)
zv = (xv**2+yv)
pos = np.vstack([xv.ravel(), yv.ravel(), zv.ravel()]).T

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(xv,yv,zv)
plt.show()

zv_n1 = []
zv_n2 = []
p3 = []

i_range = zv.shape[0]
j_range = zv.shape[1]

# find AB, AC vectors, a surface point to later compute the normal vec and then plane equation
for i in range(i_range):
    for j in range(j_range):
        if i<i_range-1 and j<j_range-1:
            zv_a = zv[i,j+1]-zv[i,j]
            zv_b = zv[i+1,j]-zv[i,j]
            p3_arr = np.array([xv[i+1,j], yv[i+1,j], zv[i+1,j]])
            
        if i == i_range-1 and j < j_range-1:
            zv_a = zv[i,j+1]-zv[i,j]
            zv_b = zv[i-1,j]-zv[i,j]
            p3_arr = np.array([xv[i-1,j], yv[i-1,j], zv[i-1,j]])
            
        if i < i_range-1 and j == j_range-1:
            zv_a = zv[i,j-1]-zv[i,j]
            zv_b = zv[i+1,j]-zv[i,j]
            p3_arr = np.array([xv[i+1,j], yv[i+1,j], zv[i+1,j]])
            
        zv_n1.append(zv_a)
        zv_n2.append(zv_b)
        p3.append(p3_arr)
       

# sorting in pandas df
temp_df = pd.DataFrame(pd.Series(pos[:,0]), columns = ['x_val'])
temp_df['y_val'] = pd.DataFrame(pd.Series(pos[:,1]))
temp_df['z_val'] = pd.DataFrame(pd.Series(pos[:,2]))

temp_df['x1_del'] = x[1] # delta x is same for panels
temp_df['y1_del'] = y[1] # delta y is same for panels
temp_df['z1_del'] = pd.DataFrame(pd.Series(zv_n1))
temp_df['x2_del'] = x[0] # delta x is same for panels
temp_df['y2_del'] = y[0] # delta y is same for panels
temp_df['z2_del'] = pd.DataFrame(pd.Series(zv_n2))

temp_df['p3'] = pd.DataFrame(pd.Series(p3))

# compute normal vec (and thus find a,b,c coeff, and then find d value)
cross_list = []
d_val_list = []
for i in range(len(temp_df)):
    a_vec = np.array([temp_df.iloc[i]['x1_del'],temp_df.iloc[i]['y1_del'],temp_df.iloc[i]['z1_del']])
    b_vec = np.array([temp_df.iloc[i]['x2_del'],temp_df.iloc[i]['y2_del'],temp_df.iloc[i]['z2_del']])
    nor_vec = np.cross(a_vec,b_vec)
    cross_list.append(nor_vec)
    d_val = np.dot(nor_vec,temp_df.iloc[i]['p3'])
    d_val_list.append(d_val)

temp_df['normal_vec'] = pd.DataFrame(pd.Series(cross_list))
temp_df['plane_d_val'] = pd.DataFrame(pd.Series(d_val_list))

# create two points and find the line vector
p1 = np.array([0,60,0])
p2 = np.array([0,60,5000])
p_vec = p2-p1

# solve for t - rearrange line equations (t = X-x/l = Y-y/m = Z-z/n) to (X =tl+x) and so on..
# and plug in plane equation ax+by+cz=d
for i in range(len(temp_df)):
    t = (temp_df.iloc[i]['plane_d_val'] - \
        temp_df.iloc[i]['normal_vec'][0] * temp_df.iloc[i]['p3'][0] - \
        temp_df.iloc[i]['normal_vec'][1] * temp_df.iloc[i]['p3'][1] - \
        temp_df.iloc[i]['normal_vec'][2] * temp_df.iloc[i]['p3'][2])/(\
            temp_df.iloc[i]['normal_vec'][0] * p_vec[0] +\
            temp_df.iloc[i]['normal_vec'][1] * p_vec[1] +\
            temp_df.iloc[i]['normal_vec'][2] * p_vec[2])
    print(t)

# after finding t, plug in line equation to solve for X

对于这个问题,我将不胜感激。 也欢迎任何关于替代方法/库的建议,因为唯一的目的是识别交点。

谢谢,

所以我想出了我的代码问题。 使用平面上的点而不是线上的点。

此测试脚本也不适用于曲面函数。 仅仅用数学方法求解方程似乎是明智的。

无论如何,更新的代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

x = np.linspace(0,100,10)
y = np.linspace(0,100,10)
xv, yv = np.meshgrid(x,y)
zv = (xv**2+yv)

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(xv,yv,zv)
plt.show()


xv_n1 = []
xv_n2 = []

yv_n1 = []
yv_n2 = []

zv_n1 = []
zv_n2 = []

p3 = []

i_range = zv.shape[0]
j_range = zv.shape[1]

count = -1
for i in range(i_range):
    for j in range(j_range):
        count += 1
        if i<i_range-1 and j<j_range-1:
            # now x
            xv_a = xv[i,j+1]-xv[i,j]
            xv_b = xv[i+1,j]-xv[i,j]
            # now y
            yv_a = yv[i,j+1]-yv[i,j]
            yv_b = yv[i+1,j]-yv[i,j]
            #now z
            zv_a = zv[i,j+1]-zv[i,j]
            zv_b = zv[i+1,j]-zv[i,j]
            p3_arr = np.array([xv[i+1,j], yv[i+1,j], zv[i+1,j]])
            
        if i == i_range-1 and j < j_range-1:
            # now x
            xv_a = xv[i,j+1]-xv[i,j]
            xv_b = xv[i-1,j]-xv[i,j]
            # now y
            yv_a = yv[i,j+1]-yv[i,j]
            yv_b = yv[i-1,j]-yv[i,j]
            #now z
            zv_a = zv[i,j+1]-zv[i,j]
            zv_b = zv[i-1,j]-zv[i,j]
            p3_arr = np.array([xv[i-1,j], yv[i-1,j], zv[i-1,j]])
            
        if i < i_range-1 and j == j_range-1:
            # now x
            xv_a = xv[i,j-1]-xv[i,j]
            xv_b = xv[i+1,j]-xv[i,j]
            # now y
            yv_a = yv[i,j-1]-yv[i,j]
            yv_b = yv[i+1,j]-yv[i,j]
            #now z
            zv_a = zv[i,j-1]-zv[i,j]
            zv_b = zv[i+1,j]-zv[i,j]
            p3_arr = np.array([xv[i+1,j], yv[i+1,j], zv[i+1,j]])
            
        xv_n1.append(xv_a)
        xv_n2.append(xv_b)
        
        yv_n1.append(yv_a)
        yv_n2.append(yv_b)
        
        zv_n1.append(zv_a)
        zv_n2.append(zv_b)
        p3.append(p3_arr)
       
pos = np.vstack([xv.ravel(), yv.ravel(), zv.ravel()]).T

temp_df = pd.DataFrame(pd.Series(pos[:,0]), columns = ['x_val'])
temp_df['y_val'] = pd.DataFrame(pd.Series(pos[:,1]))
temp_df['z_val'] = pd.DataFrame(pd.Series(pos[:,2]))

temp_df['x1_del'] = x[1]
temp_df['y1_del'] = y[1]
temp_df['z1_del'] = pd.DataFrame(pd.Series(zv_n1))
temp_df['x2_del'] = x[0]
temp_df['y2_del'] = y[0]
temp_df['z2_del'] = pd.DataFrame(pd.Series(zv_n2))

temp_df['p3'] = pd.DataFrame(pd.Series(p3))


cross_list = []
d_val_list = []
for i in range(len(temp_df)):
    a_vec = np.array([temp_df.iloc[i]['x1_del'],temp_df.iloc[i]['y1_del'],temp_df.iloc[i]['z1_del']])
    b_vec = np.array([temp_df.iloc[i]['x2_del'],temp_df.iloc[i]['y2_del'],temp_df.iloc[i]['z2_del']])
    nor_vec = np.cross(a_vec,b_vec)
    cross_list.append(nor_vec)
    d_val = np.dot(nor_vec,temp_df.iloc[i]['p3'])
    d_val_list.append(d_val)

temp_df['normal_vec'] = pd.DataFrame(pd.Series(cross_list))
temp_df['plane_d_val'] = pd.DataFrame(pd.Series(d_val_list))


p1 = np.array([0,60,6000])
p2 = np.array([100,60,6000])
p_vec = p2-p1

for i in range(len(temp_df)):
    t = (temp_df.iloc[i]['plane_d_val'] - \
        temp_df.iloc[i]['normal_vec'][0] * p1[0] - \
        temp_df.iloc[i]['normal_vec'][1] * p1[1] - \
        temp_df.iloc[i]['normal_vec'][2] * p1[2])/(\
            temp_df.iloc[i]['normal_vec'][0] * p_vec[0] +\
            temp_df.iloc[i]['normal_vec'][1] * p_vec[1] +\
            temp_df.iloc[i]['normal_vec'][2] * p_vec[2])

p1 = np.array([0,60,6000])
p2 = np.array([100,60,6000])
p_vec = p2-p1

for i in range(len(temp_df)):
    t = (temp_df.iloc[i]['plane_d_val'] - \
        temp_df.iloc[i]['normal_vec'][0] * p2[0] - \
        temp_df.iloc[i]['normal_vec'][1] * p2[1] - \
        temp_df.iloc[i]['normal_vec'][2] * p2[2])/(\
            temp_df.iloc[i]['normal_vec'][0] * p_vec[0] +\
            temp_df.iloc[i]['normal_vec'][1] * p_vec[1] +\
            temp_df.iloc[i]['normal_vec'][2] * p_vec[2])

if np.isnan(t) == True:
    q = np.nan
elif t == 0:
    q = np.nan
elif np.isinf(t) == True:
    q = np.nan
else:
    x = t*p_vec[0]+p2[0]
    y = t*p_vec[1]+p2[1]
    z = t*p_vec[2]+p2[2]
    q = np.array([x,y,z])
    
print(q)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM