Очки на сфере - PullRequest
       5

Очки на сфере

0 голосов
/ 29 декабря 2018

Я новичок в Python, и у меня есть сфера радиуса (R) с центром в (x0, y0, z0).Теперь мне нужно найти те точки, которые находятся либо на поверхности сферы, либо внутри сферы, например, точки (x1, y1, z1), которые удовлетворяют ((x1-x0) ** 2+ (y1-y0) ** 2+ (z1-x0) * 82) ** 1/2 <= R. Я хотел бы вывести только координаты этих точек в виде массива с нулевыми углами.Вывод будет выглядеть примерно так - [[x11, y11, z11], [x12, y12, z12], ...].Пока у меня есть следующий код - </p>

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 

И я запускаю его - create_points_around_atom(n=2,structure[1].coords), где structure[1].coords - это массив из трех координат.

1 Ответ

0 голосов
/ 29 декабря 2018

Подводя итог тому, что обсуждалось в комментариях, и некоторые другие пункты:

  • Нет необходимости фильтровать точки, потому что u <= 1, что означает np.cbrt(u) <= 1 иследовательно, r = R * np.cbrt(u) <= R, то есть все точки уже будут внутри или на поверхности сферы.

  • При вызове np.random.uniform с size=(n,) создается массив из n элементов, поэтомунет необходимости делать это n раз в цикле.

  • Вы фильтруете расстояния от atom_coordinate, но точки, которые вы генерируете, центрированы на [0, 0, 0], потому чтоВы не добавляете это смещение.

  • Передача R в качестве аргумента кажется более разумным, чем его жесткое кодирование.

  • Нет необходимостичтобы «предварительно загрузить» аргументы в Python, как это иногда делается в C.

  • Поскольку sin(theta) неотрицательно по сфере, вы можете напрямую рассчитать его из costheta массив с использованием идентификатора cos²(x) + sin²(x) = 1.

Пример реализации:

# 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)
    ])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...