当前位置:网站首页>七夕,当爱神丘比特遇上牛郎和织女
七夕,当爱神丘比特遇上牛郎和织女
2022-08-04 21:33:00 【天元浪子】
七夕是中国民间的传统节日,不同时代、不同地域的人们给这个节日赋予了不同的含义。在漫长的演变过程中,七夕成了牛郎织女相会的日子。正因为这个美丽的爱情传说,七夕被视为中国最具浪漫色彩的、象征爱情的节日。在西风东渐的背景下,七夕又成了中国的“情人节”。
既然是情人节,浪漫的程序员总喜欢搞点花样出来,为紧张且平淡的生活添点色彩。今天给各位带来的是3D动画版的丘比特爱情之剑:一只金色的丘比特爱情之剑以慢镜头方式缓缓刺中一个脉动的红心,红心的主人将会无法控制地爱上TA所看到第一个人。我猜,当初牛郎和织女一定是被丘比特的爱情之剑射中以后才相爱的,毕竟,他们都生活在天上——西方文化中,木星(Jupiter)就是小爱神丘比特,金星(Venus)则是大爱神维纳斯。
在丘比特的爱情之剑出场前,先用matplotlib绘制一颗2D的红心热热身。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-np.pi/2, np.pi/2, 1000)
y1 = np.power(np.cos(x),0.5) * np.cos(200*x) + np.power(np.absolute(x),0.5) - 0.7
y2 = np.power(4-np.power(x, 2), 0.01)
plt.plot(x, y1*y2, c='r')
plt.show()

放大一点看的话,就会发现上面这颗红心其实是一条连续上下波动的曲线。下面的红心,是一个真正封闭的心形,只不过是由四条曲线首尾相连组成的。
import numpy as np
import matplotlib.pyplot as plt
x1 = np.linspace(0, 2, 300)
x2 = np.linspace(0, -2, 300)
y11 = (np.power(x1, 2/3) + np.power(np.power(x1, 4/3)-4*np.power(x1, 2)+4, 0.5))/2 - 0.12
y12 = (np.power(x1, 2/3) - np.power(np.power(x1, 4/3)-4*np.power(x1, 2)+4, 0.5))/2
y21 = (np.power(-x2, 2/3) + np.power(np.power(-x2, 4/3)-4*np.power(-x2, 2)+4, 0.5))/2 - 0.12
y22 = (np.power(-x2, 2/3) - np.power(np.power(-x2, 4/3)-4*np.power(-x2, 2)+4, 0.5))/2
plt.plot(x1, y11, c='r')
plt.plot(x1, y12, c='r')
plt.plot(x2, y21, c='r')
plt.plot(x2, y22, c='r')
plt.show()

那么,可以用一笔画一个心形吗?当然可以,极坐标方程 r = arccos(sinθ)就是一条心形线,只是形状不够完美而已。
import numpy as np
import matplotlib.pyplot as plt
theta = np.linspace(0, 2*np.pi, 1000)
x = np.arccos(np.sin(theta)) * np.cos(theta)
y = np.arccos(np.sin(theta)) * np.sin(theta)
plt.plot(x, y, c='r')
plt.show()

是时候展示3D版的红心了。运行下面的代码,除了需要numpy模块,还需要安装wxgl模块——基于PyOpenGL的三维数据绘图工具包。
pip install wxgl
关于wxgl模块的更多详情,请点击十分钟玩转3D绘图:WxGL完全手册,这里是中文文档。
下面是3D版的红心的绘制代码,
import numpy as np
import wxgl.glplot as glt
a = np.linspace(0, 2*np.pi, 500)
b = np.linspace(0.5*np.pi, -0.5*np.pi, 500)
lons, lats = np.meshgrid(a, b)
w = np.sqrt(np.abs(a - np.pi)) * 2
x = 2 * np.cos(lats) * np.sin(lons) * w
y = -2 * np.cos(lats) * np.cos(lons) * w
z = 2 * np.sin(lats)
glt.mesh(x, y, z, color='crimson') # crimson - 绯红
glt.show()
是不是很简单?wxgl的使用风格几乎和matplotlib完全一致。拖动鼠标,就可以看到这个3D版的红心的前后左右了。

