Можно создать точки в эллипсе, не используя слишком отбрасывающую выборку, тщательно продумав ее определение в полярной форме.Из википедии полярная форма эллипса задается как
Интуитивно говоря, мы должны выбирать полярный угол θ чаще, гдерадиус больше.Если говорить более математически, то наш PDF для случайной величины θ должен быть p (θ) dθ = dA / A, где dA - площадь одного сегмента под углом θ с шириной dθ.Используя уравнение для площади полярного угла dA = 1/2 r 2 dθ и площади эллипса, равной π ab, тогда PDF становится
Для случайной выборки из этого PDF-файла одним прямым методом является метод обратного CDF .Для этого необходимо рассчитать функцию накопленной плотности (CDF) и затем инвертировать эту функцию.Использование Wolfram Alpha для получения неопределенного интеграла, а затем его инвертирование дает обратный CDF, равный
, где u проходит от 0 до 1. Таким образом, для выборки случайногоугол θ, вы просто генерируете равномерное случайное число u между 0 и 1 и подставляете его в это уравнение для обратного CDF.
Чтобы получить случайный радиус, можно использовать ту же технику, которая работает для круга(см., например, Создание случайной точки в круге (равномерно) ).
Вот пример кода Python, который реализует этот алгоритм:
import numpy
import matplotlib.pyplot as plt
import random
# Returns theta in [-pi/2, 3pi/2]
def generate_theta(a, b):
u = random.random() / 4.0
theta = numpy.arctan(b/a * numpy.tan(2*numpy.pi*u))
v = random.random()
if v < 0.25:
return theta
elif v < 0.5:
return numpy.pi - theta
elif v < 0.75:
return numpy.pi + theta
else:
return -theta
def radius(a, b, theta):
return a * b / numpy.sqrt((b*numpy.cos(theta))**2 + (a*numpy.sin(theta))**2)
def random_point(a, b):
random_theta = generate_theta(a, b)
max_radius = radius(a, b, random_theta)
random_radius = max_radius * numpy.sqrt(random.random())
return numpy.array([
random_radius * numpy.cos(random_theta),
random_radius * numpy.sin(random_theta)
])
a = 2
b = 1
points = numpy.array([random_point(a, b) for _ in range(2000)])
plt.scatter(points[:,0], points[:,1])
plt.show()