检查点是否比contains_point方法更快地在椭圆内

Mar*_*oth 9 python matplotlib ellipse python-3.x

我使用matplotlib 1.15.1,我尝试生成这样的散点图:

例

椭圆具有固定尺寸,并以中心坐标,宽度,高度和角度绘制(从外部提供):我不知道它们的等距是多少.

g_ell_center = (0.8882, 0.8882)
g_ell_width = 0.36401857095483
g_ell_height = 0.16928136341606
g_ellipse = patches.Ellipse(g_ell_center, g_ell_width, g_ell_height, angle=angle, fill=False, edgecolor='green', linewidth=2)
Run Code Online (Sandbox Code Playgroud)

这个省略号应标记我的图上的正常和半正常数据.然后,我有一个~500点的数组,必须根据它们所属的椭圆进行着色.所以我尝试用contains_point方法检查每个点:

colors_array = []
colors_scheme = ['green', 'yellow', 'black']
for point in points_array:
    if g_ellipse.contains_point(point, radius=0):
        colors_array.append(0)
    elif y_ellipse.contains_point(point, radius=0):
        colors_array.append(1)
    else:
        colors_array.append(2)
Run Code Online (Sandbox Code Playgroud)

最后,得出了一些观点:

plt.scatter(x_array, y_array, s=10, c=[colors_scheme[x] for x in colors_array], edgecolor="k", linewidths=0.3)
Run Code Online (Sandbox Code Playgroud)

但contains_point非常慢!对于300点散点图,它工作了5分钟,我必须并行生成数千个散点图.也许有更快的方法?PS整个项目绑定到matplotlib,我不能使用其他库.

tmd*_*son 9

给定椭圆的中心,宽度,高度和角度,此方法应测试点是否在椭圆内.您可以找到相对于椭圆中心的点的x和y坐标,然后将使用该角度的点转换为沿长轴和短轴的坐标.最后,您可以找到该点与单元格中心的归一化距离,其中椭圆上的距离为1,内部小于1,外部大于1.

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

fig,ax = plt.subplots(1)
ax.set_aspect('equal')

# Some test points
x = np.random.rand(500)*0.5+0.7
y = np.random.rand(500)*0.5+0.7

# The ellipse
g_ell_center = (0.8882, 0.8882)
g_ell_width = 0.36401857095483
g_ell_height = 0.16928136341606
angle = 30.

g_ellipse = patches.Ellipse(g_ell_center, g_ell_width, g_ell_height, angle=angle, fill=False, edgecolor='green', linewidth=2)
ax.add_patch(g_ellipse)

cos_angle = np.cos(np.radians(180.-angle))
sin_angle = np.sin(np.radians(180.-angle))

xc = x - g_ell_center[0]
yc = y - g_ell_center[1]

xct = xc * cos_angle - yc * sin_angle
yct = xc * sin_angle + yc * cos_angle 

rad_cc = (xct**2/(g_ell_width/2.)**2) + (yct**2/(g_ell_height/2.)**2)

colors_array = []

for r in rad_cc:
    if r <= 1.:
        # point in ellipse
        colors_array.append('green')
    else:
        # point not in ellipse
        colors_array.append('black')

ax.scatter(x,y,c=colors_array,linewidths=0.3)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

请注意,整个脚本需要0.6秒才能运行并处理500个点.这包括创建和保存图形等.

在我的macbook pro上计算点的距离和颜色需要0.00017秒.