⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modpoly.m

📁 computation of conformal maps to polygonally bounded regions
💻 M
字号:
function [w,beta,indx] = modpoly(w,beta)
%MODPOLY Modify a polygon.
%   [WNEW,BETANEW] = MODPOLY(W,BETA) plots the polygon given by W and
%   BETA and allows the user to change it with the mouse.  At the start,
%   MODPOLY allows you to move vertices.  Move the cursor over a vertex
%   you want to move, hold down the left mouse button, drag it to its
%   new location, and release.  The vertex changes color and affected
%   sides become dashed as you move the vertex.
%   
%   To delete a vertex, press the Delete button.  The pointer will
%   change to a fleur.  After your next click and release, the selected
%   vertex will be deleted and you will return to movement mode.  To
%   cancel a requested deletion, press Delete again.
%   
%   The Add button works similarly.  To add, press the button and then
%   click and release on a polygon side.  A vertex will be added to the
%   middle of the side, the polygon is redrawn, and you return to
%   movement mode.
%   
%   Infinite vertices cannot be moved(!), deleted, or added.  When
%   moving the neighbor of an infinite vertex, the angle at infinity is
%   kept constant.  When you delete a neighbor of infinity, the turn at
%   the deleted vertex is lost and the angle at infinity changes.  You
%   cannot delete a vertex with two infinite neighbors.  When you add a
%   vertex to an infinite side, the new vertex appears at a "reasonable"
%   distance from its finite neighbor.
%   
%   [WNEW,BETANEW,IDX] = MODPOLY(W,BETA) also returns an index vector to
%   help keep track of additions and deletions.  IDX has the same length
%   as WNEW, and if IDX(J) is an integer, it gives the index that
%   WNEW(J) had in the original W.  If WNEW(J) was added, then IDX(J) is
%   NaN.
%   
%   Note: MODPOLY makes no attempt to keep the polygon "legal."  You can
%   easily create things which are not polygons, or change infinite
%   vertices into unrecognized finite ones.
%   
%   See also DRAWPOLY, PLOTPOLY.

%   Copyright 1998 by Toby Driscoll.
%   $Id: modpoly.m 74 1999-08-18 21:59:47Z tad $

global sc_hs sc_hv sc_k sc_w sc_beta sc_idx sc_color
n = length(sc_w); 

if nargin == 1 & isstr(w)
  % Pass through to callback
  cback(w);
  return
end

% Set up figure, axes, etc.
fig = gcf;
figure(fig);

% Save current properties to be restored
figprops = {'unit';'pos';'resizefcn';'pointer';'windowbuttondown';...
    'windowbuttonup';'pointer';'interruptible'};
figstate = get(fig,figprops);
axprops = {'unit';'pos';'xgrid';'ygrid';'interruptible'};
axstate = get(gca,axprops);

% Get figure position and screen size
set(fig,'unit','point')
figpos = get(fig,'pos');
unit = get(0,'unit');
set(0,'unit','point')
maxpos = get(0,'screensize');
set(0,'unit',unit)

% Draw polygon and initialize global vars
turn_off_hold = ~ishold;
n = length(w);
sc_w = w;				% global vertices
sc_beta = beta;			% global angles
cla
sc_hs = plotpoly(w,beta);			% side handles
% One side of a crack should be a different color.
crack = find(beta==1);
set(sc_hs(crack),'color',get(sc_hs(1),'color')/2)
hold on
sc_hv = repmat(NaN,n,1);			% vertex handles
for j=find(~isinf(w))'
  sc_hv(j) = plot(real(w(j)),imag(w(j)),'.','markersize',20);
end
set(sc_hv(rem(crack,n)+1),'color',get(sc_hv(1),'color')/2)
drawnow
axlim = axis;
sc_idx = (1:length(w))';		% indices
set(gcf,'pointer','circle')
set(gcf,'interruptible','off','busyaction','cancel')
set(gca,'interruptible','off','busyaction','cancel')

% Set up nice initial grid spacing
space = diff(axlim(1:2))/16;
space = min(0.5, ceil(space*2)/2);
axlim = round(axlim*2)/2;
axis normal
axis(axlim)

set(sc_hs,'erasemode','xor','buttondown','modpoly(''down'');')
set(sc_hv(ishandle(sc_hv)),'erasemode','xor','buttondown','modpoly(''down'');')
drawnow 

% Create uicontrols
[frame,control] = mp_make_widgets(fig);
mp_resize_widgets(fig);
set(fig,'resizefcn','modpoly(''resize'');')

