圆圈滚动问题

今天偶然之间看见了一个问题,如下图所示。
圆圈滚动问题

看了一下解答(Circles rolling on circles)发现自己也没太想清楚,虽然自己找了一个瓶盖试了一下发现事实的确如此,但还是没太懂究竟是什么原因。

一开始想在网上搜一下有没有直观一点的动画好理解问题出错的原因,但简单搜索后没有找到满意的结果。本着求人不如求己的原则,久违地打开了python,编程验证了一下两个圆转动的过程,分析问题编写代码的过程中理解了原因,但果然还是绘制出图像看得更明确一点,在这里记录一下,如果大家遇到同样的问题可以参考。

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

class Circle(object):
    def __init__(self,x,y,r):
        self.x = x
        self.y = y
        self.r = r
    def circleround(self):
        theta = np.linspace(0, 2 * np.pi, 100)  # 从0到2pi,生成100个均匀分布的数(包括0和2pi)
        x_circle = self.x + self.r * np.sin(theta)
        y_circle = self.y + self.r * np.cos(theta)
        return x_circle, y_circle


# 画布设置
fig = plt.figure()
ax = fig.add_subplot(111)
plt.xlim((-10,10))
plt.ylim((-10,10))
#plt.axis('equal')  # 设置坐标轴比例相等
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Motion Trajectory')
# 设置坐标轴的单位刻度
ax.xaxis.set_major_locator(plt.MultipleLocator(1))  # 每个轴标记之间间隔为1
ax.yaxis.set_major_locator(plt.MultipleLocator(1))
# 固定呈现的图中轴单位长度
ax.set_aspect(1)  # 在二维图中设置轴缩放比例,该函数还可以设置轴的角度
'''
    NOTE:三维图中可以使用ax.set_box_aspect([dx, dy, dz])
'''

# 参数设置
R = 5  # 大圆半径
r = 1  # 小圆半径
big = Circle(0,0,R)
plt.plot(0,0,'k.')
small = Circle(0,R+r,r)
plt.plot(0,R+r,'k.')
pot = plt.plot(0,R,'r.')
line1, = plt.plot(big.circleround()[0],big.circleround()[1])
line2, = plt.plot(small.circleround()[0],small.circleround()[1])
# 计算小圆的运动轨迹
# 设alpha是小圆圆心绕大院圆心移动的角度
# 小圆和大圆相切经过的弧度是一致的
# 则小圆上的定点相对于两圆初始切点运动的角度为大圆半径/小圆半径
alpha = np.linspace(0, 2 * np.pi, 1000)
beta = R / r * alpha

def update(frame):
    '''
        更新小圆的位置
        :param num: 当前帧的帧数,一定是整数,从0开始,FuncAnimation传入一个np.arange(0, 100),就是100帧
        :return: # 返回的对象的内容是下一个帧的数据内容。这里是下一帧的点的位置
    '''
    x_small_center = (R + r) * np.sin(alpha[frame])
    y_small_center = (R + r) * np.cos(alpha[frame])
    x_static = x_small_center - r * np.sin(alpha[frame]+beta[frame])
    y_static = y_small_center - r * np.cos(alpha[frame]+beta[frame])
    small = Circle(x_small_center, y_small_center, r)
    xround, yround = small.circleround()
    line2.set_xdata(xround)
    line2.set_ydata(yround)
    plt.plot(x_static, y_static, 'g,')

    # 如果初始切点绕过的角度为2pi,就打一个点
    # 小圆上面的点每一个绕的角度=圆心绕过的角度+该点相较于自己原始的位置绕过的角度
    if np.mod(alpha[frame]+beta[frame],2 * np.pi) < 0.05:
        plt.plot(x_static,y_static,'r.')
    return line2,

ani = animation.FuncAnimation(fig, update, frames=range(1000), interval=0.001 )
#ani.save('CircleRolling.gif',writer='pillow')
plt.show()


最终获得的图片就是这样的啦~

绿色的虚线表示我们选定点转动的轨迹,红色的小点表示小圆已经转完一圈了。这样看起来就很直观了,小圆自转的圈数是大圆与小圆半径之比再加1圈。
circles rolling
后来看到一个更简单的方便理解的方法,我们将里面的圆记为A,把外面的圆记为B。拉直圆A的边,让圆B在直线上滚动,此时B滚动的圈数是两圆半径之比,这很好理解。此时我们考虑一种极端情况,设圆A的半径变得极小,此时圆B环绕其一周仍需要自转1圈。将两种旋转模式加和,就可以知道小圆自转的圈数是大圆与小圆半径之比再加1圈了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值