

中秋节到了,送你一个Python做的Crossin牌“月饼”
source link: https://zhuanlan.zhihu.com/p/260768353
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

中秋节到了,送你一个Python做的Crossin牌“月饼”
明天是难得一见的国庆中秋双节合一,在这里除了祝大家节日快乐之外,我们还要送上一个“月饼”——当然这个月饼是不能吃的,因为它是用python做的。先给大家看一下效果图。

画这样一个月饼,其实不需要太多的代码,笔者只用了不到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/snippet/tree/master/mooncake
获取更多教程和案例,
欢迎搜索及关注:Crossin的编程教室
这里还有更多精彩。一起学,走得远!
Recommend
-
55
提出这个公式,其实还不是太细致,不过在和几个朋友讨论之后,也基本上成形了。其实一直以来自己和朋友,当然也有看不认识的人总结自己的经验,但总感觉在分类上有很多模糊的地方。所以,在不断的调整思考和整理思路的过程中,就形成了这个“产品经理水平”这个概念...
-
6
中秋节大家在吃啥?拼多多月饼、螃蟹最热销 - 精选 - 商界网 | 商界APP-专注于商人-企业以及商业思维中秋节大家在吃啥?拼多多月饼、螃蟹最热销 商界新媒体...
-
5
中秋节到了 来一组月饼NFT怎么样? 胡飞瞳 4 小时前 3.6万 对NFT感兴趣的朋友们,看看下面这些月饼你喜欢哪一个?限量发行,给我地址,发送给你。按照...
-
7
零卡月饼也能赚钱? 「中秋节月饼活动」推出无上限加密货币奖励以往的中秋节您可能是吃着月饼,和家人一起吃团圆饭,晚上一起赏月。今年,我们为了庆祝中秋节,很高兴地推出 Cake DeFi 推出的「中秋节月饼活动」。这次您可以利用 Cake DeFi 的零...
-
7
送你一个Python 数据排序的好方法摘要:学习 Pandas排序方法是开始或练习使用 Python进行基本数据分析的好方法。最常见的数据分析是使用电子表格、SQL或pand...
-
3
中秋节,美心月饼携手张智霖上演“满月”的牵挂 作者: Emily ...
-
4
一个程序员的中秋节碎碎念
-
7
5分钟用python写一个抢月饼游戏,中秋快乐 ...
-
6
中秋节过后,超市卖不完的月饼一夜消失,都去哪里了? 每经编辑 卢祥勇 盖源源 中秋节前,一进...
-
8
电视剧里的代码真能运行吗? 大家好,欢迎来到 Cr...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK