function getfigure65 % This function adds a new menu option to copy the contents of a figure (axes, % lines, or even the whole figure) into the current figure % % first call adds the menu, second call deletes it % 03-2024: E. Clotet & J. Palacín % http://robotica.udl.cat Version = 6.5; % April-2024 hmenu = findobj(gcf,'Tag','getfigure'); if (isempty(hmenu)) % Initialize menu options h_get = uimenu(gcf,'label','Getfigure','Tag','getfigure'); uimenu(h_get,'Label','Select a Figure and replicate figure size and Axis position','TAG','GET','enable','off'); uimenu(h_get,'Label','Select a Figure and replicate tex font size','TAG','GET','enable','off'); uimenu(h_get,'label','Get a copy of a Figure','callback',{@copy, 'Figure', 'Original'},'TAG','GET','separator','on'); uimenu(h_get,'label','Get a copy of a Figure (replicating Figure size)','callback',{@copy, 'Figure', 'Exact'},'TAG','GET'); uimenu(h_get,'label','Get a copy of a specific Axis','callback',{@copy, 'Axes', 'Resize'},'TAG','GET','separator','on'); uimenu(h_get,'label','Get a copy of a specific Axis (replicating Axis size)','callback',{@copy, 'Axes', 'Original'},'TAG','GET'); %uimenu(h_get,'label','Copy all the content of a specific Axes (and keep its original size)','separator','on','callback',{@copy,'Axes','OriginalFigure'},'TAG','GET'); uimenu(h_get,'label','Copy all the content of a specific Axis','separator','on','callback',{@merge,'NoResize'},'TAG','GET'); uimenu(h_get,'label','Copy all the content of a specific Axis (replicating Figure and Axis size)','callback',{@merge,'ResizeFigAndAx'},'TAG','GET'); uimenu(h_get,'label','Copy one bitmap as Axis background','separator','on','callback',{@copybitmap, 1},'TAG','GET'); uimenu(h_get,'label','Copy one bitmap as Axis background (scale image)','callback',{@copybitmap, 0},'TAG','GET'); uimenu(h_get,'label','Copy one Line','separator','on','callback',{@copy, 'Line','Original'},'TAG','GET'); uimenu(h_get,'label','Copy one Line (subsampled)','callback',{@copy, 'Line','Subsampled'},'TAG','GET'); uimenu(h_get,'label','Copy one Line (oversampled)','callback',{@copy, 'Line','Oversampled'},'TAG','GET'); uimenu(h_get,'Label','Copy all objects with the same ''Tag''','TAG','GET','enable','off'); undoButton = uimenu(h_get,'label','Undo last Get','callback',@undo_copy,'separator','on','enable','off','TAG','GET'); draggMenu = uimenu(h_get,'label','Add draggable objects...','TAG','GET','separator','on'); uimenu(draggMenu,'label','Add a draggable distance tool','callback','gca;imdistline;'); uimenu(draggMenu,'label','Add a draggable point','callback','gca;impoint;','separator','on'); uimenu(draggMenu,'label','Add a draggable line','callback','gca;imline;'); uimenu(draggMenu,'label','Add a draggable rectangle','callback','gca;imrect;'); uimenu(draggMenu,'label','Add a draggable ellipse','callback','gca;imellipse;'); uimenu(draggMenu,'label','Add a draggable polygon region','callback','gca;impoly;'); uimenu(draggMenu,'label','Add a draggable freehand region','callback','gca;imfreehand;'); uimenu(draggMenu,'label','Delete all draggable distance tools and lines','callback','delete(findobj(gca,''Tag'',''imline''));','separator','on'); uimenu(draggMenu,'label','Delete all draggable points','callback','delete(findobj(gca,''Tag'',''impoint''));'); uimenu(draggMenu,'label','Delete all draggable rectangles and ellipses','callback','delete(findobj(gca,''Tag'',''imrect''));'); uimenu(draggMenu,'label','Delete all draggable polygons','callback','delete(findobj(gca,''Tag'',''impoly''));'); uimenu(draggMenu,'label','Delete all draggable freehands','callback','delete(findobj(gca,''Tag'',''imfreehand''));'); uimenu(draggMenu,'label','Delete all draggable objects','callback','delete(findobj(gca,''Type'',''hggroup''));','separator','on'); axisMenu = uimenu(h_get,'label','Axis position, orientation and visibility...','TAG','GET','separator','on'); uimenu(axisMenu,'Label','Toggle manual edition of the Axis position','Callback','plotedit(gcf);'); uimenu(axisMenu,'Label','Normal Y-X view of the Axis: view(0,90)','Callback','view(0,90);','separator','on'); uimenu(axisMenu,'Label','90º rotated X-Y view of the Axis: view(-90,90)','Callback','view(-90,90);'); uimenu(axisMenu,'Label','Toggle Axis visible/invisible','Callback',@axisview,'separator','on'); uimenu(axisMenu,'Label','Set Axis Position to full window','Callback',@axisview,'separator','on'); uimenu(axisMenu,'Label','Set Axis Position to its default position','Callback',@axisview); uimenu(axisMenu,'Label','Set MINIMUM Axis Position spacing','Callback',@axisview); uimenu(axisMenu,'Label','Set MINIMUM no label Axis Position spacing','Callback',@axisview); uimenu(axisMenu,'Label','Set Figure Height to small','Callback',@axisview,'separator','on'); uimenu(axisMenu,'Label','Set Figure Height to medium','Callback',@axisview); uimenu(axisMenu,'Label','Set Figure Height to normal','Callback',@axisview); uimenu(axisMenu,'Label','Reset Figure size','Callback',@axisview,'separator','on'); axisEsc = uimenu(h_get,'label','Scale and Width of the Axis...','TAG','GET'); uimenu(axisEsc,'Label','Y Axis scaled as the X','Callback',@escalarY); uimenu(axisEsc,'Label','X Axis scaled as the Y','Callback',@escalarX); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 1.0','Callback',@escalarfig,'separator','on'); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 1.5','Callback',@escalarfig); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 1.618','Callback',@escalarfig); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 2.0','Callback',@escalarfig); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 2.5','Callback',@escalarfig); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 3.0','Callback',@escalarfig); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 3.5','Callback',@escalarfig); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 4.0','Callback',@escalarfig); axisMenu = uimenu(h_get,'label','Axis visual appearance...','TAG','GET'); uimenu(axisMenu,'Label','zoom on click ( [ESC] to finish)','Callback',@zoomonclic); uimenu(axisMenu,'Label','toggle: zoom','Callback','zoom;','separator','on'); uimenu(axisMenu,'Label','toggle: pan','Callback','pan;'); uimenu(axisMenu,'Label','toggle: box','Callback','box;','separator','on'); uimenu(axisMenu,'Label','toggle: grid','Callback','grid;'); uimenu(axisMenu,'Label','toggle: grid(''minor'')','Callback','grid(''minor'');'); axisMenu2 = uimenu(axisMenu,'label','MenuBar...','separator','on'); uimenu(axisMenu2,'Label','not shown: ''none''','Callback',@quitMenuBar); uimenu(axisMenu2,'Label','with only Getfigure shown','Callback','set(gcf,''MenuBar'',''none'');'); uimenu(axisMenu2,'Label','normally shown: ''figure''','Callback',@addMenuBar); axisMenu2 = uimenu(axisMenu,'label','ToolBar...'); uimenu(axisMenu2,'Label','not shown: ''none''','Callback','set(gcf,''ToolBar'',''none'');'); uimenu(axisMenu2,'Label','normally shown: ''figure''','Callback','set(gcf,''ToolBar'',''figure'');'); uimenu(h_get,'Label','Delete objects outside the current Axis (to reduce .fig size)','Callback',@hideoutside,'separator','on','TAG','GET'); uimenu(h_get,'Label','Toggle the manual edition of objects','Callback','plotedit(gcf);','separator','on','TAG','GET'); moveToMenu = uimenu(h_get,'label','Select one object an reorder its visual stacking...','TAG','GET'); uimenu(moveToMenu,'label','Send to front','callback',{@changeLayer,'Front'}); uimenu(moveToMenu,'label','Send to back','callback',{@changeLayer,'Back'}); uimenu(moveToMenu,'label','Move forward','callback',{@changeLayer,'Forward'}); uimenu(moveToMenu,'label','Move backwards','callback',{@changeLayer,'Backwards'}); uimenu(h_get,'label','Select one object and call inspect(gco)','callback',@openInspect,'TAG','GET'); uimenu(h_get,'label',['Remove Getfigure (V' num2str(Version) ') from the menu'],'callback','delete(findobj(gcf,''Tag'',''getfigure''));','TAG','GET','separator','on'); uimenu(h_get,'label','Cancel','callback',@cancelCopy,'separator','on','Visible','off','Tag','UNDO'); %**************** % UNDO STRUCTURE %**************** % numActions: Number of actions listed % currentAction: ID of the last action % actionsList: List of objects involved in each action undoStructure.numActions = 0; undoStructure.currentAction = 0; undoStructure.actionsList = {}; undoButton.UserData = undoStructure; disp(['''Getfigure'' (V' num2str(Version) ') has been added to the menu']); % Set foccus on figure figure(gcf); else delete(hmenu); disp(['''Getfigure'' (V' num2str(Version) ') has been removed from the menu']); end end function escalarX(~,~) % get the axis hca = get(gcf,'CurrentAxes'); if ~isempty(hca) % avois axis square axis(gca,'normal'); old_units = get(hca,'Units'); set(hca,'Units','pixels'); YLim = get(hca,'YLim'); XLim = get(hca,'XLim'); YTick = get(hca,'YTick'); XTick = get(hca,'XTick'); if (length(YTick) == 1) && (length(XTick) == 1) YTickDif = (YLim(2)- YLim(1))/4; elseif (length(YTick) == 1) YTickDif = XTick(2) - XTick(1); else YTickDif = YTick(2) - YTick(1); end % width of the axis Position = get(hca,'Position'); AmpladaY = Position(4); AmpladaX = Position(3); Ytot = YLim(2) - YLim(1); % Ycentre = (YLim(2) + YLim(1))/2; Xtot = XLim(2) - XLim(1); Xcentre = (XLim(2) + XLim(1))/2; XXtot = Ytot * AmpladaX / AmpladaY; % proportional XLim XXLim1 = ((XLim(1)-Xcentre)/Xtot) * XXtot + Xcentre; XXLim2 = ((XLim(2)-Xcentre)/Xtot) * XXtot + Xcentre; set(hca,'XLim',[XXLim1 XXLim2]); zoom(hca,'reset'); % set YTick: requires 0 to be in visible in the axis set(hca,'XTick',-floor(-XXLim1/YTickDif)*YTickDif:YTickDif:floor(XXLim2/YTickDif)*YTickDif); set(hca,'XTickMode','auto'); set(hca,'Units',old_units); end end function escalarY(~,~) % get the axis hca = get(gcf,'CurrentAxes'); if ~isempty(hca) % avois axis square axis(gca,'normal'); old_units = get(hca,'Units'); set(hca,'Units','pixels'); YLim = get(hca,'YLim'); XLim = get(hca,'XLim'); YTick = get(hca,'YTick'); XTick = get(hca,'XTick'); if (length(XTick) == 1) && (length(YTick) == 1) XTickDif = (XLim(2)- XLim(1))/4; elseif (length(XTick) == 1) XTickDif = YTick(2) - YTick(1); else XTickDif = XTick(2) - XTick(1); end % width of axis Position = get(hca,'Position'); AmpladaY = Position(4); AmpladaX = Position(3); Ytot = YLim(2) - YLim(1); Ycentre = (YLim(2) + YLim(1))/2; Xtot = XLim(2) - XLim(1); % Xcentre = (XLim(2) + XLim(1))/2; YYtot = Xtot * AmpladaY / AmpladaX; % proportional YLim YYLim1 = ((YLim(1)-Ycentre)/Ytot) * YYtot + Ycentre; YYLim2 = ((YLim(2)-Ycentre)/Ytot) * YYtot + Ycentre; set(hca,'YLim',[YYLim1 YYLim2]); zoom(hca,'reset'); % set YTick: requires 0 to be visible in the axis set(hca,'YTick',-floor(-YYLim1/XTickDif)*XTickDif:XTickDif:floor(YYLim2/XTickDif)*XTickDif); set(hca,'YTickMode','auto'); set(hca,'Units',old_units); end end function axisview(hco,~) hca = gca; % avois axis square axis(gca,'normal'); switch get(hco,'Label') case 'Reset Figure size' % crear figure invisible hfig = gcf; ha = gca; hfig2 = figure('Visible','off'); ha2 = gca; pf2 = get(hfig2,'Position'); pa2 = get(ha2,'Position'); % reset set(hfig,'Position',pf2); set(ha,'Position',pa2); delete(hfig2); case 'Set Figure Height to normal' pf = get(gcf,'Position'); set(gcf,'Position',[pf(1) pf(2) pf(3) 420]); case 'Set Figure Height to medium' pf = get(gcf,'Position'); set(gcf,'Position',[pf(1) pf(2) pf(3) 420*2/3]); case 'Set Figure Height to small' pf = get(gcf,'Position'); set(gcf,'Position',[pf(1) pf(2) pf(3) 420/2]); case 'Set Axis Position to full window' axis(hca,'normal'); set(hca,'Position',[0 0 1 1]); case 'Set Axis Position to its default position' set(hca,'Position',[0.1300 0.1100 0.7750 0.8150]); case 'Set MINIMUM Axis Position spacing' % deixar 70 pixels entre X=0 i l'axis X0A = 60; % deixar 5 pixels entre l'axis i XMAX XAM = 12; % deixar 50 pixels entre Y=0 i l'axis Y0A = 50; % deixar 5 pixels entre l'axis i YMAX YAM = 5; % obtenir les mides del figure en pixels pf = get(gcf,'Position'); % obtenir les mides de l'axis en pixels old_units = get(gca,'Units'); set(gca,'Units','pixels'); pa = get(gca,'Position'); % nova mida de l'axis pa = [X0A Y0A (pf(3)-X0A-XAM) (pf(4)-Y0A-YAM)]; % fixar la mida de l'axis set(gca,'Position',pa); set(gca,'Units',old_units); case 'Set MINIMUM no label Axis Position spacing' % deixar 70 pixels entre X=0 i l'axis X0A = 35; % deixar 5 pixels entre l'axis i XMAX XAM = 12; % deixar 50 pixels entre Y=0 i l'axis Y0A = 30; % deixar 5 pixels entre l'axis i YMAX YAM = 5; % obtenir les mides del figure en pixels pf = get(gcf,'Position'); % obtenir les mides de l'axis en pixels old_units = get(gca,'Units'); set(gca,'Units','pixels'); pa = get(gca,'Position'); % nova mida de l'axis pa = [X0A Y0A (pf(3)-X0A-XAM) (pf(4)-Y0A-YAM)]; % fixar la mida de l'axis set(gca,'Position',pa); set(gca,'Units',old_units); otherwise if strcmp(get(hca,'Visible'),'on') set(hca,'Visible','off'); else set(hca,'Visible','on'); end end end function quitMenuBar(~,~) % remove getfigure getfigure63; set(gcf,'MenuBar','none'); end function addMenuBar(~,~) % remove getfigure getfigure63; set(gcf,'MenuBar','figure'); % add getfigure at the end getfigure63; end function zoomonclic(~,~) % zoom en la posició del cursor hca = gca; % entrada repetida amb el mouse set(findobj(gcf,'Tag','getfigure'),'Enable','off'); while 1 [x, y, button] = ginput(1); if (button ~= 1) && (button ~= 3) % fin % activar botons set(findobj(gcf,'Tag','getfigure'),'Enable','on'); return; end % debug %disp(['x = ' num2str(x) ', y = ' num2str(y)]); c = axis(hca); c_i = c(1); c_f = c(2); f_i = c(3); f_f = c(4); % trobar les distancies d_c_i = x - c_i; d_c_f = c_f - x; d_f_i = y - f_i; d_f_f = f_f - y; if (button == 1) % Zoom (+) escalat on es fa el clic-esquerra' d_c_i = d_c_i * 0.75; d_c_f = d_c_f * 0.75; d_f_i = d_f_i * 0.75; d_f_f = d_f_f * 0.75; elseif (button == 3) % decrementar el zoom d_c_i = d_c_i / 0.75; d_c_f = d_c_f / 0.75; d_f_i = d_f_i / 0.75; d_f_f = d_f_f / 0.75; end % aplicar el zoom c_i = x - d_c_i; c_f = d_c_f + x; f_i = y - d_f_i; f_f = d_f_f + y; axis(hca,[c_i c_f f_i f_f]); end end function hideoutside(~,~) hca = gca; YLim = get(hca,'YLim'); XLim = get(hca,'XLim'); achild = hca.Children; for i = 1:1:length(achild) % inicialitzar xmin = XLim(1); xmax = XLim(2); ymin = YLim(1); ymax = YLim(2); try switch get(achild(i),'Type') case 'text' pp = achild(i).Extent; xmin = pp(1); xmax = pp(1) + pp(3); ymin = pp(2); ymax = pp(2) + pp(4); case 'line' xmin = min(achild(i).XData); xmax = max(achild(i).XData); ymin = min(achild(i).YData); ymax = max(achild(i).YData); otherwise % ????? end catch % probablement es un GraphPlot (no té propietat type) xmin = min(achild(i).XData); xmax = max(achild(i).XData); ymin = min(achild(i).YData); ymax = max(achild(i).YData); end % verificar que estigui dintre de l'axis if ((ymax < YLim(1)) || (ymin > YLim(2)) || (xmax < XLim(1)) || (xmin > XLim(2))) % està fora delete(achild(i)); end end end function escalarfig(hco,~) % escalar sense modificar la posició d'inici de l'axis % obtenir les dades de l'axis hca = gca; % avois axis square axis(gca,'normal'); % obtenir les dades relatives % Position = get(hca,'Position'); % AmpladaYr = Position(4); % AmpladaXr = Position(3); old_units = get(hca,'Units'); set(hca,'Units','pixels'); % obtenir l'amplada Y en pixels Position = get(hca,'Position'); AmpladaX = Position(3); AmpladaY = Position(4); % escalat a aplicar escala = 1; switch get(hco,'Label') case 'X Axis Width as the Y Axis x 1.0' escala = 1; case 'X Axis Width as the Y Axis x 1.5' escala = 1.5; case 'X Axis Width as the Y Axis x 1.618' escala = 1.618033988; case 'X Axis Width as the Y Axis x 2.0' escala = 2; case 'X Axis Width as the Y Axis x 2.5' escala = 2.5; case 'X Axis Width as the Y Axis x 3.0' escala = 3; case 'X Axis Width as the Y Axis x 3.5' escala = 3.5; case 'X Axis Width as the Y Axis x 4.0' escala = 4; end % fixar la nova ampladaX de l'axis AmpladaXX = AmpladaY * escala; % guardar la diferencia difX = AmpladaXX - AmpladaX; % modificar l'amplada set(hca,'Position',[Position(1) Position(2) AmpladaXX Position(4)]); % adaptar l'amplada de la finestra Posf = get(gcf,'Position'); set(gcf,'Position',[Posf(1) Posf(2) (Posf(3)+difX) Posf(4)]); % recuperar unitats axis set(hca,'Units',old_units); end function changeLayer(~, ~, direction) ginput(1); switch direction case 'Front' uistack(gco,'top'); case 'Back' uistack(gco,'bottom'); case 'Forward' uistack(gco,'up'); case 'Backwards' uistack(gco,'down'); end end function openInspect(~,~) if isempty(findobj(gcf,'Type','axes')) inspect(gcf); else ginput(1); inspect(gco); end end function cancelCopy(src, ~) src.Visible = 'off'; end function copy(src, ~, target, targetSize) persistent offsetinicialp numerop offsetfinalp rnoise if isempty(offsetinicialp) % initialize persistent subsampling values offsetinicialp = 1; numerop = 10; offsetfinalp = 0; rnoise = 0; end % Enable cancel button % Retrieve undo actions list btnID = getButtonID(src.Parent,'Cancel'); if isempty(btnID) disp('Cancel button not found'); return; end % Hide other options hcf = gcf; set(findobj(hcf,'TAG','GET'),'Visible','off'); cancelBtn = src.Parent.Children(btnID); cancelBtn.Visible = 'on'; % Get destination figure dstFigure = gcf; % Get the current type of element initialObject = gco; switch target case 'Axes' expectedSelectionClass = 'matlab.graphics.axis.Axes'; initialObject = get(dstFigure,'CurrentAxes'); case 'Figure' % delete olds axis of the figure achild = hcf.Children; for i=1:1:length(achild) switch achild(i).Type case 'axes' delete(achild(i)); end end expectedSelectionClass = 'matlab.ui.Figure'; initialObject = gcf; case 'Line' expectedSelectionClass = 'matlab.graphics.chart.primitive.Line'; initialObject = gco; end % Set targetDectected flag to 0 targetDetected = 0; % Wait untill the user selects an object that matches the target class while ~targetDetected && strcmp(cancelBtn.Visible,'on') if strcmp(target,'Figure') currentElm = gcf; elseif strcmp(target,'Axes') currentElm = get(gcf,'CurrentAxes'); else currentElm = gco; end % Check if the user selected an object matching the target class % and its different from the initial object if isa(currentElm, expectedSelectionClass) && ~isequal(initialObject, currentElm) targetDetected = 1; else refresh(); drawnow(); end end % Show the other menus set(findobj(hcf,'TAG','GET'),'Visible','on'); % Check if user cancelled the action if strcmp(cancelBtn.Visible,'off') disp('Copy action canceled'); return; end % Get the list of elements to copy and the number of elements on that % list [cpyElmsList, numCpyItems] = getTargetElms(currentElm); % Initialize list of newly added objects newlyAddedObjects = {}; % Copy elements on cpyElmsList for i = 1:numCpyItems switch class(cpyElmsList{i}) case 'matlab.graphics.illustration.Legend' la = copyobj([cpyElmsList{i}, cpyElmsList{i}.Axes], dstFigure); case 'matlab.graphics.axis.Axes' la = copyobj(cpyElmsList{i}, dstFigure); case 'matlab.graphics.chart.primitive.Line' dstChildsList = dstFigure.Children; numChilds = length(dstChildsList); targetChild = []; for childID = 1:numChilds if isa(dstChildsList(childID), 'matlab.graphics.axis.Axes') targetChild = dstChildsList(childID); break; end end if isempty(targetChild) figure(dstFigure); targetChild = axes(); end la = copyobj(cpyElmsList{i}, targetChild); numElms = length(la.XData); if strcmpi(targetSize,'subsampled') if numerop > numElms numerop = numElms; % limit end answer=inputdlg({'Index of the initial point of the line (1..)',['Number of points after the sampling (1..' num2str(numElms) ')'],'Offset to the index of the end point (0,-1,-2,...)','Add random noise to YData with amplitude...'},'Subsampling',1,{num2str(offsetinicialp),num2str(numerop),num2str(offsetfinalp),num2str(rnoise)}); drawnow; if(isempty(answer)) delete(la) return; end offsetinicialp = str2double(char(answer(1))); numerop = str2double(char(answer(2))); offsetfinalp = str2double(char(answer(3))); rnoise = str2double(char(answer(4))); if numerop > numElms numerop = numElms; % limit again end if offsetfinalp > 0 offsetfinalp = -offsetfinalp; end p = round(linspace(offsetinicialp,numElms+offsetfinalp,numerop)); la.XData = la.XData(p); la.YData = la.YData(p) + (rand(1,length(p))-0.5)*2*rnoise; if ~isempty(la.ZData) la.ZData = la.ZData(p); end elseif strcmpi(targetSize,'oversampled') answer=inputdlg({'Index of the initial point of the line (1..)',['Number of points after spline oversampling ( ..' num2str(numElms) '.. )'],'Offset to the index of the end point (0,-1,-2,...)','Add random noise to YData with amplitude...'},'Oversampling',1,{num2str(offsetinicialp),num2str(numerop),num2str(offsetfinalp),num2str(rnoise)}); drawnow; if(isempty(answer)) delete(la) return; end offsetinicialp = str2double(char(answer(1))); numerop = str2double(char(answer(2))); offsetfinalp = str2double(char(answer(3))); rnoise = str2double(char(answer(4))); if numerop < 1 numerop = 1; % limit end if offsetfinalp > 0 offsetfinalp = -offsetfinalp; end p = linspace(offsetinicialp,numElms+offsetfinalp,numerop); % oversampling using splines la.XData = spline([1:1:numElms],la.XData,p); la.YData = spline([1:1:numElms],la.YData,p) + (rand(1,length(p))-0.5)*2*rnoise; if ~isempty(la.ZData) la.ZData = spline([1:1:numElms],la.ZData,p); end end end if length(la) == 1 newlyAddedObjects{end+1} = la; %#ok Total number of elements is unknown else numAddedElems = length(la); for elemID = 1:numAddedElems newlyAddedObjects{end+1} = la(elemID); %#ok Total number of elements is unknown end end end if strcmp(targetSize, 'Resize') la.Position = [0.1300 0.1100 0.7750 0.8150]; end if strcmp(target,'Figure') && strcmp(targetSize,'Exact') dstFigure.Position(3:4) = currentElm.Position(3:4); end if strcmp(target,'Axes') && strcmp(targetSize,'OriginalFigure') dstFigure.Position(3:4) = currentElm.Parent.Position(3:4); end % Retrieve undo actions list btnID = getButtonID(src.Parent,'Undo last Get'); if isempty(btnID) disp('Button not found'); end undoButton = src.Parent.Children(btnID); undoButton.Enable = 'on'; % Update undo actions list undoStructure = undoButton.UserData; undoStructure.numActions = undoStructure.numActions + 1; undoStructure.currentAction = undoStructure.currentAction + 1; undoStructure.actionsList{undoStructure.currentAction} = newlyAddedObjects; undoButton.UserData = undoStructure; cancelBtn.Visible = 'off'; end function copybitmap(src, ~, keepLimits) % Enable cancel button % Retrieve undo actions list btnID = getButtonID(src.Parent,'Cancel'); if isempty(btnID) disp('Cancel button not found'); return; end % Hide other options hcf = gcf; hca = gca; set(findobj(hcf,'TAG','GET'),'Visible','off'); cancelBtn = src.Parent.Children(btnID); cancelBtn.Visible = 'on'; % Get the current type of element initialObject = gco; % Set targetDectected flag to 0 targetDetected = 0; % Wait untill the user selects an object that matches the target class while ~targetDetected && strcmp(cancelBtn.Visible,'on') currentElm = gco; % Check if the user selected an image % and its different from the initial object if strcmp(get(currentElm,'Type'),'image') && ~isequal(initialObject, currentElm) targetDetected = 1; else refresh(); drawnow(); end end % Show the other menus set(findobj(hcf,'TAG','GET'),'Visible','on'); % Check if user cancelled the action if strcmp(cancelBtn.Visible,'off') disp('Copy action canceled'); return; end % add in the axes ih = ishold(gca); if (ih == 0) hold(hca,'on'); end figure(hcf); %hi = image(hca.XLim,hca.YLim,ii); hi = copyobj(currentElm, hca); uistack(hi,'bottom'); if ~keepLimits hi.XData = hca.XLim; hi.YData = hca.YLim; end % copy figure colormap in case of Image %cc = get(currentFig,'colormap'); %set(hcf,'colormap',cc) if (ih == 0) hold(hca,'off'); end % Retrieve undo actions list btnID = getButtonID(src.Parent,'Undo last Get'); if isempty(btnID) disp('Button not found'); end undoButton = src.Parent.Children(btnID); undoButton.Enable = 'on'; % Update undo actions list undoStructure = undoButton.UserData; undoStructure.numActions = undoStructure.numActions + 1; undoStructure.currentAction = undoStructure.currentAction + 1; undoStructure.actionsList{undoStructure.currentAction} = {hi}; % EL UNDO PETA undoButton.UserData = undoStructure; cancelBtn.Visible = 'off'; end function btnID = getButtonID(parentID,targetName) childsList = parentID.Children; numChilds = length(childsList); btnID = []; for childID = 1:numChilds currentChild = childsList(childID); if strcmpi(currentChild.Label,targetName) btnID = childID; end end if isempty(btnID) return; end end function merge(src, ~, targetSize) btnID = getButtonID(src.Parent,'Cancel'); if isempty(btnID) disp('Cancel button not found'); return; end % Hide other options hcf = gcf; set(findobj(hcf,'TAG','GET'),'Visible','off'); cancelBtn = src.Parent.Children(btnID); cancelBtn.Visible = 'on'; % % % get destination axes (creates an axes if no axes in the figure) % dstAx = gca; expectedSelectionClass = 'matlab.graphics.axis.Axes'; initialObject = gca; targetDetected = 0; while ~targetDetected && strcmp(cancelBtn.Visible,'on') currentElm = gca; currentFig = gcf; if isa(currentElm, expectedSelectionClass) && ~isequal(initialObject, currentElm) targetDetected = 1; else refresh(); drawnow(); end end % Show other options set(findobj(hcf,'TAG','GET'),'Visible','on'); % Check if user cancelled the action if strcmp(cancelBtn.Visible,'off') disp('Exit') return; end [cpyElmsList, numCpyItems] = getTargetElms(currentElm); newlyAddedObjects = {}; % get destination axes (creates an axes if no axes in the figure) figure(hcf); dstAx = gca; for i = 1:numCpyItems switch class(cpyElmsList{i}) case 'matlab.graphics.illustration.Legend' axesObj = cpyElmsList{i}.Axes; case 'matlab.graphics.axis.Axes' axesObj = cpyElmsList{i}; end childList = axesObj.Children; numChildren = length(childList); for childID = numChildren:-1:1 newlyAddedObjects{end+1} = copyobj(childList(childID), dstAx); %#ok unknown total number of elms uistack(newlyAddedObjects{end},'top'); % copy figure colormap in case of Image if isprop(childList(childID),'Type') if strcmp(get(childList(childID),'Type'),'image') cc = get(currentFig,'colormap'); set(hcf,'colormap',cc) end end end end if strcmp(targetSize,'ResizeFigAndAx') dstAx.Position = currentElm.Position; dstAx.Parent.Position(3:4) = currentElm.Parent.Position(3:4); % Revise axis limits of the destination c = axis(dstAx); c2 = axis(currentElm); if (c(1) ~= c2(1)) c(1) = c2(1); end if (c(2) ~= c2(2)) c(2) = c2(2); end if (c(3) ~= c2(3)) c(3) = c2(3); end if (c(4) ~= c2(4)) c(4) = c2(4); end if length(c2) > 4 % 3D if (length(c2) > length(c)) c(5) = c2(5); c(6) = c2(6); else if (c(5) ~= c2(5)) c(5) = c2(5); end if (c(6) ~= c2(6)) c(6) = c2(6); end end end % set the new limits axis(dstAx,c); zoom(dstAx,'reset'); end % Retrieve undo actions list btnID = getButtonID(src.Parent,'Undo last Get'); if isempty(btnID) disp('Button not found'); end undoButton = src.Parent.Children(btnID); undoButton.Enable = 'on'; % Update undo actions list undoStructure = undoButton.UserData; undoStructure.numActions = undoStructure.numActions + 1; undoStructure.currentAction = undoStructure.currentAction + 1; undoStructure.actionsList{undoStructure.currentAction} = newlyAddedObjects; undoButton.UserData = undoStructure; cancelBtn.Visible = 'off'; end function [axesList, lastAxesID] = getTargetElms(srcElm) switch class(srcElm) case 'matlab.graphics.chart.primitive.Line' axesList{1} = srcElm; lastAxesID = 1; case 'matlab.graphics.axis.Axes' childList = srcElm.Children; numChildren = length(childList); axesList = cell(1, 1); % Check if this axis is linked to a Legend object for childID = 1:numChildren if isa(childList(childID),'matlab.graphics.illustration.Legend') if isequal(childList(childID).Axes) % Axes linked to a legend, just return the legend axesList{1} = childList(childID); lastAxesID = 1; return; end end end % No legend was linked to this axes, return the axes object axesList{1} = srcElm; lastAxesID = 1; case 'matlab.ui.Figure' childList = srcElm.Children; numChildren = length(childList); legendsList = cell(1, numChildren); lastLegendID = 0; axesList = cell(1, numChildren); for childID = 1:numChildren if isa(childList(childID),'matlab.graphics.illustration.Legend') lastLegendID = lastLegendID + 1; legendsList{lastLegendID} = childList(childID); axesList{lastLegendID} = legendsList{lastLegendID}.Axes; end end legendsList = legendsList(1:lastLegendID); lastAxesID = lastLegendID; for childID = 1:numChildren if isa(childList(childID),'matlab.graphics.axis.Axes') found = 0; % check if this axes has already been detected as part of legend for legendID = 1:lastLegendID if isequal(childList(childID), axesList{legendID}) found = 1; end end if ~found lastAxesID = lastAxesID + 1; axesList{lastAxesID} = childList(childID); end end end axesList = axesList(1:lastAxesID); axesList(1:lastLegendID) = legendsList; end end function undo_copy(source,~) % UNDO function undoStructure = source.UserData; undoID = undoStructure.currentAction; deleteElems = undoStructure.actionsList{undoID}; % remove one item at a time for elemID = 1:length(deleteElems) if ishandle(deleteElems{elemID}) % Try-catch block as some elements may have been deleted % manually by the user try delete(deleteElems{elemID}); catch end end end % Update UNDO structure undoStructure.actionsList(undoID) = []; undoStructure.currentAction = undoStructure.currentAction - 1; undoStructure.numActions = undoStructure.numActions -1; source.UserData = undoStructure; % Disable undo option if undoStructure.numActions == 0 source.Enable = 'off'; end end