文章目录
- 1、Style1
- 2、Style2
- 3、Style3
- 4、Style4
- 5、Style5
- 6、Style6
- 7、Style7
- 8、参考的库函数
- matplotlib.patches.Arc
- matplotlib.patches.Wedge
- 9、参考
1、Style1
"""
author: tyran
"""from numpy import sin, cos, pi
import matplotlib.pyplot as pltfrom matplotlib.patches import Arc, Circle, Wedge
from matplotlib.font_manager import FontPropertieslength = 20
R = 3**0.5*length/(3**0.5*cos(pi/12)-sin(pi/12))
r = 2*sin(pi/12)*R/3**0.5arc1 = Arc([0, length], width=2*r, height=2*r,angle=0, theta1=30, theta2=150, ec='orange', linewidth=4) ##ec为线条颜色,可以自由替换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)circle = Circle((0,0), R, ec='orange', fc='white', linewidth=4) ##ec为线条颜色,fc为填充颜色,可以自由替换wedge1 = Wedge([-2, 2], R-5, 90, 180, ec='orange',fc=r'white', linewidth=4) ##ec为线条颜色,fc为填充颜色,可以自由替换
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)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])# 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.axis('off')
font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12) ##可以自由下载字体使用
plt.text(-15.5, -2.5, '中秋快乐', bbox=dict(boxstyle='square', fc="w", ec='orange', linewidth=4),fontproperties=font_set,fontsize=50,color='orange') ##ec为线条颜色,color为字体颜色,可以自由替换
plt.text(-25, -33, '但愿人长久,千里共婵娟', fontproperties=font_set, fontsize=30, color='#aa4a30')
plt.ylim([-35, 35])
plt.xlim([-35, 35])plt.show()
最外环 12 个弧形对应 arc1
到 arc12
紧接着一个大圆对应着 circle
接下来是 8 个 90° 的扇形对应 wedge1
至 wedge8
字体通过 plt.text
配置实现
2、Style2
借助内旋轮线绘制月饼,先看看具体原理
内旋轮线(hypotrochoid)是追踪附着在围绕半径为 R
的固定的圆内侧滚转的半径为 r
的圆上的一个点得到的转迹线,这个点到内部滚动的圆的中心的距离是 d
。
数学表达式
import numpy as np
from numpy import sin, cos
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontPropertiesx = lambda d,r,R,theta: (R-r)*np.cos(theta) + d*np.cos(((R-r)/r)*theta)
y = lambda d,r,R,theta: (R-r)*np.sin(theta) - d*np.sin(((R-r)/r)*theta)
# 转数-内圆旋转次数
revs = 300
# 迭代次数, 即沿绘制路径获取的点。
Niter = 100
thetas = np.linspace(0, revs*2*np.pi, num=Niter)d = 20 # 距离
r = 11 # 小圆半径
R = 12 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange', linewidth = '4')length = 2.6
# 画个圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')
length = 18
# 画个大圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')
plt.axis('equal')
plt.axis('off')font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12)
plt.text(-5, -5, '中秋\n快乐', bbox=dict(boxstyle='circle', fc="w", ec='orange', linewidth=4),fontproperties=font_set, fontsize=40, color='orange') ##ec为线条颜色,color为字体颜色,可以自由替换
plt.text(-15, -25, '但愿人长久,千里共婵娟', fontproperties=font_set, fontsize=20, color='#aa4a30')plt.show()
画了两个圆,写了字体,剩下的就是内旋轮线的轨迹了
转数-内圆旋转次数 revs = 300
迭代次数, 即沿绘制路径获取的点。Niter = 100
3、Style3
借助内旋轮线绘制月饼
import numpy as np
from numpy import sin, cos
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontPropertiesx = lambda d,r,R,theta: (R-r)*np.cos(theta) + d*np.cos(((R-r)/r)*theta)
y = lambda d,r,R,theta: (R-r)*np.sin(theta) - d*np.sin(((R-r)/r)*theta)
# 转数-内圆旋转次数
revs = 30
# 迭代次数, 即沿绘制路径获取的点。
Niter = 9999
thetas = np.linspace(0,revs*2*np.pi,num=Niter)d = 10 # 距离
r = 46 # 小圆半径
R = 50 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas))d = 20 # 距离
r = 11 # 小圆半径
R = 12 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange', linewidth = '4')length = 2.6
# 画个圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')
length = 18
# 画个大圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='#FF6347', linewidth = '5')
plt.axis('equal')
plt.axis('off')font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12)
plt.text(-6, -6, '中秋\n快乐', bbox=dict(boxstyle='circle', fc="w", ec='orange', linewidth=4), fontproperties=font_set,fontsize=40, color='orange') ##ec为线条颜色,color为字体颜色,可以自由替换
plt.text(-20, -25, '但愿人长久,千里共婵娟', fontproperties=font_set, fontsize=20, color='#aa4a30')plt.show()
第一个 plot 绘制弹簧形状的蓝色的轨迹
第二个 plot 绘制最外圈弧度状的橙色轨迹
第三个 plot 绘制橙色的内圈小圆
第四个 plot 绘制红色的外圈大圆
配上文字,色彩还是比较悦目的
4、Style4
借助内旋轮线绘制月饼
import numpy as np
from numpy import sin, cos
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontPropertiesx = lambda d,r,R,theta: (R-r)*np.cos(theta) + d*np.cos(((R-r)/r)*theta)
y = lambda d,r,R,theta: (R-r)*np.sin(theta) - d*np.sin(((R-r)/r)*theta)
# 转数-内圆旋转次数
revs = 300
# 迭代次数, 即沿绘制路径获取的点。
Niter = 999
thetas = np.linspace(0,revs*2*np.pi,num=Niter)d = 10 # 距离
r = 46 # 小圆半径
R = 50 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas))d = 20 # 距离
r = 11 # 小圆半径
R = 12 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange', linewidth = '4')d = 20 # 距离
r = 11 # 小圆半径
R = 14 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange', linewidth = '4')length = 2.6
# 画个圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')
length = 18.5
# 画个大圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')
plt.axis('equal')length = 14
# 画个小圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')
plt.axis('equal')
plt.axis('off')font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12)
plt.text(-6, -5, '中秋\n快乐', bbox=dict(boxstyle='circle', fc="w", ec='orange', linewidth=4), fontproperties=font_set, fontsize=40, color='orange') ##ec为线条颜色,color为字体颜色,可以自由替换
plt.text(-20, -25, '但愿人长久,千里共婵娟', fontproperties=font_set, fontsize=20, color='#aa4a30')plt.show()
第一个 plot 中间蓝色的形状
第二个 plot 外圈黄色形状
第三个 plot 外圈黄色形状
叠加在一起
绘制三个圆,搭配文字就是最终的效果
5、Style5
借助内旋轮线绘制月饼
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontPropertiesx = lambda d,r,R,theta: (R-r)*np.cos(theta) + d*np.cos(((R-r)/r)*theta)
y = lambda d,r,R,theta: (R-r)*np.sin(theta) - d*np.sin(((R-r)/r)*theta)
# 转数-内圆旋转次数
revs = 800
# 迭代次数, 即沿绘制路径获取的点。
Niter = 99999
thetas = np.linspace(0,revs*2*np.pi,num=Niter)
d = 20
r = 23
R = 60
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange', linewidth = '4')
plt.axis('equal')
plt.axis('off')
font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12)
plt.text(-16, -15, '中秋\n快乐', bbox=dict(boxstyle='circle', fc="w", ec='orange', linewidth=4), fontproperties=font_set, fontsize=40, color='orange') ##ec为线条颜色,color为字体颜色,可以自由替换
plt.text(-2, -70, 'Python做月饼,千里共禅娟', fontproperties=font_set, fontsize=20, color='#aa4a30')
plt.show()
暴力美学,写字的时候,底板用的是白色的圆圈,通过 boxstyle
控制
6、Style6
借助内旋轮线绘制月饼
import numpy as np
from numpy import sin, cos
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontPropertiesx = lambda d,r,R,theta: (R-r)*np.cos(theta) + d*np.cos(((R-r)/r)*theta)
y = lambda d,r,R,theta: (R-r)*np.sin(theta) - d*np.sin(((R-r)/r)*theta)
# 转数-内圆旋转次数
revs = 88
# 迭代次数, 即沿绘制路径获取的点。
Niter = 200
thetas = np.linspace(0,revs*2*np.pi,num=Niter)
d = 2 # 距离
r = 6 # 小圆半径
R = 3 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange', linewidth = '4')font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12)
plt.axis('off')plt.show()
椭圆的也不在话下
7、Style7
借助内旋轮线绘制月饼
import numpy as np
from numpy import sin, cos
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontPropertiesx = lambda d,r,R,theta: (R-r)*np.cos(theta) + d*np.cos(((R-r)/r)*theta)
y = lambda d,r,R,theta: (R-r)*np.sin(theta) - d*np.sin(((R-r)/r)*theta)
# 转数-内圆旋转次数
revs = 888
# 迭代次数, 即沿绘制路径获取的点。
Niter = 2024
thetas = np.linspace(0,revs*2*np.pi,num=Niter)d = 8 # 距离
r = 36 # 小圆半径
R = 35 # 大圆半径
plt.plot(x(d, r, R, thetas), y(d, r, R, thetas), color='orange')length = 7
# 画个圆
theta = np.linspace(0, 2 * np.pi, 100)
x = length * cos(theta)
y = length * sin(theta)
plt.plot(x, y, color='orange', linewidth = '5')font_set = FontProperties(fname=r"Alibaba-PuHuiTi-Medium.ttf", size=12)
plt.text(-1.5, -1, '中秋', bbox=dict(boxstyle='circle', fc="w", ec='orange', linewidth=4),fontproperties=font_set, fontsize=40, color='orange') ##ec为线条颜色,color为字体颜色,可以自由替换
plt.axis('off')plt.show()
神奇,真的是什么形状都可以驾驭
8、参考的库函数
matplotlib.patches.Arc
matplotlib.patches.Arc
是 Matplotlib 库中用于绘制圆弧的类。这个类允许你在指定的中心位置、半径、起始角度和终止角度上绘制一个圆弧。这对于需要可视化圆形或环形结构的数据或设计图表时非常有用。
当你创建一个 Arc 对象时,你需要提供以下参数:
- xy:浮点数元组 (float, float),表示椭圆(及圆弧)的中心点坐标 (x, y)。
- width:浮点数,表示椭圆水平轴的长度,也即圆弧所在椭圆的宽度。
- height:浮点数,表示椭圆垂直轴的长度,也即圆弧所在椭圆的高度。
- angle:浮点数,默认值为 0.0,表示椭圆的旋转角度(逆时针方向)。
- theta1:浮点数,默认值为 0.0,表示圆弧的起始角度(以度为单位)。这个值相对于 angle 参数,例如,如果 angle=45 和 theta1=90,则绝对起始角度为 135。
- theta2:浮点数,默认值为 360.0,表示圆弧的结束角度(以度为单位)。这个值也相对于 angle 参数。大于等于 360 的角度,或小于 0 的角度,将通过在范围 [0, 360) 内取输入值模 360 来表示。
- **kwargs:其他关键字参数,用于设置圆弧的样式属性。大多数补丁属性都支持关键字参数,除了 fill 和 facecolor,因为圆弧不能被填充。
以下是一些常见的属性,用于进一步自定义圆弧的外观:
- agg_filter:过滤函数,接受一个 (m, n, 3) 的浮点数组和一个 dpi 值,并返回一个 (m, n, 3) 的数组。
- alpha:标量,表示圆弧的透明度。
- animated:布尔值,表示是否使用动画渲染。
- antialiased 或 aa:布尔值,表示是否应用抗锯齿效果。
- capstyle:{‘butt’, ‘projecting’, ‘round’},表示圆弧端点的样式。
- clip_box:Bbox,表示用于裁剪圆弧的边界框。
- clip_on:布尔值,表示是否应用裁剪。
- clip_path:Patch 或 (Path, Transform),表示用于裁剪圆弧的路径。
color:颜色,表示圆弧的颜色。 - edgecolor 或 ec:颜色,表示圆弧边缘的颜色。
- figure:Figure,表示圆弧所在的图形对象。
- gid:字符串,表示圆弧的标识符。
- hatch:{‘/’, ‘’, ‘|’, ‘-’, ‘+’, ‘x’, ‘o’, ‘O’, ‘.’, ‘*’},表示圆弧的填充图案(但注意圆弧不能被填充,此属性主要用于其他可填充对象)。
- in_layout:布尔值,表示圆弧是否包含在布局中。
- joinstyle:{‘miter’, ‘round’, ‘bevel’},表示圆弧段之间连接处的样式。
- label:对象,表示圆弧的标签。
- linestyle 或 ls:{‘-’, ‘–’, ‘-.’, ‘:’, ‘’} 或其他自定义样式,表示圆弧的线型。
- linewidth 或 lw:浮点数,表示圆弧的线宽。
- mouseover:布尔值,表示当鼠标悬停在圆弧上时是否触发事件。
- path_effects:AbstractPathEffect 的列表,表示应用于圆弧的路径效果。
- picker:无或布尔值或浮点数或可调用对象,表示用于选择圆弧的拾取器。
- rasterized:布尔值,表示是否将圆弧栅格化为图像。
- sketch_params:(scale: float, length: float, randomness: float),表示用于绘制草图效果的参数。
- snap:布尔值或无,表示是否将圆弧的坐标值对齐到像素网格。
- transform:Transform,表示应用于圆弧的变换。
- url:字符串,表示与圆弧关联的 URL。
- visible:布尔值,表示圆弧是否可见。
- zorder:浮点数,表示圆弧的堆叠顺序。
请注意,上述属性中的一些可能不适用于 Arc 类,因为某些属性是为其他可填充或可变形对象设计的。对于 Arc 类,最常用的属性包括 color、edgecolor、linewidth、linestyle 和 alpha 等。
matplotlib.patches.Wedge
matplotlib.patches.Wedge
是 Matplotlib 库中的一个类,用于绘制楔形(或扇形)图形。以下是这个类的中文文档,详细解释了其构造函数参数和其他相关属性。
Wedge(center, r, theta1, theta2, width=None, **kwargs)
- center:浮点数元组 (float, float),表示楔形的中心点坐标 (x, y)。
- r:浮点数,表示楔形的半径。
- theta1:浮点数,表示楔形起始角度(以度为单位),相对于 x 轴正方向逆时针测量。
- theta2:浮点数,表示楔形终止角度(以度为单位),相对于 x 轴正方向逆时针测量。
- width:可选浮点数,默认值为 None。如果给出宽度,则会绘制一个从内半径 r - width 到外半径 r 的部分楔形。
- **kwargs:其他关键字参数,用于设置楔形的样式属性。这些属性大多数与 Patch 类相同。
以下是一些常见的属性,用于进一步自定义楔形的外观:
- agg_filter:过滤函数,接受一个 (m, n, 3) 的浮点数组和一个 dpi 值,并返回一个 (m, n, 3) 的数组。
- alpha:浮点数,表示楔形的透明度。
- animated:布尔值,表示是否使用动画渲染。
- antialiased 或 aa:布尔值或 None,表示是否应用抗锯齿效果。
- capstyle:{‘butt’, ‘round’, ‘projecting’},表示楔形端点的样式。
- clip_box:Bbox 实例,表示用于裁剪楔形的边界框。
- clip_on:布尔值,表示是否应用裁剪。
- clip_path:(path, transform)、patch 或 None,表示用于裁剪楔形的路径。
- color:颜色规范,表示楔形的颜色。
- edgecolor 或 ec:颜色规范,表示楔形边缘的颜色。如果为 ‘auto’,则颜色与 facecolor 相同。
- facecolor 或 fc:颜色规范,表示楔形的填充颜色。如果为 ‘none’,则楔形不被填充。
- figure:Figure 实例,表示楔形所在的图形对象。
- fill:布尔值,表示是否填充楔形。对于 Wedge 类,这个属性通常不起作用,因为楔形总是根据 facecolor 属性决定是否填充。
- gid:字符串,表示楔形的标识符。
- hatch:{‘/’, ‘’, ‘|’, ‘-’, ‘+’, ‘x’, ‘o’, ‘O’, ‘.’, ‘*’},表示楔形的填充图案(但注意,由于 Wedge 类总是根据 facecolor 填充,此属性通常不起作用)。
- joinstyle:{‘miter’, ‘round’, ‘bevel’},表示楔形段之间连接处的样式。
- label:对象,表示楔形的标签。
- linestyle 或 ls:{‘solid’, ‘dashed’, ‘dashdot’, ‘dotted’} 或其他自定义样式,表示楔形边缘的线型。但请注意,Wedge 类通常不绘制边缘线,除非通过其他方式(如设置 edgecolor)指定。
- linewidth 或 lw:浮点数,表示楔形边缘的线宽。但请注意,Wedge 类通常不绘制边缘线。
- path_effects:AbstractPathEffect 的列表,表示应用于楔形的路径效果。
- picker:无、布尔值、浮点数或可调用对象,表示用于选择楔形的拾取器。
- rasterized:布尔值,表示是否将楔形栅格化为图像。
- sketch_params:(scale: float, length: float, randomness: float),表示用于绘制草图效果的参数。
- snap:布尔值或无,表示是否将楔形的坐标值对齐到像素网格。
- transform:Transform,表示应用于楔形的变换。
- url:字符串,表示与楔形关联的 URL。
- visible:布尔值,表示楔形是否可见。
- zorder:浮点数,表示楔形的堆叠顺序。
9、参考
- 用 Python 画个月饼 祝各位中秋快乐!
- https://github.com/spaceack/matplotlib-draw-mooncake
- Python利用matplotlib万花尺画月饼