我有两个正弦波,如下图所示。有时它们是相同的波,只是沿 y 轴移动。其他时候,正弦波具有不同的周期/幅度等。
我需要找到可以沿着线任何地方放置在两条线之间的最大半径圆(由我生成线的分辨率离散化)。
最好的方法是什么?有没有比迭代创建一个与底部曲线相切的圆并逐步增加半径直到与上部曲线在每个点相交更快的方法?
我不确定这是否是完整的答案,但它可能包含一些有用的想法。
scipy.optimize.newton
似乎收敛到最小半径的圆。此外,它是矢量化的,因此您可以一次求解多个圆。
import numpy as np
from scipy.optimize import newton
import matplotlib.pyplot as plt
from matplotlib import colors as mcolors
colors = list(mcolors.TABLEAU_COLORS.values())
# amplitude, angular frequency, phase, and y-offsets
params1 = 1, 1, 0, 0
params2 = 0.5, 0.5, 1, 2
# Sinusoid
def y(x, params):
A, w, p, y = params
return A*np.cos(w*x + p) + y
# Derivative of Sinusoid
def dy(x, params):
A, w, p, y = params
return -w*A*np.sin(w*x + p)
# Angle of Sinusoid Surface Normal
def phi(x, params):
return np.arctan2(-1, dy(x, params))
# Radius of circle required given y-coordinates
def ry(y1, y2, phi1, phi2):
return (y2 - y1)/(np.sin(phi1) + np.sin(phi2))
# Radius of circle required given x-coordinates
def rx(x1, x2, phi1, phi2):
return (x2 - x1)/(np.cos(phi1) + np.cos(phi2))
# At the solution, the radius of the circle given y-coordinates
# must agree with the radius of the circle given x-coordinates
def f(x2, x1):
y1, y2 = y(x1, params1), y(x2, params2)
phi1, phi2 = phi(x1, params1), phi(x2, params2)
return rx(x1, x2, phi1, phi2) - ry(y1, y2, phi1, phi2)
# Coordinate of center of circle
def x0y0(x1, r):
y1 = y(x1, params1)
phi1 = phi(x1, params1)
return (x1 + r*np.cos(phi1), y1 + r*np.sin(phi1))
# Plot Sinusoids
t_plot = np.linspace(0, 15, 300)
y1 = y(t_plot, params1)
y2 = y(t_plot, params2)
plt.plot(t_plot, y1, 'k', t_plot, y2, 'k')
ax = plt.gca()
plt.ylim(-2, 4)
plt.axis('equal')
# Coordinates on sinusoid 1
x1 = np.asarray([1, 4.5, 7, 11, 13])
y1 = y(x1, params1)
# X-coordinates on sinusoid 2
x2 = newton(f, x1, args=(x1,))
y2 = y(x2, params2)
# Circle radii and centers
phi1 = phi(x1, params1)
phi2 = phi(x2, params2)
r = rx(x1, x2, phi1, phi2)
x0, y0 = x0y0(x1, r)
for i in range(len(x1)):
color = colors[i]
# Mark points on curve
plt.plot(x1[i], y1[i], color, marker='*')
plt.plot(x2[i], y2[i], color, marker='*')
# Plot circles
circle = plt.Circle((x0[i], y0[i]), r[i], color=color, fill=False)
ax.add_patch(circle)
两大警告:
scipy.optimize.newton
不能保证收敛,即使收敛,也不能保证收敛到最小半径的圆(除非可以证明其他情况......)。