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

📄 polyedit.m

📁 computation of conformal maps to polygonally bounded regions
💻 M
📖 第 1 页 / 共 3 页
字号:
function p = polyedit(varargin)
%POLYEDIT Polygon editor.
%   P = POLYEDIT opens a window and runs the Polygon Editor. This editor
%   allows you to draw and modify a polygon using mouse input. 
%   
%   The editor has 4 main mutually exclusive modes:
%      ADD:    Add vertices in sequence by clicking the left mouse
%              button. If you hold the button down, a dashed line will
%              preview the new edge until you release. The last vertex
%              in sequence is always colored red for reference. Infinite
%              vertices may be added by clicking twice outside the axes
%              box (to indicate exit and reentry directions).
%      MOVE:   Move a vertex by clicking and dragging to a new
%              location. Only finite vertices may be moved, and they
%              must stay within the axes box. 
%      INSERT: Insert a trivial vertex by clicking on an existing
%              side. You may insert onto any side, including an infinite
%              one. 
%      DELETE: Delete a vertex by clicking on it. You may delete only
%              finite vertices. Deleting a vertex with an infinite
%              neighbor changes the angle at infinity.
%              
%   To close a polygon, draw the final side by clicking on the first
%   vertex in ADD mode or by using the appropriate pushbutton. Once a
%   polygon is closed, it remains so; adding in sequence is no longer
%   possible. You may continue to move, insert, and delete
%   vertices. When you are ready to exit, click on "OK" and the final
%   edition of your polygon will be returned in the variable P. 
%   
%   The controls on the right panel of the window allow you to constrain
%   the vertices to a grid or to discretize the allowable angles and/or
%   lengths. 
%   
%   Q = POLYEDIT(P) starts the editor with the given polygon P loaded.
%   
%   POLYEDIT(H), where H is the handle of a figure, runs the editor in
%   the given figure window. This allows you, for example, to "trace"
%   graphics you already have displayed. To do this, make sure you enter
%   HOLD ON before running POLYEDIT.
%   
%   See also the POLYGON class.

%   Copyright 2001 by Toby Driscoll.
%   $Id: polyedit.m 259 2003-04-01 16:39:46Z driscoll $

fig = [];
poly = [];

for j=1:nargin
  arg = varargin{j};
  if ishandle(arg) & strcmp(get(arg,'type'),'figure')
    fig = arg;
  elseif isa(arg,'polygon')
    poly = arg;
  end
end

if isempty(fig) 
  % Open a new figure.
  fig = figure('vis','off');
  figstate = [];
  axlim = [-4 4 -4 4];
  % Make a reasonable initial size.
  un = get(0,'unit');
  set(0,'unit','char')
  ss = get(0,'screensize');
  set(0,'unit',un)
  siz = max( 0.65*ss(3:4), [95 36] );
  set(fig,'unit','char','pos',[ss(3:4)-siz-[8 4] siz])
  set(fig,'closereq',@PEQuit)
else
  % Save current state.
  turn_off_hold = ~ishold;
  figprops = {'unit';'pos';'resizefcn';'pointer';'windowbuttondown';...
	'windowbuttonup';'pointer';'menubar';'name';'numbertitle'};
  figstate = get(fig,figprops);
  axprops = {'unit';'pos';'xgrid';'ygrid'};
  axstate = get(gca,axprops);

  % Set up.
  if ~ishold
    cla
    axis auto
  end
  % Reset axes limits?
  if strcmp(get(gca,'xlimmode'),'auto') & strcmp(get(gca,'ylimmode'),'auto')
    axlim = [-4 4 -4 4];
  else
    axlim = axis;
  end
end

% Set up controls
PE_make_widgets(fig,axlim);
PE_resize_widgets(fig);
data = guidata(fig);

