📄 mandelbrot.m
字号:
function mandelbrot(varargin)
% MANDELBROT Explore the Mandelbrot set.
% mandelbrot with no arguments starts with the full set.
%
% mandelbrot(center,width,grid,depth,cmapidx)
% center = Region center. Default -.5+0i.
% width = Region width. Default 3.
% grid = Grid size, usually 2^k or 3*2^k. Default 512.
% depth = Trace length. Default 256.
% cmapidx = Index into cell array of colormap functions, default 1.
%
% You can ...
% Use the mouse to zoom in on any region.
% Choose among several predefined regions.
% Increase the grid size or iteration depth.
% Change the color map.
% The "state" consists of
% center % Region center, complex scalar.
% width % Region width, flint scalar.
% grid % Grid size, flint scalar.
% depth % Trace length, flint scalar.
% cmapidx % Index into cell array of colormap functions, flint scalar.
% kz % Counts on the grid, (grid+1)-by-(grid+1) uint16 array.
% z % z values on the grid,(grid+1)-by-(grid+1) complex array.
% As the state is modified, it is saved between callbacks in the gcf user data.
cmaps = {@jets, @hots, @cmyk, @fringe};
grid = 0;
% Switchyard.
if nargin == 0 || isnumeric(varargin{1})
startup(varargin{:})
else
get_state
buttons = flipud(findobj(gcf,'type','uicontrol'));
job = varargin{1};
switch job(1:4)
case 'dept'
deepen
case 'grid'
refine
case 'colo'
colors
case 'exit'
close(gcf)
return
case 'regi'
region
otherwise
error('Argument not recognized')
end
end
state = {center,width,grid,depth,cmapidx,z,kz};
set(gcf,'userdata',state)
% ------------------------
function iterate(startdepth,finaldepth)
s = width*(-1/2:1/grid:1/2);
[u,v] = meshgrid(s+real(center),s+imag(center));
z0 = u + i*v;
if isreal(z)
z = complex(z);
end
for d = startdepth:finaldepth
if mod(d,32) == 0
set(buttons(1),'string',[num2str(d) '/' num2str(finaldepth)])
plotit;
end
[z,kz] = mandelbrot_step(z,kz,z0,d);
% mandelbrot_step is a c-mex file that does one step of:
% z = z.^2 + z0;
% kz(abs(z) < 2) = d;
end
depth = finaldepth;
set(buttons(1),'string',['depth = ' num2str(depth)])
drawnow
end
% ------------------------
function cmap = jets(cmaplen)
cycle = 16;
cmap = repmat(jet(cycle),ceil(cmaplen/cycle),1);
end
% ------------------------
function cmap = hots(cmaplen)
cycle = 16;
cmap = repmat(flipud(hot(cycle)),ceil(cmaplen/cycle),1);
end
% ------------------------
function cmap = cmyk(cmaplen)
% Blue, green, red, cyan, magenta, yellow, gray, black.
b = [0 0 3; 0 2 0; 3 0 0; 0 3 3; ...
3 0 3; 3 3 0; 1 1 1; 0 0 0]/4;
cycle = size(b,1);
cmap = repmat(b,ceil(cmaplen/cycle),1);
end
% ------------------------
function cmap = fringe(cmaplen)
cmap = zeros(min(cmaplen,256),3);
cmap(end,1) = .5;
cmap(1:12,:) = 1;
end
% ------------------------
function colors
% New color map
cmapidx = mod(cmapidx,length(cmaps))+1;
cx = char(cmaps{cmapidx});
set(buttons(3),'string',['color: ' cx(find(cx=='/')+1:end)],'value',0)
plotit
state = {center,width,grid,depth,cmapidx,z,kz};
set(gcf,'userdata',state)
end
% ------------------------
function startup(varargin)
% First entry
clf
shg
defaults = [-0.5+0i, 3, 512, 256, 1];
parms = defaults;
parms(1:nargin) = [varargin{:}];
center = parms(1);
width = parms(2);
grid = parms(3);
depth = parms(4);
cmapidx = parms(5);
kz = zeros(grid+1,grid+1,'uint16');
z = zeros(grid+1,grid+1);
set(gcf,'name','Mandelbrot')
buttons = make_buttons;
cx = char(cmaps{cmapidx});
set(buttons(3),'string',['color: ' cx(find(cx=='/')+1:end)],'value',0)
iterate(0,depth);
end
% ------------------------
function get_state
state = get(gcf,'userdata');
center = state{1};
width = state{2};
grid = state{3};
depth = state{4};
cmapidx = state{5};
z = state{6};
kz = state{7};
end
% ------------------------
function region
switch get(gcbo,'value');
case 1 % full
center = -.5+0i; width = 3;
grid = 512; depth = 256; cmapidx = 1;
case 2 % fringe
center = -.5+0i; width = 3;
grid = 512; depth = 256; cmapidx = 4;
case 3 % seahorses1
center = -0.7700-0.1300i; width = 0.10;
grid = 512; depth = 512; cmapidx = 1;
case 4 % seahorses2
center = -0.7799-0.1297i; width = 0.002;
grid = 512; depth = 512; cmapidx = 1;
case 5 % buzzsaw
center = 0.001643721971153+0.822467633298876i; width = 4.0e-11;
grid = 1024; depth = 2048; cmapidx = 2;
case 6 % west wing
center = -1.6735-0.0003318i; width = 1.5e-4;
grid = 1024; depth = 160; cmapidx = 1;
case 7 % geode
center = 0.28692299709-0.01218247138i; width = 6.0e-10;
grid = 2048; depth = 4096; cmapidx = 1;
case 8 % nebula
center = -0.737527770996094-0.128495483398438i; width = 4.8828125e-5;
grid = 1024; depth = 2048; cmapidx = 3;
case 9 % vortex1
center = -1.74975914513036646-0.00000000368513796i; width = 6.0e-12;
grid = 1024; depth = 2048; cmapidx = 2;
case 10 % vortex2
center = -1.74975914513271613-0.00000000368338015i; width = 3.75e-13;
grid = 1024; depth = 2048; cmapidx = 2;
case 11 % vortex3
center = -1.74975914513272790-0.00000000368338638i; width = 9.375e-14;
grid = 1024; depth = 2048; cmapidx = 2;
end
kz = zeros(grid+1,grid+1,'uint16');
z = zeros(grid+1,grid+1);
state = {center,width,grid,depth,cmapidx,z,kz};
set(gcf,'userdata',state)
cx = char(cmaps{cmapidx});
set(buttons(2),'string',['grid = ' num2str(grid)])
set(buttons(3),'string',['color: ' cx(find(cx=='/')+1:end)],'value',0)
iterate(0,depth);
end
% ------------------------
function plotit
s = width*(-1/2:1/grid:1/2);
if width > .002
pix = image(s+real(center),s+imag(center),kz);
set(get(gca,'title'),'userdata',0)
else
pix = image(s,s,kz);
g = ceil(-log10(width/2));
f = ['%' num2str(g+6) '.' num2str(g+4) 'f'];
if imag(center) < 0, s = ' - '; else s = ' + '; end
title(sprintf([f s f 'i'],real(center),abs(imag(center))));
set(get(gca,'title'),'userdata',center)
end
axis square
set(gca,'ydir','normal')
cmapfun = cmaps{cmapidx};
cmaplen = max(1,max(max(kz)));
colormap(cmapfun(cmaplen));
set(pix,'userdata',z)
drawnow
end
% ------------------------
function buttons = make_buttons
buttons = zeros(5,1);
bs = {'depth','grid','color','exit'};
for k = 1:4
buttons(k) = uicontrol('string',bs{k},'units','normal', ...
'position',[.86,.65-.08*k,.13,.06],'style','toggle', ...
'callback',['mandelbrot(''' bs{k} ''')']);
end
set(buttons(1),'string',['depth = ' num2str(depth)])
set(buttons(2),'string',['grid = ' num2str(grid)])
cx = char(cmaps{cmapidx});
set(buttons(3),'string',['color: ' cx(find(cx=='/')+1:end)])
set(buttons(4),'style','push')
regionlist = {'full','fringe','seahorses1','seahorses2','buzzsaw', ...
'west wing','geode','nebula','vortex1','vortex2','vortex3'};
buttons(5) = uicontrol('style','list','string',regionlist, ...
'units','normal','fontweight','bold', ...
'callback','mandelbrot(''regi'')');
ext = get(buttons(5),'extent');
set(buttons(5),'position',[.40,.02,.28,ext(4)]);
set(zoom,'enable','on','actionpostcallback',@zoomer)
end
% ------------------------
function deepen
pix = get(gca,'child');
kz = get(pix,'cdata');
z = get(pix,'userdata');
% Keep depth = 2^k or 3*2^k.
if rem(depth,3) == 0
finaldepth = 4*depth/3;
else
finaldepth = 3*depth/2;
end
set(buttons(1),'value',0,'callback',[])
iterate(depth,finaldepth);
set(buttons(1),'callback','mandelbrot(''depth'')')
end
% ------------------------
function refine
pix = get(gca,'child');
xlim = get(gca,'xlim');
ylim = get(gca,'ylim');
center = (xlim(1)+xlim(2))/2 + (ylim(1)+ylim(2))/2*i + ...
get(get(gca,'title'),'userdata');
x = get(pix,'xdata');
width = x(end)-x(1);
% Keep grid = 2^k or 3*2^k.
if rem(grid,3) == 0
grid = 4*grid/3;
else
grid = 3*grid/2;
end
set(buttons(2),'string',['grid = ' num2str(grid)],'value',0);
kz = zeros(grid+1,grid+1,'uint16');
z = zeros(grid+1,grid+1);
iterate(0,depth);
plotit;
end
% ------------------------
function zoomer(varargin)
set(zoom,'enable','on','actionpostcallback',@zoomoff)
get_state
buttons = flipud(findobj(gcf,'type','uicontrol'));
pix = get(gca,'child');
xlim = get(gca,'xlim');
ylim = get(gca,'ylim');
x = get(pix,'xdata');
y = get(pix,'ydata');
j = [find(abs(x-xlim(1)) == min(abs(x-xlim(1)))), ...
find(abs(x-xlim(2)) == min(abs(x-xlim(2))))];
k = [find(abs(y-ylim(1)) == min(abs(y-ylim(1)))), ...
find(abs(y-ylim(2)) == min(abs(y-ylim(2))))];
zoomgrid = 2.^(floor(log2(round(sqrt((k(2)-k(1))*(j(2)-j(1)))))));
j = round((sum(j)-zoomgrid)/2):round((sum(j)+zoomgrid)/2);
k = round((sum(k)-zoomgrid)/2):round((sum(k)+zoomgrid)/2);
width = (x(j(end))-x(j(1)) + y(k(end))-y(k(1)))/2;
axisshift = get(get(gca,'title'),'userdata');
center = (x(j(end))+x(j(1)))/2 + i*(y(k(end))+y(k(1)))/2 + axisshift;
kz = zeros(grid+1,grid+1,'uint16');
z = zeros(grid+1,grid+1);
iterate(0,depth);
plotit;
state = {center,width,grid,depth,cmapidx,z,kz};
set(gcf,'userdata',state)
set(buttons(2),'string',['grid = ' num2str(grid)])
set(zoom,'enable','on','actionpostcallback',@zoomer)
end
% ------------------------
function zoomoff
return
end
end % function mandelbrot
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -