Python绘制正二十面体图形示例
作者:微小冷 时间:2022-01-10 18:27:08
正二十面体的顶点
正20面体的12个顶点刚好可以分为三组,每一组都是一个符合黄金分割比例的长方形,而且这三个长方形是互相正交的。
所以,想绘制一个正二十面体是比较容易的
import numpy as np
from itertools import product
G = (np.sqrt(5)-1)/2
def getVertex():
pt2 = [(a,b) for a,b in product([1,-1], [G, -G])]
pts = [(a,b,0) for a,b in pt2]
pts += [(0,a,b) for a,b in pt2]
pts += [(b,0,a) for a,b in pt2]
return np.array(pts)
xs, ys zs = getVertex().T
ax = plt.subplot(projection='3d')
ax.scatter(xs, ys, zs)
plt.show()
得到顶点
绘制棱
接下来将这些顶点连接成线,由于总共只有12个顶点,所以两两相连,也不至于导致运算量 * 。另一方面,正二十面体的边长是相同的,而这些相同的边连接的也必然是最近的点,所以接下来只需建立顶点之间的距离矩阵,然后将距离最短的线抽出来即可。
def getDisMat(pts):
N = len(pts)
dMat = np.ones([N,N])*np.inf
for i in range(N):
for j in range(i):
dMat[i,j] = np.linalg.norm([pts[i]-pts[j]])
return dMat
pts = getVertex()
dMat = getDisMat(pts)
# 由于存在舍入误差,所以得到的边的数值可能不唯一
ix, jx = np.where((dMat-np.min(dMat))<0.01)
接下来,绘制正二十面体的棱
edges = [pts[[i,j]] for i,j in zip(ix, jx)]
ax = plt.subplot(projection='3d')
for pt in edges:
ax.plot(*pt.T)
plt.show()
效果如图所示
绘制面
当然,只是有棱还显得不太好看,接下来要对正二十面体的面进行上色。由于三条棱构成一个面,所以只需得到所有三条棱的组合,然后判定这三条棱是否可以组成一个三角形,就可以获取所有的三角面。当然,这一切的前提是,正二十面体只有30个棱,即使遍历多次,也无非27k的计算量,是完全没问题的。
def isFace(e1, e2, e3):
pts = np.vstack([e1, e2, e3])
pts = np.unique(pts, axis=0)
return len(pts)==3
from itertools import combinations
faces = [es for es in combinations(edges, 3)
if isFace(*es)]
接下来绘制一下
ax = plt.subplot(projection='3d')
for f in faces:
pt = np.unique(np.vstack(f), axis=0)
try:
ax.plot_trisurf(*pt.T)
except:
pass
plt.show()
如图所示
由于plot_trisurf
的画图逻辑是,先绘制xy坐标系上的三角形,然后再以此为三角形建立z轴坐标。所以这会导致一个Bug,即所绘制的三角面不能垂直于xy坐标系,为了让正二十面体被完整地绘制出来,可以对其绕着x和y轴旋转一下,当然首先要建立一个旋转矩阵。三维空间中的旋转矩阵如下表所示。详情可参考博客:Python动态演示旋转矩阵的作用
写成代码为
# 将角度转弧度后再求余弦
cos = lambda th : np.cos(np.deg2rad(th))
sin = lambda th : np.sin(np.deg2rad(th))
# 即 Rx(th) => Matrix
Rx = lambda th : np.array([
[1, 0, 0],
[0, cos(th), -sin(th)],
[0, sin(th), cos(th)]])
Ry = lambda th : np.array([
[cos(th), 0, sin(th)],
[0 , 1, 0],
[-sin(th), 0, cos(th)]
])
然后绘图函数
ax = plt.subplot(projection='3d')
for f in faces:
pt = np.unique(np.vstack(f), axis=0)
pt = Rx(1)@Ry(1)@pt.T
ax.plot_trisurf(*pt)
for pt in edges:
pt = Rx(1)@Ry(1)@pt.T
ax.plot(*pt, lw=2, color='blue')
plt.show()
效果如下
来源:https://blog.csdn.net/m0_37816922/article/details/128258800
标签:Python,绘制,正二十面体
0
投稿
猜你喜欢
基于python实现数组格式参数加密计算
2021-08-20 23:29:54
python去掉空格的一些常用方式
2022-02-10 04:45:34
关于javascript中伪数组和真数组的一些小秘密
2023-07-02 03:47:47
MySQL学习笔记之数据的增、删、改实现方法
2024-01-27 04:07:41
Vue不能watch数组和对象变化解决方案
2024-04-30 10:41:06
pymongo实现控制mongodb中数字字段做加法的方法
2021-12-15 21:04:06
用ASP和SQL语句动态的创建Access表
2008-10-14 16:59:00
跟老齐学Python之网站的结构
2021-08-22 05:55:54
python 解析html之BeautifulSoup
2021-02-09 23:09:12
SQLServer 2000 数据库同步详细步骤[两台服务器]
2024-01-21 11:18:03
Python动态声明变量赋值代码实例
2023-11-15 03:30:47
Python如何爬取b站热门视频并导入Excel
2023-06-20 23:27:44
PHP扩展开发入门教程
2024-05-05 09:17:51
pygame编写音乐播放器的实现代码示例
2021-08-12 18:08:48
Python中使用glob和rmtree删除目录子目录及所有文件的例子
2023-12-26 07:14:18
golang编程开发使用sort排序示例详解
2023-09-16 23:20:18
php基础字符串与数组知识点讲解
2023-05-25 08:28:14
Python中使用bidict模块双向字典结构的奇技淫巧
2023-05-12 19:37:55
用Python抢火车票的简单小程序实现解析
2023-09-06 06:31:28
php 解压zip压缩包内容到指定目录的实例
2024-04-18 09:28:47