%set(gcf,'windowbuttondown','modpoly(''down'');')

% Run in place until finished
uiwait(fig)

set(gcf,'windowbuttondown','')

% Recover new info and clean up
if get(findobj(gcf,'tag','mp_done'),'user') > 0
  w = sc_w;
  beta = sc_beta;
end
if turn_off_hold
  hold off
end
delete(control)
delete(frame)
delete(sc_hs)
delete(sc_hv(ishandle(sc_hv)))
set(gcf,figprops,figstate)
set(gca,axprops,axstate)

axis auto
plotpoly(w,beta)
indx = sc_idx;
clear global sc_hs sc_hv sc_k sc_w sc_beta sc_idx


function cback(action)

ptr = get(gcf,'pointer');
global sc_hs sc_hv sc_k sc_w sc_beta sc_idx
n = length(sc_w);
  
switch action
    
case 'down'				% button down
  h = get(gcf,'currentobj');
  % Act only if h is a line object
  if strcmp(get(h,'type'),'line')
    if ~strcmp(ptr,'crosshair')		% move or delete
      if strcmp(get(h,'marker'),'.')	% vertex?
	sc_k = find(h==sc_hv);
	colr = get(gca,'colororder');
	%set(h,'color',colr(2,:))
	set(sc_hs([sc_k,rem(sc_k-2+n,n)+1]),'linesty','--')
	if strcmp(ptr,'circle')
	  % Mouse movement needed only when moving vertices
	  set(gcf,'windowbuttonmotion','modpoly(''move'');')
	end
	set(gcf,'windowbuttonup','modpoly(''up'');')
      end
    else				% insert
      if strcmp(get(h,'linesty'),'-')	% edge?
	sc_k = find(h==sc_hs);
	set(sc_hs(sc_k),'linesty','--')
	set(gcf,'windowbuttonup','modpoly(''up'');')
      end	
    end
  end
  
  
case 'move'				% mouse move
  z = get(gca,'currentpoint');
  % Snap to grid if requested.
  if get(findobj(gcf,'tag','snap'),'value');
    grid = str2num(get(findobj(gcf,'tag','grid_space'),'string'))*[1 1];
    axlim = axis;
    minxy = axlim([1 3]);
    z(1,1:2) = minxy + grid.*(round((z(1,1:2)-minxy)./grid));
  end
  
  k = sc_k;
  set(sc_hv(k),'xd',z(1,1),'yd',z(1,2))
  
  % Must handle case of infinite predecessor/successor separately.
  j = rem(k,n)+1;			% successor
  if isinf(sc_w(j))
    xd = get(sc_hs(k),'xd');
    yd = get(sc_hs(k),'yd');
    phi = atan2(diff(yd),diff(xd));
    r = sqrt(diff(xd)^2+diff(yd)^2);
    y = sc_w(k) + [0,r*exp(i*phi)];
  else
    y = [z(1,1)+i*z(1,2),sc_w(j)];
    phi = angle(-diff(y)/diff(sc_w([j,k])));
    sc_beta(k) = sc_beta(k)-phi/pi;
    sc_beta(j) = sc_beta(j)+phi/pi;
  end
  set(sc_hs(k),'xd',real(y),'yd',imag(y))
  j = rem(k-2+n,n)+1;			% predecessor
  if isinf(sc_w(j))
    xd = get(sc_hs(j),'xd');
    yd = get(sc_hs(j),'yd');
    phi = atan2(-diff(yd),-diff(xd));
    r = sqrt(diff(xd)^2+diff(yd)^2);
    y = sc_w(k) + [r*exp(i*phi),0];
  else
    y = [sc_w(j),z(1,1)+i*z(1,2)];
    phi = angle(diff(y)/diff(sc_w([j,k])));
    sc_beta(k) = sc_beta(k)+phi/pi;
    sc_beta(j) = sc_beta(j)-phi/pi;
  end
  % Make change effective
  set(sc_hs(j),'xd',real(y),'yd',imag(y))
  drawnow
  sc_w(k) = z(1,1)+i*z(1,2);
  
