1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 用python绘制斐波那契螺旋线

用python绘制斐波那契螺旋线

时间:2023-10-21 17:14:54

相关推荐

用python绘制斐波那契螺旋线

用python绘制斐波那契螺旋线

cd

啥是斐波那契数列

斐波那契数列(Fibonacci sequence),名字版本有很多,黄金分割数列、兔子数列…但指的是都是这样一个数列:

0 、 1 、 1 、 2 、 3 、 5 、 8 、 13 、 21 、 34 、 … … 0、1、1、2、3、5、8、13、21、34、…… 0、1、1、2、3、5、8、13、21、34、……

在数学上,斐波纳契数列以如下被以递推的方法定义:(从1开始)

a ( 1 ) = 1 , a ( 2 ) = 1 , a(1)=1,a(2)=1, a(1)=1,a(2)=1,

a ( n ) = a ( n − 1 ) + a ( n − 2 ) ( n > = 3 , n ∈ N ∗ ) a(n)=a(n-1)+a(n-2) (n>=3,n∈N*) a(n)=a(n−1)+a(n−2)(n>=3,n∈N∗)

通项公式为:

a n = 1 5 × [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] a_n = \frac{1}{\sqrt{5}}\times[(\frac{1+\sqrt{5}}{2})^n-(\frac{1-\sqrt{5}}{2})^n] an​=5 ​1​×[(21+5 ​​)n−(21−5 ​​)n]

斐波那契数列中的斐波那契数会经常出现在我们的眼前,比如松果、凤梨、树叶的排列、某些花朵的花瓣数,以及在植物的叶、枝、茎等排列中发现。也因为种种自然界中的“巧合”,菲波那切数列构成的斐波那契额螺旋线也被称为‘上帝曲线’。(详细介绍可以参见百度,维基,这里就不再吹Fibonacci sequence了)

咋用python绘制斐波那契曲线

cd用的是在常规坐标系下作图的方法绘制Fibonacci曲线,python中的turtle海龟画图方法也行,方法多种多样,大家各自各法欢迎尝试。

这是先在网上找到的样图,那么希望绘制如图所示的Fibonacci曲线,就需要找到其中规律。首先,显而易见,图中的1/4圆的半径是符合菲波那切数列的规律的。那么首先需要产生菲波那切数列。

1.产生菲波那切数列

import numpy as npdef fibo(n):if n == 0:fibo_list = np.array([0])else if n == 1:fibo_list = np.array([0,1])else:f_0, f_1 = 0, 1fibo_list = np.array([f_0,f_1])for i in np.arange(n-2):fibo_num = f_0 + f_1fibo_list = np.append(fibo_list,fibo_num)f_0, f_1 = f_1, fibo_numreturn fibo_list

输入所欲要的数列序数n即可获得一个包含n个数字的array对象。

2.寻找图形中每个1/4圆对应的圆点

同样,如果画出任意圆心需要先找出规律。

罗列前几个圆心坐标如下:

如上表所示,

a) 圆心坐标自第一项起x, y坐标每两项变化一次。(可以通过取余来实现)

b) 对于第n个圆心的横坐标x,每次变化时为前一项加上或者将去第n项的菲波那切数列。同样规律适用于纵坐标y。

c) 加上或者减去第n项序数,规律见表中的flag数列。规律可表示如下:

( − 1 ) 1 + m o d ( n , 2 ) + n 2 (-1)^{1+\frac{mod(n,2)+n}{2}} (−1)1+2mod(n,2)+n​

综上,x坐标与y坐标可分别表示为:

x ( n ) = x ( n − 1 ) + m o d ( n + 1 , 2 ) × F ( n ) × ( − 1 ) 1 + m o d ( n , 2 ) + n 2 x(n)=x(n-1)+mod(n+1,2)\times{F(n)}\times{(-1)^{1+\frac{mod(n,2)+n}{2}}} x(n)=x(n−1)+mod(n+1,2)×F(n)×(−1)1+2mod(n,2)+n​

