How to interactively select different plots in a figure and merge them together?
1 view (last 30 days)
Show older comments
Lorenzo Melito
on 11 Mar 2024
Commented: Lorenzo Melito
on 26 Mar 2024
I have several little lines of plot that represent portions of particle trajectories: each of such "pieces" are described by x- and y-coordinates. I am looking for a way to produce a figure of all these pieces, click on each of the pieces that visually belong to the same trajectory, and merge their x- and y- coordinates into a single array.
Here is a very simple example:
x = linspace(0,pi,100);
y = sin(x); z = cos(x/2);
x1 = x(1:12); y1 = y(1:12);
x2 = x(19:25); y2 = y(19:25);
x3 = x(45:67); y3 = y(45:67);
x4 = x(90:end); y4 = y(90:end);
x5 = x(4:19); y5 = z(4:19);
x6 = x(40:88); y6 = z(40:88);
plot(x1,y1,'b'); grid on; hold on
plot(x2,y2,'b')
plot(x3,y3,'b')
plot(x4,y4,'b')
plot(x5,y5,'r')
plot(x6,y6,'r')
From here, I need to click on all the blue plots (which belong to the "sine" trajectory) or red plots (which belong to the "cosine" trajectory), collect their coordinates and save them into a single array (for a future reconstruction of the original trajectory or whatever).
Searching a bit through MATLAB Answers, I came across this question that explains how to extract data from MATLAB figures. This is quite similar to what I need; but instead of by inspecting properties, I need to do it interactively by clicking on each plot, one after the other, and saving in the workspace the XData and YData of all plots I have clicked. In this sense, the concept should be similar to what ginput does with plot coordinates.
0 Comments
Accepted Answer
Sachin Lodhi
on 18 Mar 2024
Hi Lorenzo, from what I understand, you want to join together line segments on a figure in a way that you can control as you go. Below, I've put together a piece of code to help you start with this. Remember, this is just a basic setup for merging lines, and you might need to tweak it a bit to make it work just right for you.
function merge_plot_pieces
% Sample plot pieces
x = linspace(0,pi,100);
y = sin(x); z = cos(x/2);
% Define segments
segments = { x(1:12), y(1:12); x(19:25), y(19:25); x(45:67), y(45:67); x(90:end), y(90:end); x(4:19), z(4:19); x(40:88), z(40:88)};
colors = ['b', 'b', 'b', 'b', 'r', 'r'];
% Initialize global variables to store merged coordinates and last color
global mergedX;
global mergedY;
global lastColor;
mergedX = [];
mergedY = [];
lastColor = ''; % Empty indicates no color selected yet
% Plot segments
fig = figure; hold on; grid on;
for i = 1:size(segments, 1)
h = plot(segments{i,1}, segments{i,2}, colors(i));
set(h, 'ButtonDownFcn', @plotClicked, 'UserData', colors(i)); % Store color in UserData
end
% Set up a key press function to reset the merging process
set(fig, 'KeyPressFcn', @resetMerging);
end
function plotClicked(src, ~)
% This function is called when a plot segment is clicked
global mergedX;
global mergedY;
global lastColor;
currentColor = src.UserData; % Get the color of the clicked plot from UserData
% Check if the color matches the last clicked color or if it's the first click
if isempty(lastColor) || strcmp(lastColor, currentColor)
% Append clicked segment data to global variables
mergedX = [mergedX, src.XData];
mergedY = [mergedY, src.YData];
lastColor = currentColor; % Update lastColor
% Plot the merged trajectory
plot(mergedX, mergedY, currentColor, 'LineWidth', 2, 'Tag', 'mergedTrajectory');
legend off
else
% If the colors don't match, do not merge and optionally alert the user
disp('Cannot merge: Selected segment is of a different color.');
end
end
function resetMerging(~, ~)
% This function resets the merging process to allow starting with a new color without clearing the last merged trajectory
global mergedX;
global mergedY;
global lastColor;
% Reset the global variables without clearing the last merged trajectory
mergedX = [];
mergedY = [];
lastColor = '';
disp('Merging process reset. You can now start merging a new color.');
end
I hope this helps.
3 Comments
Sachin Lodhi
on 26 Mar 2024
To save the merged trajectories (mergedX and mergedY) in the MATLAB workspace from within the function, you need to use the 'assignin' function. The 'assignin' function allows you to assign a value to a variable in a specified workspace, which in your case would be the 'base' workspace (MATLAB's main workspace).
You can modify the plotClicked and resetMergign function in the following way -
function plotClicked(src, ~)
global mergedX;
global mergedY;
global lastColor;
currentColor = src.UserData; % Get the color of the clicked plot from UserData
if isempty(lastColor) || strcmp(lastColor, currentColor)
mergedX = [mergedX, src.XData];
mergedY = [mergedY, src.YData];
lastColor = currentColor;
plot(mergedX, mergedY, currentColor, 'LineWidth', 2, 'Tag', 'mergedTrajectory');
legend off
% Save to base workspace
assignin('base', 'mergedX', mergedX);
assignin('base', 'mergedY', mergedY);
assignin('base', 'lastColor', lastColor);
else
disp('Cannot merge: Selected segment is of a different color.');
end
end
function resetMerging(~, ~)
global mergedX;
global mergedY;
global lastColor;
mergedX = [];
mergedY = [];
lastColor = '';
% Save the reset state to base workspace
assignin('base', 'mergedX', mergedX);
assignin('base', 'mergedY', mergedY);
assignin('base', 'lastColor', lastColor);
disp('Merging process reset. You can now start merging a new color.');
end
More Answers (0)
See Also
Categories
Find more on Annotations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!