% Initialize with the given polygon, if any.
if ~isempty(poly)
  w = vertex(poly);
  data.polyvertex = w;
  data.polybeta = angle(poly) - 1;
  data.isclosed = 1;
  data.atinf = zeros(length(w),2);
  data.atinf(isinf(w),:) = 1;
  data.atinf = data.atinf(:);
  data.Edges = plot(poly);
  hold on
  x = get(data.Edges,'xdata');
  y = get(data.Edges,'ydata');
  for j = 1:length(w)
    data.Vertices(j) = plot(real(w(j)),imag(w(j)),'bo',...
	'markerfacecolor','b');
    if isinf(w(j))
      set(data.Vertices,'user',[ x{j} y{j} ])
    else
      set(data.Vertices,'user',[ x{j}(1) y{j}(1) ] )
    end
  end
  data.addmode = 'normal';
  guidata(fig,data)
  set(data.AddButton,'enable','off')
  set(data.MoveButton,'value',1)
  set(data.FinishButton,'enable','off')
  set(data.AcceptButton,'enable','on')
  PEMoveMode(fig)
else
  set(data.AddButton,'value',1)
  PEAddMode(fig)
end

% Let it run (modally, since it has an output value).
set(fig, 'pointer','crosshair','menubar','none',...
    'name','Polygon Editor','numbertitle','off','resizefcn',@PE_resize_widgets)
hold on
set(fig,'vis','on')
try
  uiwait(fig)
  % Retrieve the polygon and assign to output if nonempty.
  data = guidata(fig);
  P = data.polygon;
  if ~isempty(P) | nargout > 0
    p = P;
  end
catch
  errordlg({'Unexpected termination. Last message:',lasterr},...
      'PolyEdit error')
  P = [];
end
  
% Clean up the mess.
if isempty(figstate)
  % This was a new figure.
  delete(fig)
else
  set(fig,figprops,figstate)
  set(gca,axprops,axstate)
  set(data.Vertices,'erasemode','normal')
  set(data.Edges,'erasemode','normal')
  PEClear(fig)
  % This could be destructive in some cases.
  delete(findobj(fig,'type','uicontrol'))
  delete(data.PreviewLine)
  if turn_off_hold
    hold off
  end
  plot(p)
  set(gca,'xtickmode','auto','ytickmode','auto')
  set(gca,'xticklabelmode','auto','yticklabelmode','auto')
end


% Callback functions.

function PEAddMode(obj,varargin)
data = guidata(obj);
% Can't turn this button off by pushing on it.
if get(data.AddButton,'value')==0
  set(data.AddButton,'value',1)
  return
end
data.mode = 'Add';
guidata(obj,data)

set(data.InsertButton,'value',0)
set(data.MoveButton,'value',0)
set(data.DeleteButton,'value',0)

set(data.SnapToggle,'enable','on')
set(data.DiscAngToggle,'enable','on')
set(data.DiscLenToggle,'enable','on')
PESnapMode(obj)
PEDiscAngMode(obj)
PEDiscLenMode(obj)

set(data.Figure,'windowbuttondown',@PEAddStart)
set(data.Vertices,'button','','hittest','off','erase','norm')
set(data.Edges,'button','','hittest','off')


function PEInsertMode(obj,varargin)
data = guidata(obj);
% Can't turn this button off by pushing on it.
if get(data.InsertButton,'value')==0
  set(data.InsertButton,'value',1)
  return
end
data.mode = 'Insert';
guidata(obj,data)

set(data.AddButton,'value',0)
set(data.MoveButton,'value',0)
set(data.DeleteButton,'value',0)

set(data.SnapToggle,'enable','off')
set(data.DiscAngToggle,'enable','off')
set(data.DiscLenToggle,'enable','off')
PESnapMode(obj)
PEDiscAngMode(obj)
PEDiscLenMode(obj)

set(data.Figure,'windowbuttondown','')
set(data.Vertices,'button','','hittest','off','erase','norm')
set(data.Edges,'button',@PEInsert,'hittest','on')


function PEMoveMode(obj,varargin)
data = guidata(obj);
% Can't turn this button off by pushing on it.
if get(data.MoveButton,'value')==0
  set(data.MoveButton,'value',1)
  return
