用 Python 绘制一个 Facebook 元宇宙新 Logo

机器学习与数学

共 2571字,需浏览 6分钟

 ·

2021-11-10 01:00

Facebook 为了投身元宇宙,连名字都改了 Meta,也更换了 LOGO。

但这个 LOGO 似乎不是艺术家凭感觉设计的,而是有来头的,在数学上称为 Lissajous 曲线。

平面上的 Lissajous 曲线可以看成是沿着相互垂直方向的两个正弦振动的合成,具体是由以下参数方程描述的一系列曲线:

Lissajous 曲线在物理学、天文学和其他科学中都有应用。下面是一些 Lissajous 曲线示例,你可以通过更改 Python 代码中常量 A 和 B 的值,塑造出更多的具体曲线。

下面就让我们用 Python 来试着绘制一下这个 LOGO。

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.style.use('Solarize_Light2')
import seaborn as sns
sns.set_style("white")

所谓参数曲线,就是要根据参数来确定曲线上的每一个点。也就是说在绘制时,我们需要根据参数来取不同点的 坐标。

  • 设置常量参数 以及 ,控制曲线整体的形状。
A, B = 11
delta = 3.14159/2
  • 设置曲线上采样点的参数向量 。我们先取 50 个点,便于观察点在曲线上的分布。
t = np.linspace(02*np.pi, 50)

fig = plt.figure(figsize=(8,4.5))
a = 1 
b = 2
x = A * np.sin(a*t + delta) 
y = B * np.sin(b*t) 
plt.plot(x, y, '-o');

这画出来了一个无穷大 。大家不妨对照上图中的点,再根据参数 t 的取值,计算一下是从哪一点开始一点一点绘制的。

我们不妨将上述内容写在一起,定义一个简单的函数,方便后面调用。

def drawLissajous2D(r=10,n=500,A=1,B=1,a=1,b=1,delta=1.75,lw=2):
    
    t = np.linspace(0, r, n)
    
    fig = plt.figure(figsize=(8,4.5))
    x = A * np.sin(a*t + delta) 
    y = B * np.sin(b*t) 
    plt.plot(x, y, '-',linewidth=lw)

为了更方便观察曲线上绘制的点列,我们将参数 的范围缩小。

t = np.linspace(0, np.pi, 50)

fig = plt.figure(figsize=(8,4.5))
a = 1 
b = 2
x = A * np.sin(a*t + delta) 
y = B * np.sin(b*t) 
plt.plot(x, y, '-o');

上面只看到了无穷大的一半,因为只画了半个周期。把这些点想象成动点,将其两个坐标分开考虑, 坐标在水平方向来回变动,而 坐标在竖直方向来回变动。可以将 Lissajous 曲线看成是沿着互相垂直方向的两个正弦振动的合成。

  • 取 500 个点,调整下 的值,再次绘制曲线。曲线的样子是不是改变了,上下并不对称了。
drawLissajous2D(n=500,a=1,b=2)
  • 调整常量参数以及线条的宽度
drawLissajous2D(n=500,a=1,b=2,lw=12)
  • 看看其他参数画出来的是个啥?
drawLissajous2D(n=300,a=1,b=1,delta=3.14159/2,lw=6)
drawLissajous2D(n=300,a=3,b=9,lw=6)

13D 版本

还可以二维版本的 Lissajous 曲线扩展到三维空间中,得到三维版本的空间 Lissajous 曲线。只要增加一个 坐标,具体形式可以是下面这样子,

from mpl_toolkits import mplot3d
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc('xtick', labelsize=8)
matplotlib.rc('ytick', labelsize=8)
def drawLissajous3D(r=2*np.pi,n=500,A=1,B=1,C=1,a=1,b=1,c=2,delta=1.75,epsilon=1.75):

    # 设置 Lissajous 参数。
    t = np.linspace(0, r, n)

    x = A * np.sin(a*t) 
    y = B * np.sin(b*t + delta) 
    z = C * np.sin(c*t + epsilon) 

    plt.figure(figsize=(8,6))
    ax = plt.axes(projection='3d')

    ax.plot3D(x, y, z, '-', linewidth=6)
    ax.set_xlabel('$x = A sin(at)$', fontsize=12)
    ax.set_ylabel('$y = B sin(bt + \delta)$', fontsize=12)
    ax.set_zlabel('$z = C sin(ct + \epsilon)$', fontsize=12)
    plt.title("Lissajous 3D Curve", fontsize=12)
    ax.view_init(260)
drawLissajous3D()

可以在窗口中用鼠标交互,比如转动看看,

如果有兴趣,可以将上述绘制改成旋转动画,让这个 LOGO 在三维空间中动起来哦。


浏览 113
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报