y ( n ) = y ( n − 1 ) + m o d ( n , 2 ) × F ( n ) × ( − 1 ) 1 + m o d ( n , 2 ) + n 2 y(n)=y(n-1)+mod(n,2)\times{F(n)}\times{(-1)^{1+\frac{mod(n,2)+n}{2}}} y(n)=y(n−1)+mod(n,2)×F(n)×(−1)1+2mod(n,2)+n​

(其中,菲波那切数列以F(n)表示)

import numpy as npdef find_o_xy(f_list):#起始圆心坐标x_n, y_n = 0, 0o_x_array, o_y_array = np.array([x_n]), np.array([y_n])for n in np.arange(1,len(f_list)):#需要注意pyhton中计数是从0开始#第一项作为起始点已经给出y_n=y_n+np.mod(n+1,2)*f_list[n]*(-1)**(1+(np.mod(n+1,2)+n+1)/2)x_n=x_n+np.mod(n,2)*f_list[n]*(-1)**(1+(np.mod(n+1,2)+n+1)/2)#横纵坐标(x,y)o_x_array = np.append(o_x_array, x_n)o_y_array = np.append(o_y_array, y_n)return o_x_array, o_y_array

圆心分布如图:

3.绘制菲波那切数列曲线

已知圆心位置,圆的半径变化符合数列规律。因此,可以绘制曲线。

以n=5为例

#以下绘图以n=7为例count = 7f_list = fibo(count)x0_array,y0_array = find_o_xy(f_list)#各个正方形对应的边长,如例图半径从1,2...开始f_list_r = fibo(count+2)[2::]#画出各个正方形内的1/4圆start_angle, end_angle = np.pi, 1.5*np.pifor n in np.arange(len(f_list)):t=np.arange(start_angle,end_angle,0.001)circle_x = (f_list_r[n])*(np.sin(t))+x0_array[n]circle_y = (f_list_r[n])*(np.cos(t))+y0_array[n]start_angle += 0.5*np.piend_angle += 0.5*np.piplt.plot(circle_x,circle_y,color='b')

得到曲线如图:

4.为仿照例图,画出正方形

确定方形顶点思路是先找到圆心对角的顶点,再写出另外两点。

#现一并画出曲线与方格。count = 7f_list = fibo(count)x0_array,y0_array = find_o_xy(f_list)f_list_r = fibo(count+2)[2::] #各个正方形对应的边长square_list = np.zeros([1,2,5])start_angle, end_angle = np.pi, 1.5*np.pifor n in np.arange(len(f_list_r)):#圆心坐标x0 = x0_array[n]y0 = y0_array[n]#得到对角顶点坐标x2 = x0+f_list_r[n]*(-1)**((np.mod(n+1,2)+n+1)/2)if n == 0:y2 = -1 #起始点特殊目前只想到这么整了else:y2 = y0+f_list_r[n]*(-1)**(1+(np.mod(n,2)+n)/2)#其余两点坐标x1, x3 = x0, x2y1, y3 = y2, y0#整合一下,画正方形需要回到原点,因此5个点pp = np.array([[[x0,x1,x2,x3,x0],[y0,y1,y2,y3,y0]]])#画出圆弧t=np.arange(start_angle,end_angle,0.001)circle_x = (f_list_r[n])*(np.sin(t))+x0_array[n]circle_y = (f_list_r[n])*(np.cos(t))+y0_array[n]start_angle += 0.5*np.piend_angle += 0.5*np.piplt.plot(pp[0][0][::],pp[0][1][::],color = 'b')plt.plot(circle_x,circle_y,color='b')

输出如图:

到目前为止,绘制出菲波那切曲线的任务算是完成了。有兴趣可以调节序数n画出任意曲线。

但是,cd看着这么粗糙的图,不忍罢手,于是就地美化一波。

