来自理科生的浪漫

您所在的位置:网站首页 许家印做了什么事被监视 来自理科生的浪漫

来自理科生的浪漫

#来自理科生的浪漫| 来源: 网络整理| 查看: 265

如何使用canvas绘制李峋同款爱心?情人节的由来可以追溯到古罗马时期。

当时会举行一个叫做“Lupercalia”的节日,这个节日是为了纪念罗马神话中的牧羊神Lupercus。

在这个节日里,男性会赤膊跑到街上,用皮鞭抽打女性,以此来祈求丰收和健康。

后来,罗马天主教会将这个节日改称为“圣瓦伦丁节”,以纪念瓦伦丁大主教,他曾经禁止这种抽打女性的习俗。

现在的情人节,则是从这个节日演变而来,它是一个纪念爱情的节日。在情人节,男女方会在这一天互赠礼物(玫瑰,巧克力或者贺卡)以表达爱意或者友好。

今天我们就来看看那些浪漫的程序员们是如何表达自己的爱意的吧!

在坐标轴上画爱心

笛卡尔与心形函数的故事始于17世纪,当时笛卡尔正在研究函数的性质,他发现了一个特殊的函数,它的图像是一个心形,他称之为“心形函数”。笛卡尔把这个函数命名为“爱情函数”,以此来表达他对爱情的热爱。后来,这个函数被用来表示爱情,成为情人节的象征,也成为现代数学中的一个重要概念。

现在,我们可以在python中使用matplotlib来把这个函数画出来:

import matplotlib.pyplot as plt import numpy as np #生成从-1到1的以为数组作为x轴的数据 x_data1 = np.linspace(-1,1,1000) #根据心形公式,得到y的表达式,由于有正负之分,故分开表示 y_data1 = np.sqrt(1 - x_data1**2) + pow(np.abs(x_data1),float(2)/float(3)) y_data2 = -np.sqrt(1 - x_data1**2)+ pow(np.abs(x_data1),float(2)/float(3)) #设置空图表,并把两组数据已散点图的形式画在空图表上 fig = plt.figure() plt.scatter(x_data1, y_data1,color = 'red') plt.scatter(x_data1, y_data2,color = 'red') #设置坐标轴的显示范围 plt.xlim(-1.25,1.25) plt.ylim(-1.2,1.7) #得到坐标轴信息 ax = plt.gca() #设置坐标轴颜色,把右边和顶部的坐标设置为没有颜色 ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.spines['bottom'].set_color('white') ax.spines['left'].set_color('white') #设置坐标轴的位置 ax.spines['left'].set_position(('data',0)) ax.spines['bottom'].set_position(('data',0)) #设置刻度的位置 ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') #设置刻度的相关参数,依次包括:坐标轴名称,字体大小,字体倾斜角度,字体颜色 ax.tick_params(axis="x", labelsize=18, labelrotation=0, labelcolor="white") ax.tick_params(axis="y", labelsize=18, labelrotation=0, labelcolor="white") #设置坐标轴线的宽度 ax.spines['bottom'].set_linewidth(3) ax.spines['left'].set_linewidth(3) #设置图片的背景 ax.set_facecolor('xkcd:black') #设置图表的长宽 fig.set_figheight(15) fig.set_figwidth(15) #设置 ax.grid(True, linestyle='-.') plt.show() #保存绘制的图形到默认的目录 #fig.savefig('heart.png', dpi=500)

代码的运行结果如下所示:

另外,关于心形函数还有3D版本,代码如下所示:

import bbox as bbox import matplotlib.pyplot as plt import numpy as np def heart_3d(x, y, z): return (x ** 2 + (9 / 4) * y ** 2 + z ** 2 - 1) ** 3 - x ** 2 * z ** 3 - (9 / 80) * y ** 2 * z ** 3 def heart_3d_2(x, y, z): return (2 * x ** 2 + 2 * y ** 2 + z ** 2 - 1) ** 3 - 0.1 * x ** 2 * z ** 3 - y ** 2 * z ** 3 def plot_implicit(fn, bbox=(-1.5, 1.5)): xmin, xmax, ymin, ymax, zmin, zmax = bbox * 3 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') A = np.linspace(xmin, xmax, 100) B = np.linspace(xmin, xmax, 40) A1, A2 = np.meshgrid(A, A) for z in B: X, Y = A1, A2 Z = fn(X, Y, z) cset = ax.contour(X, Y, Z + z, [z], zdir='z', colors=('r',)) for y in B: X, Z = A1, A2 Y = fn(X, y, Z) cset = ax.contour(X, Y + y, Z, [y], zdir='y', colors=('red',)) for x in B: Y, Z = A1, A2 X = fn(x, Y, Z) cset = ax.contour(X + x, Y, Z, [x], zdir='x', colors=('red',)) ax.set_zlim3d(zmin, zmax) ax.set_xlim3d(xmin, xmax) ax.set_ylim3d(ymin, ymax) #改变视角 ax.view_init(elev=5., azim=-76) # 取消坐标轴显示 plt.axis('off') plt.show() if __name__ == '__main__': plot_implicit(heart_3d)

