Matplotlib 3D 绘制小红花原理

 更新时间:2022年02月16日 11:25:31   作者:夏小悠  
这篇文章主要介绍了Matplotlib 3D 绘制小红花原理,小编上一篇文章一家介绍了绘制小红化,本篇博文主要介绍一下3D小红花的绘制原理,看过上篇博文的朋友可以参考一下

 前言:

上篇博文中使用了matplotlib绘制了3D小红花,本篇博客主要介绍一下3D小红花的绘制原理。

1. 极坐标系

对于极坐标系中的一点 P ,我们可以用极径 r  和极角 θ 来表示,记为点 P ( r , θ ) ,

使用matplotlib绘制极坐标系:

import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    # 极径
    r = np.arange(10)
    # 角度
    theta = 0.5 * np.pi * r

    fig = plt.figure()
    plt.polar(theta, r, c='r', marker='o', ms=3, ls='-', lw=1)
    # plt.savefig('img/polar1.png')
    plt.show()

使用matplotlib绘制极坐标散点图:

import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    r = np.linspace(0, 10, num=10)
    theta = 2 * np.pi * r
    area = 3 * r ** 2

    ax = plt.subplot(111, projection='polar')
    ax.scatter(theta, r, c=theta, s=area, cmap='hsv', alpha=0.75)
    # plt.savefig('img/polar2.png')
    plt.show()

有关matplotlib极坐标的参数更多介绍,可参阅官网手册

2. 极坐标系花瓣

绘制r = s i n ( θ ) r=sin(\theta)r=sin(θ) 在极坐标系下的图像:

import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    fig = plt.figure()
    ax = plt.subplot(111, projection='polar')
    ax.set_rgrids(radii=np.linspace(-1, 1, num=5), labels='')

    theta = np.linspace(0, 2 * np.pi, num=200)
    r = np.sin(theta)
    ax.plot(theta, r)
    # plt.savefig('img/polar3.png')
    plt.show()

以 2 π 为一个周期,增加图像的旋转周期:

r = np.sin(2 * theta)

继续增加图像的旋转周期:

r = np.sin(3 * theta)
r = np.sin(4 * theta)

然后我们可以通过调整极径系数和角度系数来调整图像:

import matplotlib.pyplot as plt
import numpy as np


if __name__ == '__main__':
    fig = plt.figure()
    ax = plt.subplot(111, projection='polar')
    ax.set_rgrids(radii=np.linspace(-1, 1, num=5), labels='')

    theta = np.linspace(0, 2 * np.pi, num=200)
    r1 = np.sin(4 * (theta + np.pi / 8))
    r2 = 0.5 * np.sin(5 * theta)
    r3 = 2 * np.sin(6 * (theta + np.pi / 12))

    ax.plot(theta, r1)
    ax.plot(theta, r2)
    ax.plot(theta, r3)
    # plt.savefig('img/polar4.png')
    plt.show()

3. 三维花瓣

现在可以将花瓣放置在三维空间上了,根据花瓣的生成规律,其花瓣外边缘线在一条旋转内缩的曲线上,这条曲线的极径 r 随着角度的增大逐渐变小,其高度 h  逐渐变大。

其函数图像如下:

这样定义就满足前面对花瓣外边缘曲线的假设了,即 r 递减, h 递增。

现在将其放在三维空间中:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


if __name__ == '__main__':
    fig = plt.figure()
    ax = Axes3D(fig)
    # plt.axis('off')

    x = np.linspace(0, 1, num=30)
    theta = np.linspace(0, 2 * np.pi, num=1200)
    theta = 30 * theta
    x, theta = np.meshgrid(x, theta)

    # f is a decreasing function of theta
    f = 0.5 * np.pi * np.exp(-theta / 50)

    r = x * np.sin(f)
    h = x * np.cos(f)

    # 极坐标转笛卡尔坐标
    X = r * np.cos(theta)
    Y = r * np.sin(theta)
    ax = ax.plot_surface(X, Y, h,
                         rstride=1, cstride=1, cmap=plt.cm.cool)

    # plt.savefig('img/polar5.png')
    plt.show()

笛卡尔坐标系(Cartesian coordinate system),即直角坐标系。

然而,上述的表达仍然没有得到花瓣的细节,因此我们需要在此基础之上进行处理,以得到花瓣形状。因此设计了一个花瓣函数:

其是一个以 2 π 为周期的周期函数,其值域为[ 0.5 , 1.0 ],图像如下图所示:

再次绘制:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