稍微美化调整一波

美化这事情是个审美方面的事情。cd这里展现的仅仅是在cd本人认为中还可以的图形。

美化过程中对画图参数的查阅与使用,使我收益颇丰,下次再另发一文记录一下画图受益情况。

如图:

代码暂时只放头像图形绘制代码。其他的也就是在这个代码上面稍微改改。变化不大,就不放上来增加推文长度了。

import numpy as npimport pylab as plt# 产生菲波那切数列def fibo(n):f_0 = 0f_1 = 1fibo_list = np.array([f_0,f_1])for i in np.arange(n-2):fibo_num = f_0 + f_1fibo_list = np.append(fibo_list,fibo_num)f_0, f_1 = f_1, fibo_numreturn fibo_list#找出各个圆心def find_o_xy(f_list):import pylab as pltx_n, y_n = 0, 0 #起始圆心坐标o_x_array, o_y_array = np.array([x_n]), np.array([y_n])for n in np.arange(1,len(f_list)):#需要注意pyhton中数组计数是从0开始#第一项作为起始点已经给出y_n=y_n+np.mod(n+1,2)*f_list[n]*(-1)**(1+(np.mod(n+1,2)+n+1)/2)x_n=x_n+np.mod(n,2)*f_list[n]*(-1)**(1+(np.mod(n+1,2)+n+1)/2)o_x_array = np.append(o_x_array, x_n)o_y_array = np.append(o_y_array, y_n)return o_x_array, o_y_arraycount = 5f_list = fibo(count)x0_array,y0_array = find_o_xy(f_list)#------------------------头像4----------------------------f_list_r = fibo(count+2)[2::]start_angle, end_angle = np.pi, 1.5*np.pifig = plt.figure(num=1,facecolor='k',figsize=(10,10))#增加坐标轴对象,显示boxax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=True,aspect=1)x_min, x_max, y_min, y_max = 0, 0, 0, 0for n in np.arange(len(f_list_r)):#圆心坐标x0 = x0_array[n]y0 = y0_array[n]#得到对角顶点坐标x2 = x0+f_list_r[n]*(-1)**((np.mod(n+1,2)+n+1)/2)if n == 0:y2 = -1 #起始点特殊目前只想到这么整了else:y2 = y0+f_list_r[n]*(-1)**(1+(np.mod(n,2)+n)/2)#画出圆弧t=np.arange(start_angle,end_angle,0.001)circle_x = (f_list_r[n])*(np.sin(t))+x0_array[n]circle_y = (f_list_r[n])*(np.cos(t))+y0_array[n]start_angle += 0.5*np.piend_angle += 0.5*np.pi#画图,在坐标轴上画图ax.plot(np.append(x0_array[n],np.append(circle_x,x0_array[n])),np.append(y0_array[n],np.append(circle_y,y0_array[n])),color='k',linewidth=5)ax.fill(np.append(circle_x,x0_array[n]),np.append(circle_y,y0_array[n]),facecolor='gold',alpha = 1)#f5bf03#设置axes内的填充颜色ax.patch.set_facecolor('k')#调节坐标范围x_min,x_max=8.5,-11.5y_min,y_max=10,-10mul_times = 1.5ax.set_xlim(x_min*mul_times, x_max*mul_times)ax.set_ylim(y_min*mul_times, y_max*mul_times)#不显示坐标轴刻度以及刻度线ax.tick_params(axis='both',labelsize=0,length=0)#设置spine,即图形边框ax.spines['top'].set_color('none') #设置颜色ax.spines['bottom'].set_color('none')ax.spines['left'].set_color('none')ax.spines['right'].set_color('none')#设置图片保存为png格式,有背景plt.savefig('sdf.png',format = 'png',transparent=False,dpi=300)

后加上文字后的效果如图(比较满意的三张图):

(欢迎关注微信公众号 ID:cdsreport)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。