前两天去观摩了MATHWORKS官方举办的Mathematics is beautiful数学之美投票比赛,见到了很多非常惊艳的作品,在这里分享给大家让大家一同感受大神们的创造力,接下来由我来做全程解说。
虽然看起来代码都写好了,,,,但是实际运行起来真的只能说有些写的是。。。。缺胳膊少腿。
这场代码比赛有字符数限制,这就导致各个作者用了一些只有新版本支持的写法和一些比较奔放的写法,以及一些要添加依赖库的代码,老版本不太可能能运行,这里我会对代码进行修改,加注释,以及加一些有趣的东西,例如:
原作者:Tim
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/12578
原代码:
x=randn(3,999);
x=1.01*x./vecnorm(x);
[a,b,c]=sphere(99);
surf(a,b,c);
colormap hot
hold
p=delaunay(x');
h = patch('faces',p,'vertices',x', FaceVertexCD=cool(size(p, 1)),FaceA=.25);
axis equal off
set(gcf,'color','k')
shading flat
r=@()rand(1,3e2);
scatter(r()*10-5,r()*10-5,r().^2*200,'.w');
camva(2)
代码涉及到了非常多的简写是新版本才支持的:比如FaceVertexCD
实际就是'FaceVertexCData'
代码的思想非常简单,就是一个hot
渐变色的球体,外面放上一层cool
渐变色的三角形,以下给出我改写并加注释的版本:
% 先画一个hot渐变色的球
[a,b,c]=sphere(99);
surf(a,b,c);
colormap hot
hold on
% 在球面外生成一些随机点
% 进行三角剖分后
% 设置成半透明冷色
% 一些透明三角形交错叠加形成炫酷星球
x=randn(3,999);
x=1.01*x./vecnorm(x);
p=delaunay(x');
h=patch('faces',p,'vertices',x','FaceVertexCData',cool(size(p,1)),'FaceAlpha',.25);
% 设置坐标区域比例
axis equal off
% 设置背景色
set(gcf,'color','k')
set(gcf,'InvertHardCopy','off')
% 平滑星球表面配色
shading flat
% 在星球外生成一些随机点当作星星
r=@()rand(1,3e2);
scatter(r()*10-5,r()*10-5,r().^2*200,'.w');
camva(2)
如果把colormap hot
中的hot
配色改为cool
即内外都是冷色调:
如果前面配色改为bone
,‘FaceVertexCData’,cool(size(p,1))那里的cool
更改为pink
:
原作者:MvLevi
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/10775
原代码:
C=[-9:9e-3:9];
D=[-9:9e-3:9];
for q=1:2001
for j=1:2001
X=.5;
for i=1:5
if mod(i,2)==0
X(i+1)=X(i)-C(q)*(.5+.3*cos(X(i)))^-1;
else
X(i+1)=X(i)-D(j)*(.5+.3*cos(X(i)))^-1;
end
end
P=diff(X);
L(q,j)=mean(log(abs(P)));
end
end
pcolor(C,D,-L)
shading flat
colormap(twilight)
axis off
caxis([-3.5 3.5])
试了一下压根运行不出来:
函数或变量 ‘twilight’ 无法识别。
出错 PersonlizedLyapunovFractal (第 23 行)
colormap(twilight)
原来作者使用了一个MATLAB中没有但是python中有的colormap,作为python小天才这不写两行代码就能搞定的事情:
import matplotlib.pyplot as plt
import numpy as np
color=plt.get_cmap('twilight')(np.linspace(0, 1, 256))
np.savetxt('twilight.txt', np.c_[color],fmt='%f',delimiter='\t')
两行python代码把这个配色存到了txt里面,这时候读取了直接用就完事:
% 读取颜色
twilight=readmatrix('twilight.txt');
twilight=twilight(:,1:3);
C=-9:9e-3:9;
D=-9:9e-3:9;
for q=1:2001
for j=1:2001
X=.5;
for i=1:5
if mod(i,2)==0
X(i+1)=X(i)-C(q)*(.5+.3*cos(X(i)))^-1;
else
X(i+1)=X(i)-D(j)*(.5+.3*cos(X(i)))^-1;
end
end
P=diff(X);
L(q,j)=mean(log(abs(P)));
end
end
pcolor(C,D,-L)
shading flat
colormap(twilight)
axis off
caxis([-3.5 3.5])
不过为啥要叫Personlized Lyapunov Fractal作者也给出了解释:
If one were to correctly calculate a Lyapunov fractal the number of loops on the index “i” would, at bare minimum, be 100 instead of 5. That way it would at some point showcase the chaotic and non-chaotic areas of this evolution equation.
However, since the goal is to create a visually appealing image I decided to opt for a lower number of loops, making the image in my personal opinion prettier but it does make it devoid of any meaning it used to have. On top of that I personally tested and selected different evolution equations to arrive at this image. Hence the title “personalized”.
大体意思就是这个程序要100次迭代左右才能稳定,但那样我电脑就算爆了,时间也慢死,所以就让它迭代了5次出来个好看图形就完事。
原作者:Teodo
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/11128
为了节省代码量达到要求,把image
函数命名为i
他真的我哭死。原始代码:
% Credits for the code go to Jenny Bosten
a=2E3;
c=256;
X=linspace(-1,1,a);
[t,r]=cart2pol(X,X');
g=[0 .2 .5
1 .9 .9
0 0 0];
d=@rand;
i=@image;
i(ones(a))
hold
m=[];
f=[0
127
c];
for k=1:3
m=[m;bone.*g(k,:)];
colormap(m)
i(rescale(2-r,k*c-255,k*c),'AlphaData',20*abs(ifft2(r.^-1.6.*cos(7*rand(a)))));
end
scatter(a*d(a,1),a*d(a,1),d(a,1)*2,'y','f');
camva(3)
原理非常简单,就是通过ifft
生成比较连续的噪声充当星云,这些星云曲面(图片)不仅仅有着自己的一套渐变色还有三个主色调,就把三个半透明的噪声图片叠加在一起就行,可以自行调整主色调或者colormap,以下是增加注释版代码:
% Credits for the code go to Jenny Bosten
a=2e3;
c=256;
X=linspace(-1,1,a);
[t,r]=cart2pol(X,X');
% 三种基础颜色,可自行修改
g=[0 .2 .5
1 .9 .9
0 0 0];
% 把背景设置为黑色(省代码写法)
% 也可set(gca,'Color','k')
image(ones(a))
hold on
% 通过ifft2生成较为有连续性的噪声矩阵用来模拟星云
% 三次绘制不同颜色
m=[];
f=[0 127 c];
for k=1:3
m=[m;bone.*g(k,:)]; % 这里bone 改成其他颜色有奇效
colormap(m)
image(rescale(2-r,k*c-255,k*c),'AlphaData',20*abs(ifft2(r.^-1.6.*cos(7*rand(a)))));
end
% 生成黄色随机散点
scatter(a*rand(a,1),a*rand(a,1),rand(a,1)*2,'filled','MarkerFaceColor','y');
camva(3)
原作者:Stewart Thomas
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/10848
这个代码大体是把几个人的作品拼在了一起,不过效果还是不错的,依旧先给出不太容易看懂的原版代码:
%colormap(bone) % Uncomment for Pluto :)
p=@rand;
q='no';
a=500;
u=ones(a);
u(p(a)>.98)=132;
image(u);
camva(4)
axes(Color=q,CameraP=[0,2,-7],CameraT=[0,1,8],Pr='p')
hold;
% Surface code from Adam Danz (orig. remix)
% Rocky surface
% This is an inverted super-gaussian + noise
% www.mathworks.com/matlabcentral/answers/575647#answer_475645
x=meshgrid(-9:.7:9);
s=-2*exp(-(x.^2/9).^3)+2.1;
% This magic from the legend Jenny Bosten
d=-200:.801:200;
surf(x,s.*p(26),x',FaceC='texturemap',EdgeC=q,CData=abs(ifft2(abs(d+d'*i).^-1.6.*cos(7*p(a)))))
% Set equal aspect ratio
axis equal
把一些为了节省代码量的地方改过来:
%colormap(bone) % Uncomment for Pluto :)
a=500;
u=ones(a);
u(rand(a)>.98)=132;
image(u);
camva(4)
axes('Color','none','CameraPosition',[0,2,-7],'CameraTarget',[0,1,8],'Projection','perspective')
hold on
get(gca)
% Surface code from Adam Danz (orig. remix)
% Rocky surface
% This is an inverted super-gaussian + noise
% www.mathworks.com/matlabcentral/answers/575647#answer_475645
x=meshgrid(-9:.7:9);
s=-2*exp(-(x.^2/9).^3)+2.1;
% This magic from the legend Jenny Bosten
d=-200:.801:200;
surf(x,s.*rand(26),x','FaceColor','texturemap','EdgeColor','none','CData',abs(ifft2(abs(d+d'*1i).^-1.6.*cos(7*rand(a)))))
% Set equal aspect ratio
axis equal
原作者:Tim
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/12393
需要安装大佬自己写个一个体素绘制工具函数:https://ww2.mathworks.cn/matlabcentral/fileexchange/78745-voxview?s_tid=srchtitle_VOXview_1
虽说代码量有规定,但是没说不让引用上千行的工具函数哈哈哈,工具函数我已经下载了在文末压缩包内:
x=-1:.005:1;
r=sqrt(x.^2+x'.^2);
g=abs(ifft2(exp(6*1i*rand(401))./max(r.^2,1e-4)))-.1;
surf(30*g);
shading flat
hold on;
t=ones(401,401,41);
t(1)=.9;
VOXview(t*.1, t.*(-1:.0025:0).^2);
colormap(flipud(gray));
caxis([0 20])
axis off
set(gcf,'color',[.8,.9,1])
light
camva(60)
campos([380, 320, 30])
代码还是没啥好说的,经典的傅里叶逆变换生成连续噪声,事实上如果没下载工具函数仅仅运行部分代码也能有不错的效果:
x=-1:.005:1;
r=sqrt(x.^2+x'.^2);
g=abs(ifft2(exp(6*1i*rand(401))./max(r.^2,1e-4)))-.1;
surf(30*g);
shading flat
hold on;
t=ones(401,401,41);
t(1)=.9;
colormap(flipud(gray));
caxis([0 20])
原作者:Brandon Caasenbrood
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/11308
作者将Paul Bourke
大佬的分形作品使用MATLAB进行了复现:
% Inspired by the work of Paul Bourke
% see http://paulbourke.net/fractals/clifford/
N = 1e8;
x = single(zeros(N,1)); % required for speed up
y = x;
F = @(x,y) [,];
% Clifford Attractor - discrete system
for k=1:N-1
x(k+1)=sin(-2*y(k))+cos(-2*x(k));
y(k+1)=sin(2*x(k))-cos(2*y(k));
end
I = zeros(900);
E = 1;
D = size(I,1) - 2*E;
for k=1:N
W=ceil(D*(x(k)+2)/4)+E;
U=ceil(D*(y(k)+2)/4)+E;
I(W,U)=I(W,U)+.002;
end
imshow(I);
set(gcf,'Color','k');
axis tight;
事实上如果前往 http://paulbourke.net/fractals/clifford/ 进行查看:
将迭代部分a,b,c,d
数值修改还会有不同的效果,比如:
for k=1:N-1
x(k+1)=sin(-1.4*y(k))+cos(-1.4*x(k));
y(k+1)=sin(1.6*x(k))+0.7.*cos(1.6*y(k));
end
当然Paul Bourke
大佬的网站已经算好并提供了一部分效果:
Peter de Jong attractors以及 Paul Richards 也做了部分相关工作,整出来一些很有意思的图片:
原作者:Adam Danz
链接:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/5/entries/10580
这段代码真的是简单但是绘制出来的图片非常有张力,拿柱状图当房子非常有创造力:
% rng(0) %(twister)
c=[.2 .1 .2];
axes(colorm=autumn,Color=c,Pr='p',CameraT=[40 33 3])
hold on
bar3(randg(2,60),'c');
axis equal
campos([1,33,7])
% camva(70)
t=0:.1:6;
fill3(0*t+61,40*cos(t)+30,40*sin(t)+5,t)
p=plot3([61 61],[-10 70],[1;1]*(5:3:30),Col=c);
set(p,{'LineW'},num2cell(9:-1:1)')
light(po=[-70 4 2],Col=[1 .2 0])
微调后代码
c=[.2 .1 .2];
axes('Colormap',autumn,'Color',c,'Projection','perspective','CameraTarget',[40 33 3])
hold on
bar3(randg(2,60),'c');
axis equal
campos([1,33,7])
% camva(70)
t=0:.1:6;
fill3(0*t+61,40*cos(t)+30,40*sin(t)+5,t)
p=plot3([61 61],[-10 70],[1;1]*(5:3:30),'Color',c);
set(p,{'LineWidth'},num2cell(9:-1:1)')
light('Position',[-70 4 2],'Color',[1 .2 0])
hiahiahia在浏览过程中发现有几个人引用并以我写的工具函数为基础作图进行了参赛,甚至有的工具函数被mathworks工作人员引用了:
这里篇幅原因就只给我的玫瑰花球的代码:
function roseBall(colorList)
% @author:slandarer
%曲面数据计算
%==========================================================================
[x,t]=meshgrid((0:24)./24,(0:0.5:575)./575.*20.*pi+4*pi);
p=(pi/2)*exp(-t./(8*pi));
change=sin(15*t)/150;
u=1-(1-mod(3.6*t,2*pi)./pi).^4./2+change;
y=2*(x.^2-x).^2.*sin(p);
r=u.*(x.*sin(p)+y.*cos(p));
h=u.*(x.*cos(p)-y.*sin(p));
%颜色映射表
%==========================================================================
hMap=(h-min(min(h)))./(max(max(h))-min(min(h)));
col=size(hMap,2);
if nargin<1
colorList=[0.1300 0.1000 0.1600
0.2000 0.0900 0.2000
0.2800 0.0800 0.2300
0.4200 0.0800 0.3000
0.5100 0.0700 0.3400
0.6600 0.1200 0.3500
0.7900 0.2200 0.4000
0.8800 0.3500 0.4700
0.9000 0.4500 0.5400
0.8900 0.7800 0.7900];
end
colorFunc=colorFuncFactory(colorList);
dataMap=colorFunc(hMap');
colorMap(:,:,1)=dataMap(:,1:col);
colorMap(:,:,2)=dataMap(:,col+1:2*col);
colorMap(:,:,3)=dataMap(:,2*col+1:3*col);
function colorFunc=colorFuncFactory(colorList)
xx=(0:size(colorList,1)-1)./(size(colorList,1)-1);
y1=colorList(:,1);y2=colorList(:,2);y3=colorList(:,3);
colorFunc=@(X)[interp1(xx,y1,X,'linear')',interp1(xx,y2,X,'linear')',interp1(xx,y3,X,'linear')'];
end
%曲面旋转及绘制
%==========================================================================
surface(r.*cos(t),r.*sin(t),h+0.35,'EdgeAlpha',0.05,...
'EdgeColor',[0 0 0],'FaceColor','interp','CData',colorMap)
hold on
surface(r.*cos(t),r.*sin(t),-h-0.35,'EdgeAlpha',0.05,...
'EdgeColor',[0 0 0],'FaceColor','interp','CData',colorMap)
Xset=r.*cos(t);
Yset=r.*sin(t);
Zset=h+0.35;
yaw_z=72*pi/180;
roll_x=pi-acos(-1/sqrt(5));
R_z_2=[cos(yaw_z),-sin(yaw_z),0;
sin(yaw_z),cos(yaw_z),0;
0,0,1];
R_z_1=[cos(yaw_z/2),-sin(yaw_z/2),0;
sin(yaw_z/2),cos(yaw_z/2),0;
0,0,1];
R_x_2=[1,0,0;
0,cos(roll_x),-sin(roll_x);
0,sin(roll_x),cos(roll_x)];
[nX,nY,nZ]=rotateXYZ(Xset,Yset,Zset,R_x_2);
surface(nX,nY,nZ,'EdgeAlpha',0.05,...
'EdgeColor',[0 0 0],'FaceColor','interp','CData',colorMap)
for k=1:4
[nX,nY,nZ]=rotateXYZ(nX,nY,nZ,R_z_2);
surface(nX,nY,nZ,'EdgeAlpha',0.05,...
'EdgeColor',[0 0 0],'FaceColor','interp','CData',colorMap)
end
[nX,nY,nZ]=rotateXYZ(nX,nY,nZ,R_z_1);
for k=1:5
[nX,nY,nZ]=rotateXYZ(nX,nY,nZ,R_z_2);
surface(nX,nY,-nZ,'EdgeAlpha',0.05,...
'EdgeColor',[0 0 0],'FaceColor','interp','CData',colorMap)
end
%--------------------------------------------------------------------------
function [nX,nY,nZ]=rotateXYZ(X,Y,Z,R)
nX=zeros(size(X));
nY=zeros(size(Y));
nZ=zeros(size(Z));
for i=1:size(X,1)
for j=1:size(X,2)
v=[X(i,j);Y(i,j);Z(i,j)];
nv=R*v;
nX(i,j)=nv(1);
nY(i,j)=nv(2);
nZ(i,j)=nv(3);
end
end
end
%axes属性调整
%==========================================================================
ax=gca;
grid on
ax.GridLineStyle='--';
ax.LineWidth=1.2;
ax.XColor=[1,1,1].*0.4;
ax.YColor=[1,1,1].*0.4;
ax.ZColor=[1,1,1].*0.4;
ax.DataAspectRatio=[1,1,1];
ax.DataAspectRatioMode='manual';
ax.CameraPosition=[-6.5914 -24.1625 -0.0384];
end
这三款代码的详细解释请点击下列链接跳转推送:
链接:https://mp.weixin.qq.com/s/pdCyopOeUwYGc4p_tMzZsg
链接:https://mp.weixin.qq.com/s/XnVEuWZRoBMaePUMkLNZRA
链接:https://mp.weixin.qq.com/s/eYrqGUDWs0bubWTXGfPkLA
完整代码及素材:
链接:
https://pan.baidu.com/s/1syihVAfOIwQ1TQVc9MQ4Jg?pwd=slan
提取码:slan