使用Python的NumPy和matplotlib画心脏线
数学解释
首先我们看一下心脏线的函数表达:
x
=
c
o
s
(
α
)
x=cos(\alpha)
x=cos(α)
y
=
s
i
n
(
α
)
+
c
o
s
(
α
)
2
/
3
y=sin(\alpha)+cos(\alpha)^{2/3}
y=sin(α)+cos(α)2/3
知道了心脏线的方程,那我们只需要使用一些绘图的技巧就可以很简单的画图
画心脏线
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(6,4))
data=np.linspace(0,2*np.pi,1000)
x = np.cos(data)
y = np.sin(data)+((np.cos(data))**2)**(1/3)
plt.plot(x,y,'r')
plt.show()
输出如下:
np.linspace主要用来创建等差数列,参数如下:
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
Return evenly spaced numbers over a specified interval.
(在start和stop之间返回均匀间隔的数据)
Returns num evenly spaced samples, calculated over the interval [start, stop].
(返回的是 [start, stop]之间的均匀分布)
The endpoint of the interval can optionally be excluded.
Changed in version 1.16.0: Non-scalar start and stop are now supported.
(可以选择是否排除间隔的终点)
参数含义:
> start:返回样本数据开始点
> stop:返回样本数据结束点
> num:生成的样本数据量,默认为50
> endpoint:True则包含stop;False则不包含stop
> retstep:If True, return (samples,step), where step is the spacing between samples.(即如果为True则结果会给出数据间隔)
> dtype:输出数组类型
> axis:0(默认)或-1
三种方法对内部进行填充
#直接填充法
def fill_solution(x,y):
plt.fill_between(x,y,facecolor='red')
#随机投点法
def random_solution():
for i in range(50000):
data_new = np.random.uniform(0,2*np.pi,1)
r = np.random.uniform(0,1,1)
x_new= r*np.cos(data_new)
y_new= r*np.sin(data_new)+((np.cos(data_new))**2)**(1/3)
plt.scatter(x_new,y_new,c='r')
plt.title("Cardioid")
#同心圆法
def Concentric_circles():
theta=np.arange(0,np.pi*2+0.1,0.001)
plt.figure(figsize=(50,30))
for r in np.arange(0,1,0.0005):
x=r*np.cos(theta)
y=r*(np.sin(theta)+(np.cos(theta)**2)**(1/3))
plt.rcParams['lines.linewidth']=r*20
plt.plot(x,y,c="r")
plt.show()
#----------------------------------------------end!
#个人觉得fill_between函数是最优的,而且其多用于组合图形的填充
完整代码:
# -*- coding: utf-8 -*-
'''
@Time : 2021/09/24 20:16:33
@Author : ghz
'''
import matplotlib.pyplot as plt
import numpy as np
#直接填充法
def fill_solution(x,y):
plt.fill_between(x,y,facecolor='red')
#随机投点法
def random_solution():
for i in range(50000):
data_new = np.random.uniform(0,2*np.pi,1)
r = np.random.uniform(0,1,1)
x_new= r*np.cos(data_new)
y_new= r*np.sin(data_new)+((np.cos(data_new))**2)**(1/3)
plt.scatter(x_new,y_new,c='r')
plt.title("Cardioid")
#同心圆法
def Concentric_circles():
theta=np.arange(0,np.pi*2+0.1,0.001)
plt.figure(figsize=(50,30))
for r in np.arange(0,1,0.0005):
x=r*np.cos(theta)
y=r*(np.sin(theta)+(np.cos(theta)**2)**(1/3))
plt.rcParams['lines.linewidth']=r*20
plt.plot(x,y,c="r")
plt.show()
def main():
plt.figure(figsize=(6,4))
data=np.linspace(0,2*np.pi,1000)
x = np.cos(data)
y = np.sin(data)+((np.cos(data))**2)**(1/3)
plt.plot(x,y,'r')
#画心脏线
'''----------------说明-------------------
以下两个函数可以分别调用直接填充法和随机投点法
按照需求注释掉其中一个即可
若只画心脏线,则可以将两个全部注释
'''
#fill_solution(x,y)
#random_solution()
plt.show()
if __name__ == '__main__':
#由于数据源的不同,直接调用Concentric_circles函数进行随机投点
main()
#Concentric_circles()