接下来,这段代码将红心数据的生成封装了一个函数,然后调用自定义的模型变换函数,这颗红心就跳动起来了。
import numpy as np
import wxgl.glplot as glt
def red_heart(r, slices=100, thick=2.0, shift=(0,0,0)):
"""返回红心顶点数据"""
a = np.linspace(0, 2*np.pi, slices)
b = np.linspace(0.5*np.pi, -0.5*np.pi, slices)
lons, lats = np.meshgrid(a, b)
w = np.sqrt(np.abs(a - np.pi)) * thick
x = r * np.cos(lats) * np.sin(lons) * w + shift[0]
y = -r * np.cos(lats) * np.cos(lons) * w + shift[1]
z = r * np.sin(lats) + shift[2]
return x, y, z
def heart_beat(t):
"""心跳函数"""
t %= 1000
if t < 300:
scale = 1 + t/3000
elif t > 700:
scale = 1 + (1000-t)/3000
else:
scale = 1.1
return (scale,)
glt.mesh(*red_heart(2), color='crimson', transform=heart_beat)
glt.show()
点击左侧工具条上的播放按钮,这颗红心就会按照60次/秒的心率跳动起来。熟悉了wxgl的使用,不难读懂下面这个完整的丘比特爱情之箭的代码。
import numpy as np
import wxgl
import wxgl.glplot as glt
def red_heart(r, slices=100, thick=2.0, shift=(0,0,0)):
"""返回红心顶点数据"""
a = np.linspace(0, 2*np.pi, slices)
b = np.linspace(0.5*np.pi, -0.5*np.pi, slices)
lons, lats = np.meshgrid(a, b)
w = np.sqrt(np.abs(a - np.pi)) * thick
x = r * np.cos(lats) * np.sin(lons) * w + shift[0]
y = -r * np.cos(lats) * np.cos(lons) * w + shift[1]
z = r * np.sin(lats) + shift[2]
return x, y, z
def heart_beat(t):
"""心跳函数"""
t %= 1000
if t < 300:
scale = 1 + t/3000
elif t > 700:
scale = 1 + (1000-t)/3000
else:
scale = 1.1
return (scale,)
def arrow_fly(t):
"""丘比特之箭飞行函数"""
t %= 4000
if t > 2000:
return ((0,-2,40-t/100),)
else:
return ((0,-2,0),)
def heart_fly(t):
"""丘比特之箭飞行函数"""
t %= 4000
if t > 2000:
return ((0,0,1,90), (0,-2,40-t/100))
else:
return ((0,0,1,90), (0,-2,0))
glt.figure(azim=50, elev=16, style='gray') # 设置初始方位角、高度角、背景色
glt.mesh(*red_heart(2), color='crimson', transform=heart_beat) # 绘制跳动的红心
x, y, z = red_heart(0.2, thick=3.0, shift=(0,-8,0)) # 生成心形箭头顶点数据
glt.mesh(x, -z, y, color='crimson', transform=heart_fly) # 绘制心形箭头
light = wxgl.SunLight(roughness=0, metalness=0, shininess=0.5) # 箭杆灯光
glt.cylinder((0,0,-8), (0,0,9), 0.1, color='goldenrod', transform=arrow_fly, light=light) # 绘制箭杆
vs = [(-1,1,11), (1,-1,11), (1,-1,6), (-1,1,6),(-1,-1,11), (1,1,11), (1,1,6), (-1,-1,6)] # 箭尾顶点数据
texture = wxgl.Texture(r'res\feather.png') # 箭尾羽毛纹理
texcoord = [(0,1), (0,0), (1,0), (1,1),(0,1), (0,0), (1,0), (1,1)] # 箭尾纹理坐标
light = wxgl.BaseLight() # 箭尾灯光
glt.quad(vs, texture=texture, texcoord=texcoord, transform=arrow_fly, light=light) # 绘制箭尾
glt.show()
wxgl的工具条提供了录制gif和MP4文件的功能,下面的gif就是使用wxgl自带的录制功能生成的。

代码中用到了羽毛的纹理,请下载这个图片,并保存到代码指定的位置。
边栏推荐
猜你喜欢

Develop your own text recognition application with Tesseract

Yolov7:Trainable bag-of-freebies sets new state-of-the-art for real-time objectdetectors

大势所趋之下的nft拍卖,未来艺术品的新赋能

ES6高级-async的用法

PMP证书在哪些行业有用?

PRIMAL: Pathfinding via Reinforcement and Imitation Multi-Agent Learning Code Analysis

数电快速入门(五)(编码器的介绍以及通用编码器74LS148和74LS147的介绍)

88. (the home of cesium) cesium polymerization figure

js data type, throttling/anti-shake, click event delegation optimization, transition animation

Red team kill-free development practice of simulated confrontation
随机推荐
拼多多开放平台订单信息查询接口【pdd.order.basic.list.get订单基础信息列表查询接口(根据成交时间)】代码对接教程
Dotnet using WMI software acquisition system installation
webmine网页挖矿木马分析与处置
路由中的meta、params传参的一些问题(可传不可传,为空,搭配,点击传递多次参数报错)
数电快速入门(二)(复合逻辑运算和逻辑代数的基本定律的介绍)
AtCoder Beginner Contest 262 D - I Hate Non-integer Number
LayaBox---TypeScript---Problems encountered at first contact
热力学相关的两个定律
88.(cesium之家)cesium聚合图
mdk5.14 cannot be burned
动手学深度学习_NiN
1319_STM32F103串口BootLoader移植
Some problems with passing parameters of meta and params in routing (can be passed but not passed, empty, collocation, click to pass multiple parameters to report an error)
In action: 10 ways to implement delayed tasks, with code!
PCBA scheme design - kitchen voice scale chip scheme
Chapter7 : Network-Driven Drug Discovery
PCBA方案设计——厨房语音秤芯片方案
LeetCode: 406. 根据身高重建队列
[21 days learning challenge - kernel notes] (2), based in the device tree
知识分享|如何设计有效的帮助中心,不妨来看看以下几点