有没有一种聪明的方法来确定任意形状内的点?

Is there a clever way to determine the points that are inside of an arbitrary shape?

我的目标是确定点是否位于形状内部。考虑以下示例:

import numpy as np
from matplotlib import pyplot as plt
import warnings
warnings.filterwarnings('ignore', 'invalid value encountered in sqrt')

r1 = 10
r2 = 4
a = 12  # x shift for circle 2
b = -4  # y shift for circle 2

theta = np.arange(0, 2*np.pi, 0.0006)

r1_complex = r1*np.exp(1j*theta)
r1_x, r1_y = np.real(r1_complex), np.imag(r1_complex)

r2_complex = r2*np.exp(1j*theta)
r2_x, r2_y = np.real(r2_complex) + a, np.imag(r2_complex) + b

fig, ax = plt.subplots()

ax.plot(r1_x, r1_y)
ax.plot(r2_x, r2_y)

ax.set_aspect('equal')
ax.grid()
plt.show()

输出

我想找到橙色圆圈内部的蓝色圆圈的点。如果可能的话,最好不要迭代地尝试找到它。

对于这种情况,我可以很容易地确定橙色圆圈内的点,因为我知道圆的方程。将代码修改为:

import numpy as np
from matplotlib import pyplot as plt
import warnings
warnings.filterwarnings('ignore', 'invalid value encountered in sqrt')

r1 = 10
r2 = 4
a = 12  # x shift for circle 2
b = -4  # y shift for circle 2

theta = np.arange(0, 2*np.pi, 0.0006)

r1_complex = r1*np.exp(1j*theta)
r1_x, r1_y = np.real(r1_complex), np.imag(r1_complex)

r1_inside_y = np.logical_and(r1_y < np.sqrt(r2**2 - (r1_x - a)**2) + b, r1_y > -np.sqrt(r2**2 - (r1_x - a)**2) + b)

r2_complex = r2*np.exp(1j*theta)
r2_x, r2_y = np.real(r2_complex) + a, np.imag(r2_complex) + b

fig, ax = plt.subplots()

ax.plot(r1_x, r1_y)
ax.plot(r2_x, r2_y)
ax.plot(r1_x[r1_inside_y], r1_y[r1_inside_y])

ax.set_aspect('equal')
ax.grid()
plt.show()

输出

产生了我正在寻找的东西。有没有办法在不知道圆的方程式的情况下得到同样的结果?也许是一种算法,或者是 numpy 操作的巧妙方法?

编辑

我说的任意形状是一种有N个点的闭合形状。考虑这张图片:

我想知道黑线中位于红线范围内的点。对于这个例子,这个算法应该找到两个点,蓝色的 x4 和 x5 点。点 x1, x2, ... xN 将是两个形状共享相同原点的坐标点。

原来,这个算法已经在matplotlib.path模块中标准化了。您可以使用 Path class 产生相同的结果。考虑对上述代码进行以下更改:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import path

r1 = 10
r2 = 4
a = 12  # x shift for circle 2
b = -4  # y shift for circle 2

theta = np.arange(0, 2*np.pi, 0.0006)

r1_complex = r1*np.exp(1j*theta)
r1_x, r1_y = np.real(r1_complex), np.imag(r1_complex)
stacked1 = np.stack((r1_x, r1_y), axis=1)  # A list of coordinates

r2_complex = r2*np.exp(1j*theta)
r2_x, r2_y = np.real(r2_complex) + a, np.imag(r2_complex) + b
stacked2 = np.stack((r2_x, r2_y), axis=1)  # A list of coordinates

p = path.Path(stacked2)
r1_inside = p.contains_points(stacked1)

fig, ax = plt.subplots()

ax.plot(r1_x, r1_y)
ax.plot(r2_x, r2_y)
ax.plot(r1_x[r1_inside], r1_y[r1_inside])

ax.set_aspect('equal')
ax.grid()
plt.show()

这会在不了解形状的数学属性的情况下生成相同的图像。