运行结果如下所示:

使用matplotlib绘制漂亮的花花

matplotlib不止可以用来画爱心,如果对3D建模感兴趣的,可以学一些python绘制3D花的原理,以下是使用python在matplotlib中绘制玫瑰花的代码案例:

import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(projection='3d') # 将相位向后移动了6*pi [x, t] = np.meshgrid(np.array(range(25)) / 24.0, np.arange(0, 575.5, 0.5) / 575 * 20 * np.pi + 4*np.pi) p = (np.pi / 2) * np.exp(-t / (8 * np.pi)) # 添加边缘扰动 change = np.sin(15*t)/150 # 将t的参数减少,使花瓣的角度变大 u = 1 - (1 - np.mod(3.3 * t, 2 * np.pi) / np.pi) ** 4 / 2 + change y = 2 * (x ** 2 - x) ** 2 * np.sin(p) r = u * (x * np.sin(p) + y * np.cos(p)) h = u * (x * np.cos(p) - y * np.sin(p)) c= plt.get_cmap('Reds') surf = ax.plot_surface(r * np.cos(t), r * np.sin(t), h, rstride=1, cstride=1, cmap= c, linewidth=0, antialiased=True) plt.show()

运行结果如下所示:

使用turtle绘制图案

turtle是一个python绘图库,我们可以通过代码来控制turtle来绘制一些图形,比如一个简单的爱心或者一朵美丽的玫瑰花,爱心的绘制比较简单:

import turtle #导入turtle库 turtle.pensize(4)#设置画笔像素为4像素 turtle.pencolor("red")#设置画笔颜色为红色 turtle.fillcolor("pink")#设置填充颜色为粉红色 turtle.begin_fill()#开始填充 #开始绘制爱心 turtle.left(135) turtle.forward(100) turtle.circle(-50,180)#第一个半圆 turtle.left(90) turtle.circle(-50,180)#第二个半圆 turtle.forward(100) turtle.end_fill()#结束填充 turtle.done()

运行结果如下所示:

玫瑰花的绘制比较复杂:

from turtle import * import time #初始化玫瑰 #画布大小 setup(600,800,0,0) speed(0) penup() # 提起画笔 seth(90) #朝向90度 fd(340) #向前移动指定的距离 seth(0) pendown() #放下画笔 #开始画 speed(5) #画笔移动速度为5秒 begin_fill() #开始填充 fillcolor('red') #为红色 circle(50,30) #画一个半径为50,弧度为30的圆 for i in range(10): fd(1) left(10) #逆时针转动画笔10度 circle(40,40) for i in range(6): fd(1) left(3) circle(80,40) for i in range(20): fd(0.5) left(5) circle(80,45) for i in range(10): fd(2) left(1) circle(80,25) for i in range(20): fd(1) left(4) circle(50,50) time.sleep(0.1) circle(120,55) speed(3) seth(-90) fd(70) right(150) #顺时针转动画笔150度 fd(20) left(140) circle(140,90) left(30) circle(160,100) left(130) fd(25) penup() right(150) circle(40,80) pendown() left(115) fd(60) penup() left(180) fd(60) pendown() end_fill() right(120) circle(-50,50) circle(-20,90) speed(1) fd(75) speed(1) circle(90,110) penup() left(162) fd(185) left(170) pendown() circle(200,10) circle(100,40) circle(-52,115) left(20) circle(100,20) circle(300,20) speed(1) fd(250) penup() speed(2) left(180) fd(250) circle(-300,7) right(80) circle(200,5) pendown() left(60) begin_fill() fillcolor('green') circle(-80,100) right(90) fd(10) left(20) circle(-63,127) end_fill() penup() left(50) fd(20) left(180) pendown() circle(200,25) penup() right(150) fd(180) right(40) pendown() begin_fill() fillcolor('green') circle(-100,80) right(150) fd(10) left(60) circle(-80,98) end_fill() penup() left(60) fd(13) left(180) pendown() speed(1) circle(-200,23) exitonclick() #当点击时退出

