找到两条线之间的最大半径圆

问题描述 投票:0回答:1

我有两个正弦波,如下图所示。有时它们是相同的波,只是沿 y 轴移动。其他时候,正弦波具有不同的周期/幅度等。

我需要找到可以沿着线任何地方放置在两条线之间的最大半径圆(由我生成线的分辨率离散化)。

最好的方法是什么?有没有比迭代创建一个与底部曲线相切的圆并逐步增加半径直到与上部曲线在每个点相交更快的方法?

python numpy matplotlib geometry
1个回答
0
投票

我不确定这是否是完整的答案,但它可能包含一些有用的想法。

最后一个方程可能有多个解,但实际上

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
    不能保证收敛,即使收敛,也不能保证收敛到最小半径的圆(除非可以证明其他情况......)。
  • 该解决方案没有考虑圆在接触上曲线之前与下曲线上的第二个点相交的可能性。我无法从问题陈述中判断是否需要这样做,因为问题提到“增大半径直到与上曲线相交”。不过,由于正弦曲线凸部的对称性,这很容易检查。
© www.soinside.com 2019 - 2024. All rights reserved.