case 'up'				% button up
  set(sc_hs([sc_k,rem(sc_k-2+n,n)+1]),'linesty','-')
  set(gcf,'windowbuttonup','')
  if strcmp(ptr,'circle')
    % Moved a vertex.  Just clean up.
    colr = get(gca,'colororder');
    set(sc_hv(sc_k),'color',colr(1,:))
    set(gcf,'windowbuttonmotion','')
  elseif strcmp(ptr,'fleur') 		% Delete...
	colr = get(gca,'colororder');
    set(sc_hv(sc_k),'color',colr(1,:))
    set(gcf,'pointer','circle')
    idx = rem(sc_k+(-2:1)+n-1,n)+1;	% 2 back, here, and 1 forward
    infb = isinf(sc_w(idx(2)));
    infa = isinf(sc_w(idx(4)));
    if n <= 3 | (infa & infb)
      return				% do nothing
    elseif ~infb & ~infa 
      % Finite neighborhs; easy.
      v = get(sc_hs(idx(1)),'xdata')+i*get(sc_hs(idx(1)),'ydata');
      v(3:4) = get(sc_hs(idx(4)),'xdata')+i*get(sc_hs(idx(4)),'ydata');
      b = scangle(v);
      sc_beta(idx([2,4])) = b(2:3);
      v = v(2:3);
    else
      % An infinite neighbor
      axlim = axis;
      r = sqrt(diff(axlim(1:2))^2+diff(axlim(3:4))^2);
      x = get(sc_hs(sc_k*infb + idx(2)*infa),'xdata');
      y = get(sc_hs(sc_k*infb + idx(2)*infa),'ydata');
      ang = atan2(diff(y),diff(x)) + (pi*infb);
      j = (idx(2)*infb) + (idx(4)*infa);
      sc_beta(j) = sc_beta(j) + sc_beta(sc_k);
      if infb
	v = sc_w(idx(4)) + [1.1*r*exp(i*ang),0];
      else
	v = sc_w(idx(2)) + [0,1.1*r*exp(i*ang)];
      end
    end
    
    set(sc_hs(idx(2)),...
	'xdata',real(v),'ydata',imag(v),'linesty','-')
    delete(sc_hv(sc_k))
    sc_hv(sc_k) = [];
    sc_w(sc_k) = [];
    delete(sc_hs(sc_k))
    sc_hs(sc_k) = [];
    sc_beta(sc_k) = [];
    sc_idx(sc_k) = [];
    
  elseif strcmp(ptr,'crosshair') 	% Add
    [wn,bn] = scaddvtx(sc_w,sc_beta,sc_k);
    sc_w = wn(:);
    sc_beta = bn(:);
    cla
    axlim = axis;
    sc_hs = plotpoly(wn,bn);
    axis(axlim)
    axis normal
    cback('snap');
    sc_hv = repmat(NaN,n+1,1);
    for j=find(~isinf(wn))'
      sc_hv(j) = plot(real(wn(j)),imag(wn(j)),'.','markersize',20);
    end
    set(sc_hs,'erasemode','xor','buttondown','modpoly(''down'');')
    set(sc_hv(ishandle(sc_hv)),'erasemode','xor',...
	'buttondown','modpoly(''down'');')
    drawnow 
    sc_idx = [sc_idx(1:sc_k);NaN;sc_idx(sc_k+1:n)];
    set(gcf,'pointer','circle')
    
  end
  
  
case 'delete'		 		% toggle delete state
  if ~strcmp(ptr,'fleur')
    set(gcf,'pointer','fleur')
  else
    set(gcf,'pointer','circle')
  end
  
  
case 'add'				% toggle add state
  if ~strcmp(ptr,'crosshair')
    set(gcf,'pointer','crosshair')
  else
    set(gcf,'pointer','circle')
  end
  
  
case 'done'
  set(findobj(gcf,'tag','mp_done'),'user',1)
  drawnow
  uiresume(gcf)
  
case 'cancel'
  set(findobj(gcf,'tag','mp_done'),'user',-1)
  drawnow
  uiresume(gcf)
  
case 'snap'
  fig = gcf;
  snap = findobj(fig,'tag','snap');
  if get(snap,'value')
    space = str2num(get(findobj(fig,'tag','grid_space'),'string'));
    axlim = axis;
    x = axlim(1):space:axlim(2);
    y = axlim(3):space:axlim(4);
    set(gca,'xticklabelmode','auto','yticklabelmode','auto')
    set(gca,'xtick',x,'ytick',y)
    % For clarity, keep only about eight of the labels.
    N = length(x);
    keep = [1,3:ceil((N-1)/8):N-2,N];
    xl = get(gca,'xticklabel');
    p = min(size(xl,2),4);
    xlnew = setstr(ones(N+1,1)*blanks(p));
    xlnew(keep,:) = xl(keep,1:p);
    N = length(y);
    keep = [1,3:ceil((N-1)/8):N-2,N];
    yl = get(gca,'yticklabel');
    p = min(size(yl,2),4);
    ylnew = setstr(ones(N+1,1)*blanks(p));
    ylnew(keep,:) = yl(keep,1:p);
    % Make it so.
    set(gca,'xticklabel',xlnew,'yticklabel',ylnew)
    set(gca,'xgrid','on','ygrid','on')
  else
    set(gca,'xtickmode','auto','xticklabelmode','auto','xgrid','off')
    set(gca,'ytickmode','auto','yticklabelmode','auto','ygrid','off')
  end    
  drawnow    
  
  