运行结果如下:

使用canvas绘制爱心

在如何使用canvas绘制李峋同款爱心?一文中,我们介绍了如何使用HTML的canvas结合JavaScript来绘制一个跳动的爱心,现在我们来重温一下这段代码:

爱心代码 html, body { height: 100%; padding: 0; margin: 0; background: #000; } canvas { position: absolute; width: 100%; height: 100%; } var settings = { particles: { length: 500, duration: 2, velocity: 100, effect: -0.75, size: 32, }, }; (function () { var b = 0; var c = ["ms", "moz", "webkit", "o"]; for (var a = 0; a < c.length && !window.requestAnimationFrame; ++a) { window.requestAnimationFrame = window[c[a] + "RequestAnimationFrame"]; window.cancelAnimationFrame = window[c[a] + "CancelAnimationFrame"] || window[c[a] + "CancelRequestAnimationFrame"]; } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (h, e) { var d = new Date().getTime(); var f = Math.max(0, 16 - (d - b)); var g = window.setTimeout(function () { h(d + f); }, f); b = d + f; return g; }; } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (d) { clearTimeout(d); }; } })(); var Point = (function () { function Point(x, y) { this.x = typeof x !== "undefined" ? x : 0; this.y = typeof y !== "undefined" ? y : 0; } Point.prototype.clone = function () { return new Point(this.x, this.y); }; Point.prototype.length = function (length) { if (typeof length == "undefined") return Math.sqrt(this.x * this.x + this.y * this.y); this.normalize(); this.x *= length; this.y *= length; return this; }; Point.prototype.normalize = function () { var length = this.length(); this.x /= length; this.y /= length; return this; }; return Point; })(); var Particle = (function () { function Particle() { this.position = new Point(); this.velocity = new Point(); this.acceleration = new Point(); this.age = 0; } Particle.prototype.initialize = function (x, y, dx, dy) { this.position.x = x; this.position.y = y; this.velocity.x = dx; this.velocity.y = dy; this.acceleration.x = dx * settings.particles.effect; this.acceleration.y = dy * settings.particles.effect; this.age = 0; }; Particle.prototype.update = function (deltaTime) { this.position.x += this.velocity.x * deltaTime; this.position.y += this.velocity.y * deltaTime; this.velocity.x += this.acceleration.x * deltaTime; this.velocity.y += this.acceleration.y * deltaTime; this.age += deltaTime; }; Particle.prototype.draw = function (context, image) { function ease(t) { return --t * t * t + 1; } var size = image.width * ease(this.age / settings.particles.duration); context.globalAlpha = 1 - this.age / settings.particles.duration; context.drawImage( image, this.position.x - size / 2, this.position.y - size / 2, size, size ); }; return Particle; })(); var ParticlePool = (function () { var particles, firstActive = 0, firstFree = 0, duration = settings.particles.duration; function ParticlePool(length) { // create and populate particle pool particles = new Array(length); for (var i = 0; i < particles.length; i++) particles[i] = new Particle(); } ParticlePool.prototype.add = function (x, y, dx, dy) { particles[firstFree].initialize(x, y, dx, dy); // handle circular queue firstFree++; if (firstFree == particles.length) firstFree = 0; if (firstActive == firstFree) firstActive++; if (firstActive == particles.length) firstActive = 0; }; ParticlePool.prototype.update = function (deltaTime) { var i; // update active particles if (firstActive < firstFree) { for (i = firstActive; i < firstFree; i++) particles[i].update(deltaTime); } if (firstFree < firstActive) { for (i = firstActive; i < particles.length; i++) particles[i].update(deltaTime); for (i = 0; i < firstFree; i++) particles[i].update(deltaTime); } // 移除非活性粒子 while ( particles[firstActive].age >= duration && firstActive != firstFree ) { firstActive++; if (firstActive == particles.length) firstActive = 0; } }; ParticlePool.prototype.draw = function (context, image) { // 绘制活性粒子 if (firstActive < firstFree) { for (i = firstActive; i < firstFree; i++) particles[i].draw(context, image); } if (firstFree < firstActive) { for (i = firstActive; i < particles.length; i++) particles[i].draw(context, image); for (i = 0; i < firstFree; i++) particles[i].draw(context, image); } }; return ParticlePool; })(); (function (canvas) { var context = canvas.getContext("2d"), particles = new ParticlePool(settings.particles.length), particleRate = settings.particles.length / settings.particles.duration, // particles/sec time; // 用-PI


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3