appdesigner课程设计——Fibonacci可视化

课程简介

作为数学系学生,数学模型这门课对于我们来说真的是又爱又恨。作为一门数学课,基础原理是十分重要的,但囿于学生水平不足,很多细节往往是一带而过,老师一笑置之。到了期末是最好笑,这里请允许我吐槽几句,翻开书吧,又发现里面很多代码没有自己动手过,打开了电脑吧,又发现都期末了,现在来跑跑代码也不大有用。高姿态上了一学期的水课,心想着:就这······不会有人过不了吧。巧了,我有一同学也这么想,结果还真挂科了,这还是他读这么久以来第一次挂科。废话不多说,我们来看看课程设计是个什么牛马玩意。

题目要求

我抽到的题目其实很无聊☕,如下:
Fibonacci数列的比值极限分析及可视化设计
(1)参考课本章节10.2和幻灯片7.2内容,介绍差分方程的基本知识及Fibonacci数列相关理论;
(2)请基于 Matlab APP Designer 设计 Fibonacci 数列的比值极限系统。
是不是人就傻了,这玩意有啥好写的。硬要写的话,只能联想一下这个问题的著名起源——兔子问题:在神奇的印度大陆,兔子长盛不衰,神奇的幼兔一个月就一定会成长为成兔,而我们神奇的成兔一个月必生一对幼兔,成兔为了保持自己kpi,这个过程每个月都如此反复,乐此不疲。说到 Fibonacci,更为常人所知的还有黄金分割——0.618,这个数字正是在 n ( n → ∞ ) n(n\rightarrow\infty) 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

写在最后

课程设计事小,几部番剧却是好番剧,强烈建议观看!!

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值