import numpy as np
import matplotlib.pyplot as plt

#阿基米德螺线函数,ax为axes对象
def Arch_spiral(ax):
    #生成极角和极径值,theta为极角,r为极径
    theta=np.arrange(0,6*np.pi,np.pi/180)#生成(0,6n)之间,间隔为n/180的序列数
    r=2*theta
    #绘制螺旋线
    ax.plot(theta,r,'b',alpha=0.8)
    #设置网格线,线形为短画线
    ax.grid(linestyle='--')
    #设置极径标签位置,-22.5为角度,负数代表顺时针
    ax.set_rlabel_position(-22.5)
    #设置极径网格线显示范围
    ax.set_rticks([5,15,25,35])
    #绘制标题
    ax.set_title('阿基米德螺旋线',pad=15.0)
    #绘制文本
    ax.text(240*np.pi/180,50,r'$r=2\theta$')

#斐波那契数列计算函数
def Fibo(n):
    if n==0:
        F=1
    elif n==1:
        F=1
    else:
        F=Fibo(n-1)+Fibo(n-2)

    return F

#斐波那契螺旋线函数,ax为axes对象
def Fibo_spiral(ax):
    #计算斐波那契数列
    l_Fibo=[]
    n=0
    for i in range(n+1):
        l_Fibo.append(Fibo(i))
    center=[(0,0),(1,0),(1,-1),(-1,-1),(-1,2),(4,2),(4,-6)]#圆心坐标
    #绘制斐波那契数为边的正方形
    for i in range(n-1):
        x=center[i][0]
        y=center[i][1]
        L=l_Fibo[i+1]
        #确定正方形顶点坐标
        mod=(i+1)%4
        if mod==1:
            x1=x-L
            y1=y-L
        elif mod==2:
            x1=x-L
            y1=y+L
        elif mod==3:
            x1=x+L
            y1=y+L
        elif mod==0:
            x1=x+L
            y1=y-L
        rect=[(x,y),(x1,y),(x1,y1),(x,y1),(x,y)]
        #绘制正方形
        x=[p[0] for p in rect]
        y=[p[1] for p in rect]
        ax.plot(x,y,'k',lw=1)
    #绘制螺旋线
    start_angle=-180#弧线初始角度
    for i in range(n-1):
        end_angle=start_angle+90#弧线的终止角度
        theta=np.linspace(start_angle,end_angle,10)#生成两个角度之间的10个序列数
        r=l_Fibo[i+1]#弧线的圆半径
        #弧线上点x轴坐标=a+r*cos@,a为圆心的x坐标
        X=center[i][0]+r*np.cos(theta*np.pi/180)
        #弧线上点y轴坐标=b+r*sin@,b为圆心的y坐标
        Y=center[i][1]+r*np.sin(theta*np.pi/180)
        ax.plot(X,Y)#绘制弧线
        start_angle=end_angle+180#修改弧线的初始角度,绘制下一段弧线

    #设置x轴,y轴的单位角度长度相等
    ax.axis('equal')
    #设置网格线,线型为短画线
    ax.grid(linestyle='--')
    #绘制标题
    ax.set_title('斐波那契螺旋线')
    #绘制文本
    ax.text(-25,13,'斐波那契数列:',fontsize=8)
    ax.text(-24,10,r'$F_0=1$',fontsize=8)
    ax.text(-24,7,r'$F_1=1$',fontsize=8)
    ax.text(-24,4,r'$F_n=F_{n-1}+F_{n-2}$',fontsize=8)

#蝴蝶曲线函数
def Butterfly(ax):
    #生成绘图数据
    t=np.arange(0.0,12*np.pi,0.01)#生成(0,12n)之间,间隔为0.01的序列数
    x=np.sin(t)*(np.e**np.cos(t)-2*np.cos(4*t)-np.sin(t/12)**5)
    y=np.cos(t)*(np.e**np.cos(t)-2*np.cos(4*t)-np.sin(t/12)**5)

    #以散点图方式绘制曲线
    ax.scatter(x,y,c=y,s=3,cmap='cool')
    #设置网格线,线型为短画线
    ax.grid(linestyle='--')
    #设置x轴范围
    ax.set_xlim(-3.5,3.5)
    #设置y轴范围
    ax.set_ylim(-3.5,3.5)
    #绘制标题
    ax.set_title('蝴蝶曲线')
    #绘制文本
    ax.text(-2.5,-2.5,r'$x=sin(t)(e^{cos(t)}-2cos(4t)-sin(t/12)^5)$',fontsize=6)
    ax.text(-2.5,-3,r'$y=cos(t)(e^{cos(t)}-2cos(4t)-sin(t/12)^5)$',fontsize=6)

#开始主程序
if __name__=='__main__':
    #配置默认参数,支持中文显示,字体为‘楷体’
    plt.rcParams['font.sans-serif']=['KariTi']
    plt.rcParams['axes.unicode_minus']=False#正常显示负号
    #绘制阿基米德螺旋线
    ax1=plt.subplot(221,polar=True)#生成子图对象,2行2列的第1个,为极坐标系
    Arch_spiral(ax1)
    #绘制蝴蝶曲线
    ax2=plt.subplot(222)#生成子图对象,2行2列的第2个
    Butterfly(ax2)
    #绘制斐波那契螺旋线
    ax3=plt.subplot(212)#生成子图对象,2行1列的第2列
    Fibo_spiral(ax3)
    #保存图像到文件
    plt.savefig('E:\\1.png',dpi=300)
    plt.show()