case 'xlim'
  xlim = str2num(get(findobj(gcf,'tag','xlimits'),'string'));
  set(gca,'xlim',xlim)
  cback('snap');
  
  
case 'ylim'
  ylim = str2num(get(findobj(gcf,'tag','ylimits'),'string'));
  set(gca,'ylim',ylim)
  cback('snap');
  
case 'resize'
  mp_resize_widgets(gcbo);
  
end


function [frame,widget] = mp_make_widgets(fig)
bgcolor = .7*[1 1 1];
set(fig,'defaultuicontrolbackground',bgcolor,'defaultuicontrolunits','point')

% Create uicontrol frames
frame(1) = uicontrol('style','frame','tag','mp_settings');
frame(2) = uicontrol('style','frame','tag','mp_actions');

axlim = axis;
space = 0.5;

widget(1) = uicontrol('style','check',...
    'string','Snap to grid',...
    'call','modpoly(''snap'');',...
    'hor','c',...
    'tag','snap');
widget(2) = uicontrol('style','text',...
    'string','Grid spacing:',...
    'hor','l');
widget(3) = uicontrol('style','edit',...
    'string',sprintf('%.3g',space),...
    'call','modpoly(''snap'');',...
    'tag','grid_space');

widget(4) = uicontrol('style','text',...
    'string','x limits:',...
    'hor','r');
widget(5) = uicontrol('style','edit',...
    'string',sprintf('[%.3g %.3g]',axlim(1:2)),...
    'hor','l',...
    'tag','xlimits',...
    'call','modpoly(''xlim'');');
widget(6) = uicontrol('style','text',...
    'string','y limits:',...
    'hor','r');
widget(7) = uicontrol('style','edit',...
    'string',sprintf('[%.3g %.3g]',axlim(3:4)),...
    'hor','l',...
    'tag','ylimits',...
    'call','modpoly(''ylim'');');

widget(8) = uicontrol('style','push',...
    'string','Add',...
    'call','modpoly(''add'');');
widget(9) = uicontrol('style','push',...
    'string','Delete',...
    'call','modpoly(''delete'');');
widget(10) = uicontrol('style','push',...
    'string','Done',...
    'call','modpoly(''done'');',...
    'tag','mp_done');
widget(11) = uicontrol('style','push',...
    'string','Cancel',...
    'call','modpoly(''cancel'');');

set(widget(10),'user',0)
set(frame(1),'userdata',widget(1:7))
set(frame(2),'userdata',widget(8:11))

function mp_resize_widgets(fig)

figpos = get(fig,'pos');

% Frames
f(1) = findobj(fig,'tag','mp_settings');
f(2) = findobj(fig,'tag','mp_actions');

% Minimum sizes
figpos(3) = max(figpos(3),376);
figpos(4) = max(figpos(4),170);

set(fig,'pos',figpos)
set(f,{'pos'},{[0 0 figpos(3) 72];[figpos(3)-80 72 80 figpos(4)-72]})

% Axes
% Axes area needs a border of at least 24 pt on each side
usable = figpos(3:4) - [80 72];
size = min(usable - 48);
margin = (usable - size)/2 + [0 72];
set(gca,'unit','point','pos',[margin(1:2) size size])

% Settings
h = get(f(1),'userdata');
pos = {
[4 48 100 20];...
[4 28 60 14];...
[62 26 40 18];...
[120 50 48 14];...
[172 49 54 18];...
[120 28 48 14];...
[172 27 54 18]
};
set(h,{'pos'},pos)

% Actions
offset = [figpos(3)-76 figpos(4)-94 0 0];
h = get(f(2),'userdata');
pos = {
[0 72 72 18]+offset;...
[0 52 72 18]+offset;...
[0 20 72 18]+offset;...
[0  0 72 18]+offset
};
set(h,{'pos'},pos)

drawnow

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -