Math 超椭圆点拾取

Math 超椭圆点拾取,math,random,Math,Random,我读过关于如何从圆和椭圆中选择点的SO问题 如何从超椭圆的内部均匀地选择随机点 更一般地说,如何从任意超级公式描述的曲线内部均匀地选择随机点 丢弃方法不被认为是一种解决方案,因为它在数学上是不容易理解的。为了对超椭圆进行采样,让我们假设a=b=1,而不丧失一般性。然后,可通过重新缩放相应轴来获得一般情况 第一象限中的点(正x坐标和正y坐标)可以如下所示: 对于0,您是否在询问如何在特定编程语言中执行此操作?如果是,请具体说明。如果从数学的角度来看,我只是想要一个通用的伪代码风格的算法。我使用的

我读过关于如何从圆和椭圆中选择点的SO问题

如何从超椭圆的内部均匀地选择随机点

更一般地说,如何从任意超级公式描述的曲线内部均匀地选择随机点


丢弃方法不被认为是一种解决方案,因为它在数学上是不容易理解的。

为了对超椭圆进行采样,让我们假设
a=b=1
,而不丧失一般性。然后,可通过重新缩放相应轴来获得一般情况

第一象限中的点(正x坐标和正y坐标)可以如下所示:


对于
0,您是否在询问如何在特定编程语言中执行此操作?如果是,请具体说明。如果从数学的角度来看,我只是想要一个通用的伪代码风格的算法。我使用的语言非常灵活,所以应该很好,最好将其作为伪代码留给未来的读者。
x = r * ( cos(t) )^(2/n)
y = r * ( sin(t) )^(2/n)
dx*dy = (2/n) * r * (sin(2*t)/2)^(2/n - 1) dr*dt
      = (1/n) * d(r^2) * d(f(t))
f(t) = -(n/2) * 2F1(1/n, (n-1)/n, 1 + 1/n, cos(t)^2) * cos(t)^(2/n)
import numpy as np
from numpy.random import uniform, randint, seed
from scipy.optimize import brenth, ridder, bisect, newton
from scipy.special import gamma, hyp2f1

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

seed(100)

def superellipse_area(n):
    #https://en.wikipedia.org/wiki/Superellipse#Mathematical_properties
    inv_n = 1. / n
    return 4 * ( gamma(1 + inv_n)**2 ) / gamma(1 + 2*inv_n)

def sample_superellipse(n, num_of_points = 2000):

    def f(n, x):
        inv_n = 1. / n
        return -(n/2)*hyp2f1(inv_n, 1 - inv_n, 1 + inv_n, x)*(x**inv_n)

    lb = f(n, 0.5)
    ub = f(n, 0.0)

    points = [None for idx in range(num_of_points)]
    for idx in range(num_of_points):
        r = np.sqrt(uniform())

        v = uniform(lb, ub)

        w = bisect(lambda w: f(n, w**n) - v, 0.0, 0.5**(1/n))
        z = w**n

        x = r * z**(1/n)
        y = r * (1 - z)**(1/n)

        if uniform(-1, 1) < 0:
            y, x = x, y
        x = (2*randint(0, 2) - 1)*x
        y = (2*randint(0, 2) - 1)*y

        points[idx] = [x, y]
    return points

def plot_superellipse(ax, n, points):
    coords_x = [p[0] for p in points]
    coords_y = [p[1] for p in points]

    ax.set_xlim(-1.25, 1.25)
    ax.set_ylim(-1.25, 1.25)
    ax.text(-1.1, 1, '{n:.1f}'.format(n = n), fontsize = 12)
    ax.scatter(coords_x, coords_y, s = 0.6)

params = np.array([[0.5, 1], [2, 4]])

fig = plt.figure(figsize = (6, 6))
gs = gridspec.GridSpec(*params.shape, wspace = 1/32., hspace = 1/32.)

n_rows, n_cols = params.shape
for i in range(n_rows):
    for j in range(n_cols):
        n = params[i, j]
        ax = plt.subplot(gs[i, j])

        if i == n_rows-1:
            ax.set_xticks([-1, 0, 1])
        else:
            ax.set_xticks([])

        if j == 0:
            ax.set_yticks([-1, 0, 1])
        else:
            ax.set_yticks([])

        #ensure that the ellipses have similar point density
        num_of_points = int(superellipse_area(n) / superellipse_area(2) * 4000)

        points = sample_superellipse(n, num_of_points)
        plot_superellipse(ax, n, points)

fig.savefig('fig.png')