📄 editlines.m
字号:
% get the anchor vector anchors=get(hanchors,'userdata'); % if provided, anchor information indicates which curves are editable and % what their anchors are. If provided, only curves whose handles are found in % this vector will be edited regardless of whether or not thay have anchors. % anchor vector is defined as: % [hcurve1 num_anchors_curve1 (x,y)s_of_curve1_anchors hcurve2 ... ] % obj=get(gcf,'currentobject'); hline=obj; if( ~strcmp('line',get(obj,'type')) ) % the user has clicked outside of all lines editlines('tempfini'); return; end % at this point we know the user has selected a line. If the line is % aleady selected, then we add a point or delete a point. If not, then % we change the line style and thickness to indicat that it has been % selected. % % delete any locate information that may be on stuff=get(gca,'userdata'); if( length(stuff)>6 ) htext=stuff(2,6); else htext=0; end if(htext) delete(htext); htext=0; stuff(2,6)=0; set(gca,'userdata',stuff); end newline=0; if(isempty(dat)) newline=1; elseif( dat(1)~= hline & dat(7)~= hline & dat(8)~=hline ) newline=1; end if( newline ) % we have selected a new line % see if this is an editable curve canedit=1; nanchors=0; if( length(anchors)>0 ) canedit=0; k=1; while(k<length(anchors) ) if( anchors(k) == hline ) canedit=1; nanchors=anchors(k+1); len=nanchors*2; line_anchors=anchors(k+2:k+1+len); break; else n=anchors(k+1); k=k+2+2*n; end end end if( ~canedit ) return; end if(~isempty(dat)) % reset the previous line delete(dat(7)); if(dat(8)) delete(dat(8)); end if(dat(2)==1) ls='-'; elseif(dat(2)==2) ls='--'; elseif(dat(2)==3) ls=':'; elseif(dat(2)==4) ls='-.'; elseif(dat(2)==5) ls='o'; elseif(dat(2)==6) ls='+'; elseif(dat(2)==7) ls='.'; elseif(dat(2)==8) ls='*'; elseif(dat(2)==9) ls='x'; end if (dat(2) < 5) set(dat(1),'linestyle',ls,'linewidth',dat(3),... 'color',dat(4:6),'erasemode','normal'); elseif (dat(2) >= 5) set(dat(1),'marker',ls,'linewidth',dat(3),... 'color',dat(4:6),'erasemode','normal'); end % store the anchor info ind=find( anchors==dat(1) ); la=dat(9:length(dat));%get the previous anchors na=length(la)/2;% number of prev anchors front=anchors(1:ind); back=anchors(ind+2+2*anchors(ind+1):length(anchors)); anchors=[front na la back]; set(hanchors,'userdata',anchors); end dat=zeros(1,8); dat(1)=hline; ls=get(hline,'linestyle'); if( strcmp(ls,'-')) ls=1; elseif(strcmp(ls,'--')) ls=2; elseif(strcmp(ls,':')) ls=3; elseif(strcmp(ls,'-.')) ls=4; elseif(strcmp(ls,'o')) ls=5; elseif(strcmp(ls,'+')) ls=6; elseif(strcmp(ls,'.')) ls=7; elseif(strcmp(ls,'*')) ls=8; elseif(strcmp(ls,'x')) ls=9; end dat(2) =ls; dat(3) =get(hline,'linewidth'); dat(4:6) =get(hline,'color'); % set the properties on the line set(hline,'erasemode','xor','color',[.5 .5 .5],'linewidth',.2,... 'linestyle','-'); x=get(hline,'xdata'); y=get(hline,'ydata'); npts=length(x); % see if it is a polygon (closed curve) ispoly=0; if( x(1)==x(npts) & y(1)==y(npts) & npts>1) ispoly=1; end % draw the points if(ispoly) dat(7)=line(x(2:npts),y(2:npts),'erasemode','xor','color',dat(4:6),... 'marker','o'); else dat(7)=line(x,y,'erasemode','xor','color',dat(4:6),... 'marker','o'); end % test the anchors for validity for k=1:nanchors ind=find( x==line_anchors(2*k-1) ); if( length(ind)>0 ) i2=find( y==line_anchors(2*k)); if(~isempty(i2)) valid_anchors=[valid_anchors ... line_anchors(2*k-1:2*k)]; end end end line_anchors=valid_anchors; nanchors=length(line_anchors)/2; % draw the anchors dat(8)=0; if( nanchors ) dat(8)=line(line_anchors(1:2:2*nanchors),line_anchors... (2:2:2*nanchors),'color',[1 0 0],... 'marker','o','markersize',12,'linestyle','none','erasemode','xor'); end % store the anchors dat=[dat line_anchors]; set(hstor,'userdata',dat); % if here then we are not selecting a new line (or we are in link mode) else % its an already defined line so we turn on the buttonup and motion % functions % get the selection type flag=get(gcf,'selectiontype'); % % button 1 assignments % % Note: linkmode has all buttons off except number 1. This allows % movement and link only. Note that the button1up function assigned % here only makes or breaks polygons. Linking of 1 curve to another % is only activated by the button1motion function which re-defines the % button1up function to editlines('link') % if( strcmp(flag,'normal') ) if(~linkmode & ~smoothmode) set(gcf,'windowbuttonupfcn','editlines(''button1up'')'); elseif( linkmode == -1) % normal linking does not use the poly option set(gcf,'windowbuttonupfcn','editlines(''linkpoly'')'); elseif( smoothmode ) set(gcf,'windowbuttonupfcn','editlines(''smooth'')'); end if( ~smoothmode ) set(gcf,'windowbuttonmotionfcn','editlines(''button1motion'')'); end % % button 2 assignments % elseif( strcmp(flag,'extend') ) %button if(~linkmode & ~smoothmode & ~nodelete) set(gcf,'windowbuttonupfcn','editlines(''button2up'')'); set(gcf,'windowbuttonmotionfcn',... 'editlines(''button2motion'')'); elseif( linkmode ) set(gcf,'windowbuttonupfcn','editlines(''autoseg'')'); set(gcf,'windowbuttonmotionfcn',''); end % % button 3 assignments % elseif( strcmp(flag,'alt') ) %button 3 if( ~smoothmode) set(gcf,'windowbuttonupfcn','editlines(''button3up'')'); set(gcf,'windowbuttonmotionfcn',... 'editlines(''button3motion'')'); %elseif( linkmode ) % set(gcf,'windowbuttonupfcn','editlines(''autoseg'')'); % set(gcf,'windowbuttonmotionfcn',''); elseif( smoothmode ) set(gcf,'windowbuttonupfcn','editlines(''smooth3'')'); set(gcf,'windowbuttonmotionfcn',''); end end % now get the current point and store it in user data pt=get(gca,'currentpoint'); pt=pt(1,1:2); % get the lines data and determine the index of the closest point % get the lines data x=get(dat(1),'xdata'); y=get(dat(1),'ydata'); npts=length(x); live=find(~isnan(x)); d=abs(x(live)-pt(1)) + abs(y(live)-pt(2)); it=find( d==min(d) ); it=live(it);% flags and parameters:% xonly ... if 1 then only x coordinate is changed% yonly ... if 1 then ony y coordinate is changed% killrd ... max distance to kill with a drag kill % set the kill radius at .2% of the xaxis length % xlim=get(gca,'xlim'); killrd=.002*abs(xlim(1)-xlim(2)); % see if it is a polygon (closed curve) ispoly=0; if( x(1)==x(npts) & y(1)==y(npts) ) ispoly=1; end stuff=[length(it) it hstor pt dat(1) dat(7:length(dat))]; % first row stuff=[stuff;zeros(2,length(stuff))]; stuff(2,1)=xonly; stuff(2,2)=yonly; stuff(2,3)=killrd; stuff(2,4)=ispoly; stuff(2,5)=locate; stuff(2,6)=htext; % reserved for text handle of locate display stuff(2,7)=dragmode; stuff(2,8)=linkmode; stuff(3,1)=fastopt; stuff(3,2)=singnan; stuff(3,3)=noadd; set(gca,'userdata',stuff); end % store the undo information % [npts x(1:npts) y(1:npts) dat] if(~linkmode) set(hundo,'userdata',[npts x y dat]); else if(newline) x2=get(hline,'xdata'); y2=get(hline,'ydata'); n2=length(x2); ustuff=[npts x y dat inf hline n2 x2 y2]; set(hundo,'userdata',ustuff); else set(hundo,'userdata',[npts x y dat]); end end return;endif( strcmp(action,'button1up') | strcmp(action,'button2up') ... | strcmp(action,'button3up') ) % turn off the window button functions set(gcf,'windowbuttonupfcn',''); set(gcf,'windowbuttonmotionfcn',''); % we are adding (or deleting) a point to the current line % or toggling the anchor status of a point % find the clicked point stuff=get(gca,'userdata'); lit=stuff(1,1); it=stuff(1,2:lit+1); hstor=stuff(1,lit+2); xpt=stuff(1,lit+3); ypt=stuff(1,lit+4); hline=stuff(1,lit+5); hline2=stuff(1,lit+6); hline3=stuff(1,lit+7); if( hline3 ) line_anchors=stuff(1,lit+8:length(stuff(1,:))); nanchors=length(line_anchors)/2; else nanchors=0; line_anchors=[]; end xonly=stuff(2,1); yonly=stuff(2,2); killrd=stuff(2,3); ispoly=stuff(2,4); noadd=stuff(3,3); % get the lines data x=get(hline,'xdata'); y=get(hline,'ydata'); npts=length(x); if( strcmp(action,'button1up') ) % add a point if(noadd) return; end % check to see if the point already exists dtest=abs(x(it)-xpt)+abs(y(it)-ypt); if( dtest<.5*killrd ) return; end % find all those points which surround xpt ind=surround(x,xpt); % now for each pair of surrounding points compute the perpendicular % distance from xpt,ypt to the line segment connecting the pair m=(y(ind+1)-y(ind))./(x(ind+1)-x(ind)); b=y(ind)-m.*x(ind); d=abs(m*xpt -ypt +b)./sqrt(m.*m+1); % find the minimum distance live = find(~isnan(d)); if(isempty(live)) editlines('tempfini'); return; end it=find(d(live)==min(d(live))); % the next lines are there to trap an apparent MATLAB bug. Occaisionally, it % seems possible to click outside all lines and still have the current object % be a line. This leads to the current circumstance where we are inserting a % point which is way off the line. The intended behavior is a temporary fini % so we do that if(min(d)>2*killrd) editlines('tempfini'); return; end % insert the point x=[x(1:ind(it)) xpt x(ind(it)+1:npts)]; y=[y(1:ind(it)) ypt y(ind(it)+1:npts)]; npts=length(x); elseif( strcmp(action,'button2up') ) % delete a point % make sure its not an anchor. To delete an anchor you must first free it if( nanchors ) ind=find( x(it)==line_anchors(1:2:2*nanchors) ); if( length(ind)> 0) ohoh = find(y(it)==line_anchors(2*ind)); if( length(ohoh) > 0) return; end end end %check for accidental deletion of a segment separator if( isnan(x(it)) | isnan(y(it)) ) return; end % check for deletion of polygon endpoint done=0; if( it(1)==1 | it(1)==npts ) % it might be an end point if( ispoly ) % see if it is a polygon x=[x(2:npts-1) x(2)]; y=[y(2:npts-1) y(2)]; npts=length(x); done=1; end end if( ~done) if( length(it)>1 ) error('click closer to the point to delete it'); end x=[x(1:it-1) x(it+1:npts)]; y=[y(1:it-1) y(it+1:npts)]; npts=length(x); end elseif( strcmp(action,'button3up') ) % toggle the points anchor status % see if its a polygon and we have selected an endpoint if(ispoly) if(it(1)==1 | it(1)==npts) it=1; % make sure only one of the endpoints is an anchor end end %check for accidental selection of a segment separator if( isnan(x(it)) | isnan(y(it)) ) return; end if( length(it)>1 ) it=it(1); end % see if it already is an anchor found=0; if( nanchors ) ind=find( x(it)==line_anchors(1:2:2*nanchors) ); if( length(ind)> 0) ooohh = find(y(it)==line_anchors(2*ind)); if( length(ooohh) > 0) % ok remove it from anchor status. % 2*ind(ooohh) points to the % ycoord of the selected anchor nanchors=nanchors-1; line_anchors=[line_anchors(1:2*ind(ooohh)-2)... line_anchors(2*ind(ooohh)+1:length(line_anchors))]; % remove any line anchors within .5*killrd of this one kmax=nanchors; nanchors=0; la=[]; for k=1:kmax xa=line_anchors(2*k-1); ya=line_anchors(2*k); d=sqrt( (xa-x(it))^2 + (ya-y(it))^2 ); if( d> killrd ) nanchors=nanchors+1; la=[la xa ya]; end end line_anchors=la; found=1; end end end if( ~found ) % make the point an anchor nanchors=nanchors+1; line_anchors=[line_anchors x(it) y(it)]; end % store the anchor information % the user data of hstor is: % dat(1) = handle of the selected line % dat(2) = original linestyle % dat(3) = original linewidth % dat(4:6) = original color % dat(7) = handle of duplicate line % dat(8) = handle of the anchor line % dat(9:length(dat)) = (x,y)'s of the anchors of the selected line dat=get(hstor,'userdata'); dat=[dat(1:8) line_anchors];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -