Алгоритм. Вычислить псевдослучайную точку внутри эллипса.
Для простой системы частиц, которую я создаю, мне нужно, учитывая эллипс с шириной и высотой, вычислить случайную точку X, Y, которая лежит в этом эллипсе.
Теперь я не лучший в математике, поэтому я хотел спросить здесь, может ли кто-нибудь указать мне в правильном направлении.
Возможно, правильный способ - выбрать случайный float в диапазоне ширины, взять его для X и из него рассчитать значение Y?
Ответы
Ответ 1
-
Создайте случайную точку внутри круга радиуса 1. Это можно сделать, взяв случайный угол phi
в интервале [0, 2*pi)
и случайное значение rho
в интервале [0, 1)
и вычислить
x = sqrt(rho) * cos(phi)
y = sqrt(rho) * sin(phi)
Квадратный корень в формуле обеспечивает равномерное распределение внутри круга.
-
Масштаб x
и y
к размерам эллипса
x = x * width/2.0
y = y * height/2.0
Ответ 2
Используйте выборку отбраковки: выберите случайную точку в прямоугольнике вокруг эллипса. Проверьте, находится ли точка внутри эллипса, проверив знак (x-x0) ^ 2/a ^ 2 + (y-y0) ^ 2/b ^ 2-1. Повторяйте, если точка не внутри. (Это предполагает, что эллипс выровнен с координатными осями. Аналогичное решение работает в общем случае, но, конечно, сложнее).
Ответ 3
Вы можете использовать преобразование координат с квадратом в декарте:
x = cos(angle) * radius
y = sin(angle) * radius
что небольшое изменение
x = cos(angle) * width
y = sin(angle) * height
Вы не указали какой-либо язык, но здесь приведена быстрая демонстрация с помощью Обработки:
float ellipseWidth = 150,ellipseHeight = 100;
float angle,radius,x,y;
void setup(){
size(400,400);
smooth();
noStroke();
ellipseMode(CENTER);
background(0);
fill(255);
}
void draw(){
//choose a random angle on the ellipse
angle = random(TWO_PI);
//convert from polar to cartesian, using both width and height as radii
x = cos(angle) * ellipseWidth;
y = sin(angle) * random(ellipseHeight);//random 'lengths' vertically
//draw
translate(200,200);//move to centre
ellipse(x,y,5,5);
}
Вы можете увидеть, как он запускает здесь
![points in ellipse]()
НТН
Ответ 4
Я бы предложил очень простой метод:
- Выберите случайный X
- Рассчитайте верхнюю и нижнюю границы Y для этого конкретного X
- Рандомизировать Y в пределах расчетных границ
Формула Bounds (любезность Википедии):
![Upper and lower bounds]()
Ответ 5
Можно создавать точки внутри эллипса без использования отбраковки выборки, тщательно учитывая ее определение в полярной форме. Из wikipedia полярная форма эллипса задается символом
![Полярный радиус эллипса]()
Интуитивно говоря, мы должны чаще выбирать полярный угол θ, где радиус больше. Математически, наш PDF для случайной величины θ должен быть p (θ) dθ = dA/A, где dA - площадь одного сегмента под углом θ с шириной dθ. Используя уравнение для области полярного угла dA = 1/2 r 2 dθ, а площадь эллипса равна π a b, тогда PDF становится
![Theta PDF]()
Для случайного отбора из этого PDF-документа одним прямым методом является метод ![Обратный 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()
![Случайно сгенерированные точки в эллипсе с осями 2 и 1]()