明天是难得一见的国庆中秋双节合一,在这里除了祝大家节日快乐之外,我们还要送上一个“月饼”——当然这个月饼是不能吃的,因为它是用python做的。先给大家看一下效果图。
图1. 月饼效果图 画这样一个月饼,其实不需要太多的代码,笔者只用了不到50行代码,而且用的是我们经常用到的绘图库matplotlib,这对于我们大部分人来说是很容易上手的,下面笔者就详细介绍一下怎么画这样一个月饼。
首先导入各种需要的库:
import numpy as np
from numpy import sin , cos , pi
import matplotlib.pyplot as plt
import matplotlib.patches as mpatch
from matplotlib.patches import Arc , Circle , Wedge
from matplotlib.collections import PatchCollection 然后设置3个变量,这3个变量的用途到后面会有解释:
length = 20
R = 3 ** 0.5 * length / ( 3 ** 0.5 * cos ( pi / 12 ) - sin ( pi / 12 ))
r = 2 * sin ( pi / 12 ) * R / 3 ** 0.5 接下来我们要画12条弧线,这12条弧线是月饼边缘的花纹:
arc1 = Arc ([ 0 , length ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 30 , theta2 = 150 , ec = 'orange' , linewidth = 4 )
arc2 = Arc ([ - length / 2 , length / 2 * 3 ** 0.5 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 60 , theta2 = 180 , ec = 'orange' , linewidth = 4 )
arc3 = Arc ([ - length / 2 * 3 ** 0.5 , length / 2 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 90 , theta2 = 210 , ec = 'orange' , linewidth = 4 )
arc4 = Arc ([ - length , 0 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 120 , theta2 = 240 , ec = 'orange' , linewidth = 4 )
arc5 = Arc ([ - length / 2 * 3 ** 0.5 , - length / 2 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 150 , theta2 = 270 , ec = 'orange' , linewidth = 4 )
arc6 = Arc ([ - length / 2 , - length / 2 * 3 ** 0.5 ], width = 2 *
r , height = 2 * r , angle = 0 , theta1 = 180 , theta2 = 300 , ec = 'orange' , linewidth = 4 )
arc7 = Arc ([ 0 , - length ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 210 , theta2 = 330 , ec = 'orange' , linewidth = 4 )
arc8 = Arc ([ length / 2 , - length / 2 * 3 ** 0.5 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 240 , theta2 = 360 , ec = 'orange' , linewidth = 4 )
arc9 = Arc ([ length / 2 * 3 ** 0.5 , - length / 2 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 270 , theta2 = 390 , ec = 'orange' , linewidth = 4 )
arc10 = Arc ([ length , 0 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 300 , theta2 = 420 , ec = 'orange' , linewidth = 4 )
arc11 = Arc ([ length / 2 * 3 ** 0.5 , length / 2 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 330 , theta2 = 450 , ec = 'orange' , linewidth = 4 )
arc12 = Arc ([ length / 2 , length / 2 * 3 ** 0.5 ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 0 , theta2 = 120 , ec = 'orange' , linewidth = 4 ) 看到这里估计很多人懵逼了,代码是不是有点多了?实际上这些弧线都是来自于同一个Arc类,它们的用法都是一样的,只不过部分参数不同,所以我们只要掌握一个,其他的全都会了。这里笔者就用arc1来说明一下:
arc1 = Arc ([ 0 , length ], width = 2 * r , height = 2 * r , angle = 0 , theta1 = 30 , theta2 = 150 , ec = 'orange' , linewidth = 4 ) 其中 [0, length] 是这个Arc弧线的圆心,因为这个Arc类是一个椭圆形的一部分,所以其包含圆心、横轴、纵轴等参数,length 变量就是arc1圆心的纵坐标,width=2*r 和 height=2*r 就说明这个椭圆的纵轴和横轴长度相等,其是一个圆,而不是椭圆,变量 r 就是这个圆的半径。angle=0 就是我们不需要对这个圆进行旋转,theta1=30 和 theta2=150 是指明这个弧线的起始角度和终止角度,这里的角度分别是30度 和150度 。而 ec='orange' 和linewidth=4 分别指边线的颜色和线条宽度,颜色我们设为橙色 ,宽度为4 。而这些弧线的效果图如图2所示,在图中笔者标出了arc1、arc5和arc9这3条弧线的位置,所有弧线按照逆时针方向 排列。这些位置大同小异,大家只要计算好其各自的位置参数就行,这里就不再赘述了。
图2. 弧线效果图 然后我们再画一个圆,这个圆是月饼的主体部分,其圆心和整个月饼的中心是重合的,圆心位置我们选在了坐标原点,代码如下:
circle = Circle (( 0 , 0 ), R , ec = 'orange' , fc = 'white' , linewidth = 4 ) 这里变量R就是这个大圆的半径,边线颜色设置为橙色,表面颜色设为白色。其效果如图3所示。
图3. 大圆效果图 接下来我们再画上一些花纹,这些花纹主要由8个扇形组成,其中有4个大的扇形和4个小的扇形,代码如下:
wedge1 = Wedge ([ - 2 , 2 ], R - 5 , 90 , 180 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge2 = Wedge ([ - 5 , 5 ], R - 12 , 90 , 180 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge3 = Wedge ([ - 2 , - 2 ], R - 5 , 180 , 270 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge4 = Wedge ([ - 5 , - 5 ], R - 12 , 180 , 270 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge5 = Wedge ([ 2 , - 2 ], R - 5 , 270 , 360 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge6 = Wedge ([ 5 , - 5 ], R - 12 , 270 , 360 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge7 = Wedge ([ 2 , 2 ], R - 5 , 0 , 90 , ec = 'orange' , fc = r 'white' , linewidth = 4 )
wedge8 = Wedge ([ 5 , 5 ], R - 12 , 0 , 90 , ec = 'orange' , fc = r 'white' , linewidth = 4 ) 这里wedge1、wedge3、wedge5、wedge7是大扇形,wedge2、wedge4、wedge6、wedge8是小扇形,一个大扇形嵌套一个小扇形,其中wedge1嵌套wedge2,wedge3嵌套wedge4,以此类推。Wedge这个类和前面Arc有些类似,不过Wedge是圆的一部分,以wedge1为例:
wedge1 = Wedge ([ - 2 , 2 ], R - 5 , 90 , 180 , ec = 'orange' , fc = r 'white' , linewidth = 4 ) 其中[-2, 2] 是这个Wedge所代表的圆的圆心,R-5 是其半径,90 和180 分别代表起始和终止角度,ec 、fc 和linewidth 这些都和前面Arc类的用法相似,这8个扇形的效果图如图4所示。在图中笔者标出了wedge1、wedge2、wedge5和wedge6的位置,所有扇形按照逆时针方向放置。
图4. 扇形效果图 最后我们再把公众号“CROSSIN ”的名称加上,因为代码不多,所以把剩余所有代码都写在这里:
art_list = [ arc1 , arc2 , arc3 , arc4 , arc5 , arc6 , arc7 , arc8 , arc9 , arc10 , arc11 , arc12 ]
art_list . extend ([ circle , wedge1 , wedge2 , wedge3 , wedge4 , wedge5 , wedge6 , wedge7 , wedge8 ])
fig , ax = plt . subplots ( figsize = ( 8 , 8 ))
ax . set_aspect ( 'equal' )
for a in art_list :
ax . add_patch ( a )
plt . text ( - 18 , - 2.5 , 'CROSSIN' , fontfamily = r 'Times New Man' , bbox = dict ( boxstyle = 'square' , fc = "w" , ec = 'orange' , linewidth = 4 ), fontsize = 50 , color = 'orange' )
plt . ylim ([ - 35 , 35 ])
plt . xlim ([ - 35 , 35 ])
plt . show () art_list是我们设置的一个list变量,里面放有arc1到arc12这12个图形,然后再把circle以及8个扇形都加进去。ax.set_aspect('equal') 是设置整个图形x轴和y轴同比例,for a in art_list: ax.add_patch(a) 是把art_list中所有图形加入到画布当中。而plt.text 这行代码中,-18和-2.5是这个text的左下角的坐标,fontfamily 和 fontsize 分别是文字的字体和大小,bbox 是设置text边框的格式,这些参数也都和前面讲过的很多参数差不多,这里不再赘述。plt.ylim 和plt.xlim 是设置整个画布的坐标范围。最终效果如图1所示。
当然我们也可以改变图片的颜色,比如设置成蓝色的,如图5所示,这个完全可以根据个人爱好而定。
图5. 蓝色月饼图 笔者在这里用了不到50行代码就画出了一个月饼,其中还有不少复用的,所以核心只有几个绘图函数,理解起来并不难。你也可以自己动手试一试,定制一块你自己的月饼。
最后再次祝大家,中秋快乐!国庆快乐!
作者:tyran 完整代码:https:// gitee.com/crossin/snipp et/tree/master/mooncake ----
获取更多教程和案例,
欢迎搜索及关注:Crossin的编程教室
这里还有更多精彩。一起学,走得远!