if __name__ == '__main__':
    fig = plt.figure()
    ax = Axes3D(fig)
    # plt.axis('off')

    x = np.linspace(0, 1, num=30)
    theta = np.linspace(0, 2 * np.pi, num=1200)
    theta = 30 * theta
    x, theta = np.meshgrid(x, theta)

    # f is a decreasing function of theta
    f = 0.5 * np.pi * np.exp(-theta / 50)

    # 通过改变函数周期来改变花瓣的形状
    # 改变值域也可以改变花瓣形状
    # u is a periodic function
    u = 1 - (1 - np.absolute(np.sin(3.3 * theta / 2))) / 2
    r = x * u * np.sin(f)
    h = x * u * np.cos(f)
    
    # 极坐标转笛卡尔坐标
    X = r * np.cos(theta)
    Y = r * np.sin(theta)
    ax = ax.plot_surface(X, Y, h,
                         rstride=1, cstride=1, cmap=plt.cm.RdPu_r)

    # plt.savefig('img/polar6.png')
    plt.show()

4. 花瓣微调

  为了使花瓣更加真实,使花瓣的形态向下凹,因此需要对花瓣的形状进行微调,这里添加一个修正项和一个噪声扰动,修正函数图像为:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


if __name__ == '__main__':
    fig = plt.figure()
    ax = Axes3D(fig)
    # plt.axis('off')

    x = np.linspace(0, 1, num=30)
    theta = np.linspace(0, 2 * np.pi, num=1200)
    theta = 30 * theta
    x, theta = np.meshgrid(x, theta)

    # f is a decreasing function of theta
    f = 0.5 * np.pi * np.exp(-theta / 50)

    noise = np.sin(theta) / 30
    # u is a periodic function
    u = 1 - (1 - np.absolute(np.sin(3.3 * theta / 2))) / 2 + noise

    # y is a correction function
    y = 2 * (x ** 2 - x) ** 2 * np.sin(f)
    r = u * (x * np.sin(f) + y * np.cos(f))
    h = u * (x * np.cos(f) - y * np.sin(f))

    X = r * np.cos(theta)
    Y = r * np.sin(theta)
    ax = ax.plot_surface(X, Y, h,
                         rstride=1, cstride=1, cmap=plt.cm.RdPu_r)

    # plt.savefig('img/polar7.png')
    plt.show()

修正前后图像区别对比如下:

5. 结束语

3D花的绘制主要原理是极坐标,通过正弦/余弦函数进行旋转变形构造,参数略微变化就会出现不同的花朵,有趣!

到此这篇关于Matplotlib 3D 绘制小红花原理的文章就介绍到这了,更多相关Matplotlib 绘制小红花内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python脚本,标识符,变量使用,脚本语句,注释,模块引用详解

    Python脚本,标识符,变量使用,脚本语句,注释,模块引用详解

    这篇文章主要为大家详细介绍了Python脚本,标识符,变量使用,脚本语句,注释,模块引用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • Python httpx库入门指南(最新推荐)

    Python httpx库入门指南(最新推荐)

    Httpx 是一个用于发送 HTTP 请求的 Python 库,它提供了简单易用的 API,可以轻松地发送 GET、POST、PUT、DELETE 等请求,并接收响应,下面介绍下Python httpx库入门指南,感兴趣的朋友一起看看吧
    2023-12-12
  • 解决python读取几千万行的大表内存问题

    解决python读取几千万行的大表内存问题

    今天小编就为大家分享一篇解决python读取几千万行的大表内存问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • python中pyenv-win安装与使用教程

    python中pyenv-win安装与使用教程

    pyenv-win是一个在Windows系统上管理Python版本的工具,本文主要介绍了python中pyenv-win安装与使用教程,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • OpenCV NAO机器人辅助捡球丢球流程分析

    OpenCV NAO机器人辅助捡球丢球流程分析

    这篇文章主要介绍了OpenCV NAO机器人辅助捡球丢球,本项目使用NAO机器人识别球并捡起,然后将其扔到指定位置,主要涉及图像的获取、滤波、目标物体定位和NAO机器人的运动控制,需要的朋友可以参考下
    2022-05-05
  • Python中__new__与__init__方法的区别详解

    Python中__new__与__init__方法的区别详解

    这篇文章主要介绍了Python中__new__与__init__方法的区别,是Python学习中的基础知识,需要的朋友可以参考下
    2015-05-05
  • Python Pytorch深度学习之核心小结

    Python Pytorch深度学习之核心小结

    今天小编就为大家分享一篇关于Pytorch核心小结的文章,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-10-10
  • 如何使用python统计字符在文件中出现的次数

    如何使用python统计字符在文件中出现的次数

    在开发过程中很多时候我们有统计单个字符或者字符串在另一个字符串中出现次数的需求,下面这篇文章主要给大家介绍了关于如何使用python统计字符在文件中出现的次数的相关资料,需要的朋友可以参考下
    2023-03-03
  • python中字符串String及其常见操作指南(方法、函数)

    python中字符串String及其常见操作指南(方法、函数)

    String方法是用来处理代码中的字符串的,它几乎能搞定你所遇到的所有字符串格式,下面这篇文章主要给大家介绍了关于python中字符串String及其常见操作(方法、函数)的相关资料,需要的朋友可以参考下
    2022-04-04
  • python numpy中multiply与*及matul 的区别说明

    python numpy中multiply与*及matul 的区别说明

    这篇文章主要介绍了python numpy中multiply与*及matul 的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05

最新评论