end
data.mode = 'Move';
guidata(obj,data)

set(data.AddButton,'value',0)
set(data.InsertButton,'value',0)
set(data.DeleteButton,'value',0)

set(data.SnapToggle,'enable','on')
set(data.DiscAngToggle,'enable','off')
set(data.DiscLenToggle,'enable','off')
PESnapMode(obj)
PEDiscAngMode(obj)
PEDiscLenMode(obj)

set(data.Figure,'windowbuttondown','')
set(data.Vertices,'button',@PEMoveStart,'hittest','on','erase','norm')
set(data.Edges,'button','','hittest','off')


function PEDeleteMode(obj,varargin)
data = guidata(obj);
% Can't turn this button off by pushing on it.
if get(data.DeleteButton,'value')==0
  set(data.DeleteButton,'value',1)
  return
end
data.mode = 'Delete';
guidata(obj,data)

set(data.AddButton,'value',0)
set(data.InsertButton,'value',0)
set(data.MoveButton,'value',0)

set(data.SnapToggle,'enable','off')
set(data.DiscAngToggle,'enable','off')
set(data.DiscLenToggle,'enable','off')
PESnapMode(obj)
PEDiscAngMode(obj)
PEDiscLenMode(obj)

set(data.Figure,'windowbuttondown','')
set(data.Vertices,'button',@PEDelete,'hittest','on')
set(data.Edges,'button','','hittest','off')


function PESnapMode(obj,varargin)
% What to do if snap mode is enabled/disabled.
data = guidata(obj);
if get(data.SnapToggle,'value') & strcmp(get(data.SnapToggle,'enable'),'on')
  % Turns off discretization modes.
  set(data.DiscAngToggle,'value',0)
  set(data.DiscLenToggle,'value',0)
  space = str2num(get(data.GridSpaceEdit,'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    

function PEDiscAngMode(obj,varargin)
data = guidata(obj);
if get(data.DiscAngToggle,'value') & ...
      strcmp(get(data.DiscAngToggle,'enable'),'on')
  set(data.SnapToggle,'value',0)
  PESnapMode(obj)
end

function PEDiscLenMode(obj,varargin)
data = guidata(obj);
if get(data.DiscLenToggle,'value') & ...
      strcmp(get(data.DiscLenToggle,'enable'),'on')
  set(data.SnapToggle,'value',0)
  PESnapMode(obj)
end

function PEAddStart(obj,varargin)
data = guidata(obj);
%%set(data.PreviewLine,'vis','on')
set(data.Figure,'windowbuttonmotion',@PEAddMove)
set(data.Figure,'windowbuttonup',@PEAddFinish)
PEAddMove(obj)

function PEAddMove(obj,varargin)
data = guidata(obj);
ptrpos = get(data.Axes,'currentpoint');
P = ptrpos(1,1:2);
axlim = axis;
pts = PE_get_clicks(data);
%%x = get(data.Vertices,'xdata');
%%y = get(data.Vertices,'ydata');
%%pts = [x(:),y(:)];
m = size(pts,1);

grid = str2num(get(data.GridSpaceEdit,'string'));
grid = grid * get(data.SnapToggle,'value');
qang = 1/str2num(get(data.AngQuantEdit,'string'));
qang = qang * get(data.DiscAngToggle,'value');
qlen = str2num(get(data.LenQuantEdit,'string'));
qlen = qlen * get(data.DiscLenToggle,'value');

switch data.addmode
  case 'normal'
    mode = 0;
  case 'first'
    % Point may not be outside axes box.
    P(1) = min(max(P(1),axlim(1)),axlim(2));
    P(2) = min(max(P(2),axlim(3)),axlim(4));
    mode = 0;
  case 'infinite'
    % Point may not be inside axes box.
    if all(P>axlim([1,3])) & all(P<axlim([2,4]))
      [junk,j] = min(abs([P(1)-axlim(1:2);P(2)-axlim(3:4)]'));
      P = axlim(j);
    end
    mode = 1;

⌨️ 快捷键说明

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