简体   繁体   English

球体上的点

[英]Points on sphere

I am new in Python and I have a sphere of radius (R) and centred at (x0,y0,z0). 我是Python的新手,我有一个半径(R)的球面,并以(x0,y0,z0)为中心。 Now, I need to find those points which are either on the surface of the sphere or inside the sphere eg points (x1,y1,z1) which satisfy ((x1-x0)**2+(y1-y0)**2+(z1-x0)*82)**1/2 <= R. I would like to print only those point's coordinates in a form of numpy array. 现在,我需要找到那些在球体表面或球体内的点,例如满足((x1-x0)** 2+(y1-y0)** 2的点(x1,y1,z1) +(z1-x0)* 82)** 1/2 <=R。我只想以numpy数组的形式打印这些点的坐标。 Output would be something like this-[[x11,y11,z11],[x12,y12,z12],...]. 输出将是这样的-[[x11,y11,z11],[x12,y12,z12],...]。 I have the following code so far- 到目前为止,我有以下代码-

import numpy as np
import math

def create_points_around_atom(number,atom_coordinates):
    n= number
    x0 = atom_coordinates[0]
    y0 = atom_coordinates[1]
    z0 = atom_coordinates[2]
    R = 1.2
    for i in range(n):
        phi = np.random.uniform(0,2*np.pi,size=(n,))
        costheta = np.random.uniform(-1,1,size=(n,))
        u = np.random.uniform(0,1,size=(n,))
        theta = np.arccos(costheta)
        r = R * np.cbrt(u)
        x1 = r*np.sin(theta)*np.cos(phi) 
        y1 = r*np.sin(theta)*np.sin(phi)
        z1 = r*np.cos(theta)
        dist  = np.sqrt((x1-x0)**2+(y1-y0)**2+(z1-z0)**2)
        distance = list(dist)
        point_on_inside_sphere = []
        for j in distance:
            if j <= R:
                point_on_inside_sphere.append(j)
                print('j:',j,'\tR:',R)
                print('The list is:', point_on_inside_sphere)
                print(len(point_on_inside_sphere))
                kk =0
                for kk in range(len(point_on_inside_sphere)):
                    for jj in point_on_inside_sphere:
                        xx = np.sqrt(jj**2-y1**2-z1**2)
                        yy = np.sqrt(jj**2-x1**2-z1**2)
                        zz = np.sqrt(jj**2-y1**2-x1**2)
                    print("x:", xx, "y:", yy,"z:", zz)
                kk +=1 

And I am running it- create_points_around_atom(n=2,structure[1].coords) where, structure[1].coords is a numpy array of three coordinates. 我正在运行它create_points_around_atom(n=2,structure[1].coords) ,其中structure[1].coords是一个由三个坐标组成的numpy数组。

To sum up what has been discussed in the comments, and some other points: 总结评论中讨论的内容以及其他一些要点:

  • There is no need to filter the points because u <= 1 , which means np.cbrt(u) <= 1 and hence r = R * np.cbrt(u) <= R , ie all points will already be inside or on the surface of the sphere. 不需要过滤点,因为u <= 1 ,这意味着np.cbrt(u) <= 1 ,因此r = R * np.cbrt(u) <= R ,即所有点都已经在内部或内部球体的表面。

  • Calling np.random.uniform with size=(n,) creates an array of n elements, so there's no need to do this n times in a loop. 调用size=(n,) np.random.uniform会创建一个由n元素组成的数组,因此无需循环执行n次。

  • You are filtering distances from the atom_coordinate , but the points you are generating are centered on [0, 0, 0] , because you are not adding this offset. 您正在过滤atom_coordinate距离,但是生成的点以[0, 0, 0]为中心,因为您没有添加此偏移量。

  • Passing R as an argument seems more sensible than hard-coding it. R作为参数传递似乎比对它进行硬编码更为明智。

  • There's no need to "pre-load" arguments in Python like one would sometimes do in C. 无需像在C语言中有时那样“预加载” Python中的参数。

  • Since sin(theta) is non-negative over the sphere, you can directly calculate it from the costheta array using the identity cos²(x) + sin²(x) = 1 . 由于sin(theta)在球面上是非负的,因此您可以使用costheta cos²(x) + sin²(x) = 1costheta数组直接计算出它。

Sample implementation: 示例实施:

# pass radius as an argument
def create_points_around_atom(number, center, radius):

    # generate the random quantities
    phi         = np.random.uniform( 0, 2*np.pi, size=(number,))
    theta_cos   = np.random.uniform(-1,       1, size=(number,))
    u           = np.random.uniform( 0,       1, size=(number,))

    # calculate sin(theta) from cos(theta)
    theta_sin   = np.sqrt(1 - theta_cos**2)
    r           = radius * np.cbrt(u)

    # use list comprehension to generate the coordinate array without a loop
    # don't forget to offset by the atom's position (center)
    return np.array([
        np.array([
            center[0] + r[i] * theta_sin[i] * np.cos(phi[i]),
            center[1] + r[i] * theta_sin[i] * np.sin(phi[i]),
            center[2] + r[i] * theta_cos[i]
        ]) for i in range(number)
    ])

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

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