端午节到了,用Python画一个粽子吧!

粽子曲面

之前通过matplotlib绘制了圆锥曲面,但matplotlib绘制曲面图有几个问题,其中plot_surface需要有规范的xOy坐标,然后根据其坐标绘制z轴参数;plot_trisurf则必须有明确的三角面的顶点。这些限制提高了绘制三维曲面的技术要求,所以接下来用open3d来以点云的形式来绘制一些更复杂的曲面。

首先就是下面这个参数方程对应的曲面

{ x = a cos ⁡ u y = a cos ⁡ v z = a cos ⁡ ( u + v ) u , v ∈ ( 0 , 2 π ) \left\{\begin{aligned} x&=a\cos u\\ y&=a\cos v\\ z&=a\cos(u+v) \end{aligned}\right.\quad u,v \in (0,2\pi) xyz=acosu=acosv=acos(u+v)u,v(0,2π)

下面是绘图代码

import numpy as np
import open3d as o3d

def getSin(N):
    u = np.linspace(0, np.pi*2, N)
    v = np.linspace(0, np.pi*2, N)
    u,v = np.meshgrid(u,v)
    x = np.cos(u).reshape(-1)
    y = np.cos(v).reshape(-1)
    z = np.cos(u+v).reshape(-1)
    return np.array([x,y,z]).T

pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(getSin(500))
o3d.visualization.draw_geometries([pcd])

最后效果如下,非常像一个粽子

在这里插入图片描述

真·粽子曲面

上面的粽子图,其实是散点图,只不过点数太多,看上去就比较连续,接下来通过open3d,将这个粽子的散点图,转换为粽子曲面。由于曲面生成的本质是绘制三角面,而随着点数的增多,所需绘制时间也就越长,故而少选一些点

tri = o3d.geometry.TriangleMesh

pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(getSin(20))
mesh = tri.create_from_point_cloud_alpha_shape(pcd, 2)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)

其中,o3d.geometry.TriangleMesh是一个类,之所以将其重新赋值,皆因后面调用的生成曲面的方法名字太长,这样可以缩减一下一行的长度。

compute_vertex_normals用于生成法线,如果没有这个,最后得到的曲面是看不出三维效果的。

最终得到的效果如下,像是个金属质感的粽子,还挺好看的

在这里插入图片描述

点击Ctrl+数字,可以更改曲面的配色,为了表现得更加细腻,下面用 100 × 100 100\times100 100×100的网格来生成粽子曲面,效果如下

在这里插入图片描述

正弦曲面

粽子曲面又叫余弦曲面,如果把 cos ⁡ \cos cos换成 sin ⁡ \sin sin,那么就得到了正弦曲面

{ x = a sin ⁡ u y = a sin ⁡ v z = a sin ⁡ ( u + v ) u , v ∈ ( 0 , 2 π ) \left\{\begin{aligned} x&=a\sin u\\ y&=a\sin v\\ z&=a\sin(u+v) \end{aligned}\right.\quad u,v \in (0,2\pi) xyz=asinu=asinv=asin(u+v)u,v(0,2π)

其绘图代码如下

import numpy as np
import open3d as o3d

def getCos(N):
    u = np.linspace(0, np.pi*2, N)
    v = np.linspace(0, np.pi*2, N)
    u,v = np.meshgrid(u,v)
    x = np.sin(u).reshape(-1)
    y = np.sin(v).reshape(-1)
    z = np.sin(u+v).reshape(-1)
    return np.array([x,y,z]).T

pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(getCos(500))
pcd.estimate_normals()
o3d.visualization.draw_geometries([pcd])

其中,estimate_normals用于估计点的法线,这样在绘图的时候会产生漂亮的光效,最终绘图结果如下,可见正弦曲面和余弦曲面的确有着类似互补的性质。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_37816922/article/details/131186700