概述
Fibonacci可视化
- 课程简介
- 题目要求
- 设计及代码实现
- 封面设计
- 内容设计
- tab1——兔子问题基本假设及介绍
- 兔子问题可视化
- 黄金螺旋线
- Return功能实现
- 写在最后
课程简介
作为数学系学生,数学模型这门课对于我们来说真的是又爱又恨。作为一门数学课,基础原理是十分重要的,但囿于学生水平不足,很多细节往往是一带而过,老师一笑置之。到了期末是最好笑,这里请允许我吐槽几句,翻开书吧,又发现里面很多代码没有自己动手过,打开了电脑吧,又发现都期末了,现在来跑跑代码也不大有用。高姿态上了一学期的水课,心想着:就这······不会有人过不了吧。巧了,我有一同学也这么想,结果还真挂科了,这还是他读这么久以来第一次挂科。废话不多说,我们来看看课程设计是个什么牛马玩意。
题目要求
我抽到的题目其实很无聊☕,如下:
Fibonacci数列的比值极限分析及可视化设计
(1)参考课本章节10.2和幻灯片7.2内容,介绍差分方程的基本知识及Fibonacci数列相关理论;
(2)请基于 Matlab APP Designer 设计 Fibonacci 数列的比值极限系统。
是不是人就傻了,这玩意有啥好写的。硬要写的话,只能联想一下这个问题的著名起源——兔子问题:在神奇的印度大陆,兔子长盛不衰,神奇的幼兔一个月就一定会成长为成兔,而我们神奇的成兔一个月必生一对幼兔,成兔为了保持自己kpi,这个过程每个月都如此反复,乐此不疲。说到 Fibonacci,更为常人所知的还有黄金分割——0.618,这个数字正是在
n
(
n
→
∞
)
n(nrightarrowinfty)
n(n→∞) 个月后成兔与兔子总数之间的比值。
设计及代码实现
封面设计
我的课程设计里面总共包括两个.mlapp文件,一个是封面,一个是主要内容。
以下是我的封面设计(model_app.mlapp)
很简单,一共就只有一个图像控件(图像控件在较新的matlab版本中才有),3个按钮控件和一个文本框。分别给3个按钮添加回调函数,实现不同的功能(选中控件,右键->添加至*****的回调函数);
相关信息按钮:
function Button_2Pushed(app, event)
message = sprintf(['课程名字:数学模型课程设计 n ' ...
'组别:第19组(Fibonacci数列比值极限分析&可视化设计)n'...
'作品风格:会夹带许多作者喜欢的二次元人物,说实话,这个课题真的挺无聊的']);
uialert(app.UIFigure,message,'课设简介',...
'Icon','info');
end
课程设计按钮:
function ButtonPushed(app, event)
delete(app.UIFigure);
run model_app2.mlapp;
end
退出程序(有一个确定是否退出的信息框):
function Button_3Pushed(app, event)
selection = uiconfirm(app.UIFigure,'确定退出吗?','退出提示',...
'Icon','warning');
switch selection
case 'OK'
delete(app.UIFigure);
case 'Cancel'
return;
end
end
第一个mlapp文件的设计便到此为止了,以鄙人愚见,封面主要作用有二:①传递基本信息 ②封面好看,吸引你过来看
接下来,我们便进入到第二个mlapp文件(model_app2.mlapp)的讲解:
内容设计
tab1——兔子问题基本假设及介绍
由于要呈现的内容一面放不下,所以鄙人选择了容器——选项卡组,对容器的灵活使用是做好课程设计的基本要求。分为四个板块,第一个板块里头没有回调函数,也即没有实现任何功能,只是起到介绍课程设计的作用而已。如下图所示,这里顺便安利一下个人比较喜爱的番剧,左边的兔子背景来自京阿尼的《玉子市场》,其剧场版《玉子爱情故事》是一部质量很高的纯爱番,鄙人已经看过3,4遍了。右下角是比较出名的《四月是你的谎言》,画风比较有特色,建议看两遍,第一遍是带着疑惑的看,第二遍是在知道何为谎言下去看,观感完全不同。
兔子问题可视化
第二个板块是可视化部分,先放图:
1.先继续安利一下番剧,这个比较重要。《龙与虎》是一部校园喜剧恋爱番,男主人设和女主的人设都很不错,男二就有点相对拉胯。经典老番,需要慢慢地看,不然会看得比较奇怪,因为会错过一些情感上的过渡,导致看得莫名其妙。
2.界面基本布局:运行时,先在app.totaldatEditField输入将要模拟的天数,然后按下app.startButton运行,app.UIAxes与app.UIAxes2将会同时工作,具体见后文描述。一次模拟完成后,可以按app.resetButton刷新两个坐标区的图像,本来这里还可以加一个保存图像,但我觉得没太大意思,就不这么设计了。这里虽然没有对操作进行信息引导,但我在设计中加入了防误触的考虑——将app.dayEditField,app.childEditFeild,app.adultEditField和app.-sumEditField设置为UnEditable(把交互性Editable一项打勾去掉)
3.实现“伪航拍”——从直观上体会数量的变化
代码实现:(app.startButton的回调函数)
function startButtonPushed(app, event)
app.videostart=true;
app.resetButton.Text="stop";
app.startButton.Enable=false;
totalday=str2double(app.totaldayEditField.Value);
x_old=[];
x_new=[];
y_old=[];
y_new=[];
hold(app.UIAxes2,"on");
axis(app.UIAxes2,[0 totalday 0 fibonacci(totalday)]);
xticks(app.UIAxes2,0:1:totalday);
grid(app.UIAxes2,"on");
hold(app.UIAxes,"on");
axis(app.UIAxes,[0 1 0 1]);
for i=1:totalday
if app.videostart
app.dayEditField.Value=int2str(i);
a=fibonacci(i-1);
b=fibonacci(i);
app.childEditField.Value=int2str(a);
app.adultEditField.Value=int2str(b);
app.sumEditField.Value=int2str(a+b);
if ~isempty(x_old)
scatter(app.UIAxes,x_old,y_old,8, "blue","filled");
end
scatter(app.UIAxes2,i,b,10,"blue","filled");
scatter(app.UIAxes2,i,a,10,"blue");
x_new=rand(b,1);
y_new=rand(b,1);
scatter(app.UIAxes,x_new,y_new,8,"blue");
x_old=x_new;
y_old=y_new;
pause(0.5);
end
end
app.resetButton.Text="reset";
end
4.代码亮点及讲解:
①设置了防误触装置,模拟开始后,直到结束或中止前,app.startButton的功能失效,即使点中了也不会产生实质效果。直到运行结束或中止后,start按钮才能重新正常使用。在代码中体现为:
function startButtonPushed(app, event)
app.resetButton.Text="stop";
•••
function resetButtonPushed(app, event)
app.startButton.Enable=true;
•••
②为了在运行中正确中止运行过程,引进了私有属性app.videostart,是一个逻辑变量。该逻辑变量之所以设置为私有属性,是因为方便于app.start-Button和app.resetButton同时对该变量拥有修改权。start的回调代码以天数作为循环条件,每次在循环之前,便会判断逻辑变量videostart的值,以判断是否继续操作。在代码中具体表现为:
function startButtonPushed(app, event)
app.videostart=true;
•••
for i=1:totalday
if app.videostart
•••
•••
end
function resetButtonPushed(app, event)
app.startButton.Enable=true;
app.videostart=false;
•••
end
③重置图像后(Reset),为了防止使用者忘记更改app.totaldayEditField而直接进行运行,从而导致Bug,每次Reset后将赋予app.totaldayEditField一个初始值。
function resetButtonPushed(app, event)
•••
app.childEditField.Value="1";
app.adultEditField.Value="0";
app.sumEditField.Value="1";
app.dayEditField.Value="0";
app.totaldayEditField.Value="10";
④代码会根据要生成的天数自动调整app.UIAxes2坐标区的坐标轴,以达到图像美观的效果。在代码中体现为(Matlab2020后的版本有自带的Fibona-cci函数,可以直接使用)(利用函数hold,axis,xticks,grid对图像进行个性化控制):
function startButtonPushed(app, event)
app.videostart=true;
•••
for i=1:totalday
if app.videostart
hold(app.UIAxes2,"on");
axis(app.UIAxes2,[0 totalday 0 fibonacci(totalday)]);
xticks(app.UIAxes2,0:1:totalday);
grid(app.UIAxes2,"on");
•••
end
⑤实心圆和空心圆的生成规则:在app.UIAxes坐标区上用空心圆表示幼兔,实心圆表示成年兔,幼兔经过一个月后成长为成兔。空心圆的生成利用了随机函数生成一个坐标值,定点表示在图像区域上。我们需要记录每一个月份下空心圆的位置,到了下一个月时,这些位置的点将有空心圆升级为实心圆。同时生成该月份下幼兔数量的空心圆。在代码中体现为(省去图像及文本框信息的显示):
function startButtonPushed(app, event)
•••
for i=1:totalday
if app.videostart
a=fibonacci(i-1);
b=fibonacci(i);
•••(文本框信息)
x_new=rand(b,1);
y_new=rand(b,1);
•••(画图)
x_old=x_new;
y_old=y_new;
pause(0.5);
end
end
•••
end
黄金螺旋线
第三个板块为0.618&&黄金螺旋线,先放图:
1.先安利一下番剧,最下角来自于《青春猪头少年不会梦见兔女郎学姐》的剧场版,把男主梓川咲太及翔子的线回收,巨好看。尽管双叶的量子力学我又双叒叕没听懂,但不影响观影体验。牧之原翔子的这句话也成为了我的一个努力方向:我的人生也绝没有什么远大的梦想或希望,但即便如此,我还是找到了自己的人生意义。咲太君,我呢,觉得人生是为了变得更善良而存在的。
2.界面基本布局:一共分为四个板块(Panel),最左边的版块是黄金螺旋线展示的速度控制及规格大小设置,同时附有开关和信号灯。中间的面板作为绘图区域,右上角列举了生活及自然界中一些黄金螺旋线。右下角,回归主题幼兔成兔比值系统.app.TextArea_13用于输入时间(繁殖了几个月),开关启动演示。
3.黄金螺旋线代码实现(app.Switch回调函数):
function SwitchValueChanged(app, event)
value = app.Switch.Value;
if(strcmp(value,"On"))
app.Switch.Enable=false;
upbound=str2num(app.scaleEditField.Value);
vector=app.vectorSlider.Value;
A=(sqrt(5)+1)/2;
x=0;
y=0;
app.Lamp.Color='r';
for n=1:upbound
k1=A^n;
k2=A^(n-1);
As=(k1-k2)*sin((n-1)*pi/2);
Ac=(k1-k2)*cos((n-1)*pi/2);
t=n*pi/2:pi/1024:n*pi/2+pi/2;
c=k1*cos(t);
s=k1*sin(t);
As=As*ones(1,1);
Ac=Ac*ones(1,1);
x=c+x+As;
y=s+y-Ac;
plot(app.UIAxes3,x,y,'LineWidth',2);
hold(app.UIAxes3,"on");
x=x-c;
y=y-s;
pause(0.12*vector);
end
hold(app.UIAxes3,"off");
app.Switch.Value='Off';
app.Lamp.Color='g';
app.vectorSlider.Value=3;
app.Switch.Enable=true;
end
end
代码亮点及讲解:
①若要演示的规模太大,时间会花比较久,为此,引进了速度控制的滑块。运行过程中,灯会变红。
function SwitchValueChanged(app, event)
value = app.Switch.Value;
if(strcmp(value,"On"))
•••
vector=app.vectorSlider.Value;
app.Lamp.Color='r';
for n=1:upbound
•••
pause(0.12*vector);
•••
end
②防误触系统:仍然利用Enable属性进行操作
③演示结束后复位:
hold(app.UIAxes3,"off");
app.Switch.Value='Off';
app.Lamp.Color='g';
app.vectorSlider.Value=3;
app.Switch.Enable=true;
4.右下角比值系统代码实现:没有什么新的操作,故直接给出
function Switch_2ValueChanged(app, event)
value=app.Switch_2.Value;
if(strcmp(value,"On"))
day=str2double(app.TextArea_13.Value);
hold(app.UIAxes4,"on");
axis(app.UIAxes4,[0 day 0 1]);
a_vector=[];
for i=0:day
a=fibonacci(i)/(fibonacci(i+1)+fibonacci(i));
a_vector=[a_vector a];
b=1-a;
scatter(app.UIAxes4,i,a,6,"red");
scatter(app.UIAxes4,i,b,6,"black");
end
plot(app.UIAxes4,0:day,a_vector,"red");
plot(app.UIAxes4,0:day,1-a_vector,"black");
else
app.TextArea_13.Value="10";
cla(app.UIAxes4,"reset");
end
end
end
Return功能实现
function returnTabButtonDown(app, event)
delete(app.UIFigure);
run model_app.mlapp;
end
写在最后
课程设计事小,几部番剧却是好番剧,强烈建议观看!!
最后
以上就是帅气蓝天为你收集整理的appdesigner课程设计——Fibonacci可视化课程简介题目要求设计及代码实现写在最后的全部内容,希望文章能够帮你解决appdesigner课程设计——Fibonacci可视化课程简介题目要求设计及代码实现写在最后所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复