📄 scgui.m
字号:
function out = scgui(varargin)
%SCGUI Create graphical user interface for the SC Toolbox.
% SCGUI creates the graphical user interface (GUI) for the
% Schwarz-Christoffel Toolbox in a new figure window.
%
% For complete details on the interface, see the user's guide.
% Copyright 1998-2002 by Toby Driscoll.
% $Id: scgui.m 262 2003-04-01 19:28:55Z driscoll $
% If called from the GUI, reroute to switchyard function cback
%%if nargin > 1
%% out = cback(guidata(gcbo),varargin{:});
%% return
%%end
% Create figure
fig = figure('name','Schwarz-Christoffel Mapping','numbertitle','off',...
'tag','scgui','menubar','none','vis','off');
set(fig,'defaultuicontrolinterrupt','on')
% Determine/set figure size
minsize = [95 36];
unit = get(0,'units');
set(0,'units','char')
ss = get(0,'screensize');
set(0,'units',unit)
optsize = 0.65*ss(3:4);
truesize = max(optsize,minsize);
set(fig,'unit','char','pos',[0 ss(4)-truesize(2)-8 truesize])
% can't figure out why this doesn't work right.
%% movegui(fig,'northeast')
% Custom resize function
% I have to disable this because at least in my window manager (KDE), the
% resizing is soooooooo slow as to be painful. But you can try it on
% your machine.
%%set(fig,'resizefcn',@resize,'deletefcn',@selfdelete)
set(fig,'resize','off')
% Create axes
ax(1) = axes('units','char','tag','PhysicalAxes');
ax(2) = axes('units','char','tag','CanonicalAxes');
set(ax,'next','add','box','on','plotboxaspectratio',[1 1 1])
% Create widgets and set sizes appropriately (subfunctions)
make_widgets(fig);
resize_widgets(fig)
drawnow
set(fig,'closerequestfcn',@scquit)
set(fig,'vis','on')
function draw(obj,varargin)
data = guidata(obj);
p = polyedit;
if ~isempty(p)
deletepoly(obj,'confirmed')
deletemap(obj)
addpoly(obj,p)
end
function domodify(obj,varargin)
data = guidata(obj);
p = data.polygon;
if isempty(p)
errordlg('You must first draw or import a polygon,','SC Error')
return
end
n = length(p);
p1 = polyedit(p);
% Was anything really changed?
changed = 0;
w = vertex(p);
w1 = vertex(p1);
if length(w1) ~= length(w)
changed = 1;
elseif norm(w(~isinf(w))-w1(~isinf(w1))) > 1000*eps
changed = 1;
end
if changed
deletepoly(obj,'confirmed')
addpoly(obj,p1)
% Ask about continuation.
set(findobj(data.SCfig,'tag','MeshLines'),'erase','norm','vis','off')
if data.iscurrent & length(w1)==length(w)
a = questdlg('Do you want to use continuation from the current parameter solution?','Map continuation','Yes','No','No');
else
a = 'No';
end
if strcmp(a,'No')
deletemap(obj)
else
deletemap(obj,'continue')
end
end
function edit(obj,varargin)
data = guidata(obj);
w = vertex(data.polygon);
if isempty(w), return, end
if any(isinf(w))
errordlg('Cannot edit vertices of unbounded polygons.','SC Error')
return
end
n = length(w);
% Call edit window
[flag,w] = scgedit('Edit vertices','Vertices:',w);
% If edit was accepted, try to convert it to a polygon.
if flag > 0
try
p = polygon(w);
catch
errordlg('Invalid polygon specified.','SC Error')
return
end
else
return
end
% We now assume the polygon was changed.
deletepoly(obj,'confirmed')
if length(w)~=n
% No way to be a continuation
deletemap(obj)
else
deletemap(obj,'continue')
end
addpoly(obj,polygon(w))
function solve(obj,varargin)
data = guidata(obj);
p = data.polygon;
if isempty(p)
errordlg('You must first draw or import a polygon.','SC Error')
return
end
mapnum = get(data.DomainPopup,'value');
maptype = data.mapclass{mapnum};
oldmap = data.map;
trace = 1;
%trace = get(data.TraceBox,'value');
tol = str2num(get(data.TolEdit,'string'));
if trace == 1
trace = 'on';
else
trace = 'off';
end
opt = scmapopt('Trace',trace,'Tol',tol);
if ~isempty(oldmap)
% Continuation
mapcmd = sprintf('map = %s(oldmap,p,opt);',maptype);
else
mapcmd = sprintf('map = %s(p,opt);',maptype);
end
try
eval(mapcmd)
catch
errordlg('Solution process failed!','SC Error')
return
end
deletemap(obj)
% Store new map
if ~isempty(map)
addmap(obj,map)
% Get the polygon back out of the map, because indexing and trivial
% vertices may change.
p = polygon(map);
deletepoly(obj,'confirmed')
addpoly(obj,p)
end
plotcanonical(obj)
setview(obj)
function plotcanonical(obj,varargin)
data = guidata(obj);
fig = data.SCfig;
if ~data.iscurrent, return, end
% Draw the canonical domain
axes(data.CanonicalAxes)
delete(findobj(gca,'tag','PolygonPlot'))
z = parameters(data.map);
z = z.prevertex;
switch class(data.map)
case { 'diskmap','extermap','crdiskmap' }
h = plot(exp(i*linspace(0,2*pi,100)),'linewid',1);
axis normal
axis equal
axis square
axis([-1.1 1.1 -1.1 1.1])
case 'hplmap'
xmin = min(z(~isinf(z)));
xmax = max(z(~isinf(z)));
xlim = [1.1*xmin-.1*xmax,1.1*xmax-.1*xmin];
h = plot(xlim,[0,0],'linewid',1);
axis normal
axis equal
axis square
axis([xlim,-.1,1])
case 'stripmap'
minx = min(real(z(~isinf(z))));
maxx = max(real(z(~isinf(z))));
d = (maxx-minx)/2;
m = (maxx+minx)/2;
h(1) = plot([m-1.2*d,m+1.2*d],[0,0],'linewid',1);
h(2) = plot([m-1.2*d,m+1.2*d],[1,1],'linewid',1);
axis normal
axis equal
axis([m-1.2*d,m+1.2*d,-.1,1.1])
case { 'rectmap','crrectmap' }
axis auto
h = plot(polygon(z));
axis equal
end
guidata(fig,data)
set(h,'tag','PolygonPlot')
h = plot(real(z),imag(z),'ko','markersize',5,'markerfacecolor','k');
set(h,'tag','PolygonPlot')
function recenter(obj,varargin)
data = guidata(obj);
fig = data.SCfig;
% Only applies to current disk maps
isdisk = any(strcmp(class(data.map),{'diskmap','crdiskmap'}));
if ~data.iscurrent
errordlg('You must first solve for the map parameters.','SC Error')
return
elseif ~isdisk
errordlg('The conformal center is defined only for disk maps.','SC Error')
return
end
ax(1) = data.PhysicalAxes;
ax(2) = data.CanonicalAxes;
% Show physical domain & turn off point mapping
set(findobj(ax(1)),'vis','on')
set(findobj(ax(2)),'vis','off')
set(ax,'buttondown','')
% Get point and do calculation
axes(ax(1))
title('Click at conformal center')
[xc,yc] = ginput(1);
title('')
data.map = center(data.map,xc+i*yc);
guidata(obj,data)
deletemap(obj)
addmap(obj,data.map)
plotcanonical(obj)
setview(obj)
function scdisplay(obj,varargin)
data = guidata(obj);
if ~data.iscurrent
errordlg('You must first solve for the map parameters.','SC Error')
else
str = char(data.map);
pos = [0 0 100 size(str,1)];
f = figure('unit','char','vis','off','integerhandle','off',...
'name','Map parameters','numbertitle','off','pos',pos);
u = uicontrol('style','text','unit','char',...
'pos',pos,'fontname','FixedWidth','horiz','left',...
'background','white','string',str);
set(f,'vis','on')
end
function meshplot(obj,varargin)
data = guidata(obj);
if ~data.iscurrent
errordlg('You must first solve for the map parameters.','SC Error')
return
end
ax(1) = data.PhysicalAxes;
ax(2) = data.CanonicalAxes;
% Parse mesh line widgets
xrhan = data.XREdit;
ythan = data.YTEdit;
xrstring = get(xrhan,'string');
ytstring = get(ythan,'string');
if strcmp(xrstring,'defaults') | strcmp(xrstring,'default')
xr = 10;
else
xr = str2num(xrstring);
end
if strcmp(ytstring,'defaults') | strcmp(ytstring,'default')
yt = 10;
else
yt = str2num(ytstring);
end
% Bring up physical domain and clear old mesh lines
%% set(findobj(ax(1)),'vis','on')
%% set(findobj(ax(2)),'vis','off')
ml = findobj(ax,'tag','MeshLines');
set(ml,'erase','normal')
delete(ml)
delete(findobj(ax(1),'tag','PolygonPlot'))
drawnow
% Exterior map: Allow axis autoscale
if strcmp(class(data.map),'extermap')
set(ax(1),'xlimmode','auto','ylimmode','auto')
end
% Do the plot
[h,xr,yt] = plot(data.map,xr,yt);
set(h,'erasemode','none','tag','MeshLines')
% Plotting routines plot their own copy of the polygon,
% without returning handles. This locates and (re)tags these lines.
hp = findobj(ax(1),'tag','PolygonSide');
set(hp,'tag','PolygonPlot','uicontext',data.PolygonContextMenu)
% Update mesh line widgets
if isempty(xr)
xrstring = '';
else
xrstring = ['[',sprintf('%.3g ',xr),']'];
end
isdisk = strcmp(class(data.map),'diskmap');
isdisk = isdisk | strcmp(class(data.map),'extermap');
if isempty(yt)
ytstring = '';
elseif isdisk
ytstring = ['pi*[',sprintf('%.3g ',yt/pi),']'];
else
ytstring = ['[',sprintf('%.3g ',yt),']'];
end
set(xrhan,'string',xrstring)
set(ythan,'string',ytstring)
% May want to fix up the canonical domain
axes(ax(2))
z = prevertex(data.map);
switch class(data.map)
case {'diskmap','extermap','crdiskmap'}
case 'hplmap'
zf = z(~isinf(z));
xlim = [min(zf);max(zf)];
xlim = [1.1 -.1; -.1 1.1] * xlim;
ylim = [0;max(zf)];
ylim = [0 0; -.1 1.1]*ylim;
axis([xlim',-0.05*ylim(2),ylim(2)])
case 'stripmap'
%% zf = z(~isinf(z));
%% xlim = [min(zf);max(zf)];
%% xlim = [1.1 -.1; -.1 1.1] * xlim;
%% axis([xlim',-.1,1.1])
case 'rectmap'
case 'crrectmap'
end
% Want to do this so that the buttondown of the mesh lines is set up.
setview(obj)
function images = mappts(pts)
domain = get(gca,'tag');
data = guidata(gcbo);
source = pts; % (given)
images = [];
if data.iscurrent
title('Mapping...')
drawnow
if ~isempty(source)
% Forward/inverse map, depending on plane in view
if strcmp(domain,'PhysicalAxes')
images = evalinv(data.map,source);
elseif strcmp(domain,'CanonicalAxes')
images = eval(data.map,source);
end
else
images = [];
end
title('')
drawnow
end
function addpt(varargin)
% Take no action unless it's a standard left-click. But DON'T just return,
% because that short-circuits context menu clicks.
if strcmp(get(gcf,'selectiontype'),'normal')
data = guidata(gcbo);
pt = get(gca,'currentpoint');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -