找回密码
 注册
Simdroid-非首页
查看: 112|回复: 3

基于 GUI 的 Mandelbrot 分形图程序 (大家来讨论吧!)

[复制链接]
发表于 2013-5-1 02:34:57 | 显示全部楼层 |阅读模式 来自 上海
本帖最后由 RenLiujie 于 2013-5-2 05:17 编辑

最近在学习 MATLAB 的纯 m 语言的 GUI 设计,于是做了这么一个东西练练手。
东西很简单,实现的功能就是绘制逐渐放大的 Mandelbrot 分形图。
想法来自于《用Python做科学计算》,下面连接中对 Mandelbrot 分形图的意义和算法进行了详细介绍
http://hyry.dip.jp:8000/pydoc/fractal_chaos.html#mandelbrot

程序主要实现,鼠标点击图上某一点,则重绘一个以该点为中心的 局部放大图。我就是用来学习 Figure, axes 两个句柄的一些参数,鼠标事件和进度条这三样东西,所以 一个按钮什么的都没有(惭愧)。
界面大概就这样,要不是菜单栏可以保存图像比较简单,连菜单栏我都想省略。
这玩意儿,闲来无事东点点西点点,看看分形之美数学之奇倒是很不错哈哈。



当然这个程序可以有很多很多很多改进的地方,不同的逃逸半径,不同的迭代次数,还有算法上的细节对图像的影响;不同的 Colormap,显示复数区域坐标,... 都可以用各种控件来实现。还可以改用鼠标框选来放大图像,反正可以修改的太多了,看来要随着我慢慢学习慢慢改了... ^_^

代码如下,虽然用 MATLAB 很长一段时间,对一般的代码很熟悉;但是对于 GUI 编程我还只是刚刚接触,肯定代码有很多不合适的地方。尤其是变量之间的传递应该用什么方法,是设置 global 变量还是用函数参数的形式传递,或者还有什么其它方法我比较困惑。希望哪位大神能给个指导吧~

系统:WIN7 旗舰版 32bit
MATLAB 版本:Version 7.1.0.246(R14) Service Pack 3
  1. function Mandelbrot()
  2. close all;clear all;clc;
  3. % root 层面的 ---------------------------------------
  4. scsze = get(0,'screensize'); % 可用 screensize 属性获得屏幕的大小, 只读
  5. global FigureSize;
  6. FigureSize = 600;
  7. % ---------------------------------------
  8. % 在屏幕正中创建一个窗口
  9. position = [fix((scsze(3)-FigureSize)/2) fix((scsze(4)-FigureSize)/10) FigureSize FigureSize];
  10. global h_fig0;
  11. global h_fig0_axes1;
  12. global IMG;
  13. h_fig0 = figure('Position',position,... % 窗口位置
  14.     'Resize','off',... % 不可变换大小
  15.     'color',[1 1 1],... % 背景颜色
  16.     'MenuBar','figure',... % 菜单栏, 'none' or 'figure'
  17.     'toolBar','none',... % 工具栏,'none' or 'auto', MenuBar 为 'figure' 下有效
  18.     'visible','on',... % 设置可见
  19.     'NumberTitle','off',...% 标题上的 Figure X 的显示
  20.     'Name','Plot of Mandelbrot Set'...% 标题的 Name
  21.     );
  22. position2 = [0 0 FigureSize FigureSize];
  23. h_fig0_axes1_pos = [position2(1)/position(3),position2(2)/position(4),position2(3)/position(3),position2(4)/position(4) ];
  24. h_fig0_axes1 = axes('Parent',h_fig0,...
  25.     'Position',h_fig0_axes1_pos,...
  26.     'FontName','times',...
  27.     'FontAngle','italic',...
  28.     'FontSize',14,...
  29.     'XGrid','on',...
  30.     'YGrid','on',...
  31.     'XLimMode','manual',...
  32.     'YLimMode','manual',...
  33.     'XLim',[0,position2(3)],...
  34.     'YLim',[0,position2(4)],...
  35.     'visible','off');
  36. % 一些关于 Mandelbrot 集合的参数以及初始化
  37. global N; global M; global MAP; global R; global maxIter;
  38. global cx; global cy; global dx; global dy;
  39. initialize();
  40. plotMandelbrot(M,N,maxIter,R,cx,cy,dx,dy);
  41. set(h_fig0_axes1,'visible','on');

  42. end

  43. function IMG_click(src,event)
  44.     global N; global M; global MAP; global R; global maxIter;
  45.     global cx; global cy; global dx; global dy; global IMG;
  46.     global h_fig0;
  47.     global h_fig0_axes1;
  48.     h_fig0_pos = get(h_fig0,'Position');
  49.     h_fig0_axes1_pos = get(h_fig0_axes1,'Position');
  50.     point = get(h_fig0_axes1,'currentPoint');
  51.     current_x = point(1,1);
  52.     current_y = N - point(1,2);
  53.     cx = current_x/M*dx+cx-dx/2;
  54.     cy = current_y/N*dy+cy-dy/2;
  55.     dx = dx/5;
  56.     dy = dy/5;
  57.     plotMandelbrot(M,N,maxIter,R,cx,cy,dx,dy);
  58.     set(IMG,'ButtonDownFcn', @IMG_click);
  59. end

  60. % 初始化变量
  61. function initialize()
  62.     global N; global M; global MAP; global R; global maxIter;
  63.     global cx; global cy; global dx; global dy;
  64.     global FigureSize;
  65.     N = FigureSize; M = FigureSize;
  66.     MAP = zeros(N,M,3,'single');
  67.     R = 2;
  68.     maxIter = 255;
  69.     cx = -0.5;
  70.     cy = 0;
  71.     dx = 2.5;
  72.     dy = dx;
  73. end

  74. % 绘制 Mandelbrot 分形图形
  75. function plotMandelbrot(M,N,maxIter,R,cx,cy,dx,dy)
  76.     global IMG;
  77.     global MAP;
  78.     global h_fig0_axes1;
  79.     waitbar1 = waitbar(0);
  80.     for ix = 1:M
  81.         for iy = 1:N
  82.             c = cx-dx/2+dx/M*ix + i*(cy+dy/2-dy/N*iy);
  83.             z = 0;
  84.             for iter = 1: maxIter
  85.                 z = z*z + c;
  86.                 x = real(z); y = imag(z);
  87.                 if x^2+y^2 > R^2
  88.                     break;
  89.                 end
  90.             % 一种平滑算法,用于当 Itermax 较小时候
  91.             % z = z*z + c;z = z*z + c; iter = iter - log2(log2(abs(z)));
  92.             end
  93.             iter = floor(iter)+1;
  94.             MAP(iy,ix,:) = iter/maxIter;
  95.         end
  96.         if M/ix-floor(M/ix)==0 && M/ix < 10;
  97.             waitbar(2*ix/M-0.1,waitbar1)
  98.         end
  99.     end
  100.     delete(waitbar1);
  101.     IMG = imshow(MAP(:,:,1));colormap('HSV');
  102.     % 鼠标图形响应事件
  103.     set(IMG,'ButtonDownFcn', @IMG_click);
  104. end
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

点评

请lz说明自己电脑的系统及所采用的版本号,以利读者对照。 ps:我在XP上用7.0.0.19920 (R14)运行通不过;暂时只加防真币,待确定可运行,补加技术分  发表于 2013-5-1 16:43

评分

2

查看全部评分

发表于 2013-5-1 10:23:40 | 显示全部楼层 来自 上海
Simdroid开发平台
Good job.Mark.

点评

请勿灌水,下次扣分!  发表于 2013-5-1 16:44
回复 不支持

使用道具 举报

发表于 2013-5-3 22:26:22 | 显示全部楼层 来自 英国
我的机器上运行通过了,程序写的不错。

一点小建议:从编程习惯来讲,需要在函数间传递变量的时候建议使用guidata而不是global。
当然如果把GUI写成object oriented, 通过class -> properties来定义变量则更好。

评分

1

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2013-5-4 00:46:43 | 显示全部楼层 来自 上海
nwcwww 发表于 2013-5-3 22:26
我的机器上运行通过了,程序写的不错。

一点小建议:从编程习惯来讲,需要在函数间传递变量的时候建议使用 ...

谢谢。
写 gui 还是刚开始上手,您的建议很有帮助~
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-5-22 09:19 , Processed in 0.042606 second(s), 17 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表