Matlab interactive calculation of slope between two points - matlab

I create a figure with toggle button on its toolbar by uitoggletool. The callback function for it is shown below:
function calc_slope(handle,event)
on = get(handle,'State');
if strcmpi(on,'on') || strcmpi(on,'off'),
xy=imline;
addNewPositionCallback(xy,#(xy)...
title(['\DeltaY/\DeltaX = ',num2str((xy(4)-xy(3))/(xy(2)-xy(1))),...
'[\DeltaX = ',num2str(xy(2)-xy(1)),...
',\DeltaY = ',num2str((xy(4)-xy(3))),']']));
end
As you can see, I'm trying to calculate the slope between two points on a curve. The code is something I found in the web that's pretty close to what I'm trying to. The 'addNewPositionCallback" is executed in both 'On' and 'Off' state, but it's merely a means to repeat the process as many times as a user wants. What I really want to do is number 4 and 5 below.
What I really want to do is as follows:
"Draggable" points "snapped" to the nearest curve
The connecting line shows
Delta X, delta Y, and the slope provided in a "text box" drawn near
the curve
Draw as many lines as needed while in the 'On' state
Delete all lines and 'text' boxes when toggle button is set to 'Off'
The imline function gives a bunch of features such as different line colors. I can care less on those. The major "wants" are the snapping and the text box.
Your help will be greatly appreciated.
Thank you,
Eric

Related

Limit impoly clicks and convert it to a rectangle - Matlab

I am using impoly as in the script below and I have two questions:
Can I limit the to points clicked (e.g., 5) and close it automatically?
Is there a way convert the impoly to imrect like in the attached image (red box)?
Script:
clc;
clear;
figure, imshow('pout.tif');
hpoly = impoly(gca);
From the documentation of impoly, I don't think it is directly possible. For such custom behaviour, you should probably write your own point picking function.
Several matlab functio ncan help you in this direction.
[x,y] = ginput(n) to pick points
impoint(hparent,x, y) to draw draggable points,
line to draw a the line between points, and the rectangle bounding box.
impoint has a 'PositionConstraintFcn' parameter, that will call a function of yours when the point is moved. You can use it to update the lines draw when the points are moved.
I suggest you to have a main function that handles the point picking (constraining the number of points, etc...), and a "display" function, that calculate the bounding box, draw the lines between points, that you can call when a point is added (in the main function), or when a point is moved (with the 'PositionConstraintFcn'parameter).

MatLab GUI plotting a line that updates with button press

So I'm working on MatLab GUI assignment right now.
It's basically an estimation game. In every trial the user guesses the correlation displayed on the left axes. When they click submit my code calculates the absolute value of the difference between their estimation and the actual correlation.
So far so good.
On the right axes I want to plot a line that updates every time they click "submit". The x-coordinate would be the trial # and the y-coordinate would be the absolute difference previously mentioned.
I can plot this information successfully using points instead of a line by using "scatter" or "plot", but when I try to make it a line, nothing appears, although the axis does seem to update...
Both of the following codes work if the marker is '.' or 'o' or 's' or 'x' ... literally any marker.. but I can't get it to connect the dots... I've messed around with trying to use animated line and drawnow but that didn't work out for me either..
plot(handles.trial, handles.diff(handles.trial),'-.'); hold on; %plot trialwise absolute differences
or
scatter(handles.trial, handles.diff(handles.trial),'-.'); hold on; %plot trialwise absolute differences
**Problem solved!
see the solution below
Solution:
Store all of the relevant data in a matrix handles.DATA. For this to work there needed to be something in there before the first trial so during initialization I set handles.DATA = [0 0] and then with the button-press (submit) that ends a trial, the data from that trial got concatenated into the data matrix: handles.DATA = vertcat(handles.DATA, [x y]). Below this I could do the plot that I wanted to: plot(handles.DATA(:,1), handles.DATA(:,2),'Color','r'
*note: don't hold on because then you will have lines stacking on each other.
**also if you don't specify line color, the line will become a different color every time you click "submit" because this is generating a new line every time based off the updated information.

Matlab: datacursormode and calculate slope

I'm trying to calculate the slope between two points. I've tried some other methods such as imline, but none of them allows the snapping to a curve. I found out this morning that I can possibly use the data tips in the datacursormode.
So, what I want to do is:
Select two points showing the black dot for both points
Upon the second left-clicking, a line is drawn connecting the two points and a text box shows the calculated slope
If I move either black dot, the text box is updated with a new slope
I can have as many pairs as I want, many lines between a part of black dots
If either dot is deleted, the associated text box disappears along with it
I've tried things like
waitforbuttonpress;
point1 = getCursorInfo(data_cursor_mode_obj);
waitforbuttonpress;
point2 = getCursorInfo(data_cursor_mode_obj);
slope = abs((y2-y1)/(x2-x1));
text((x1+x2)/2,(y1+y2)/2,[' \leftarrow' num2str(slope) ])
This of course doesn't update the text. In fact, for some reason, Matlab complains and I don't know how to fix it.
Another thing I tried was using UpdateFcn, but a problem with it is that I can only pass one point data by doing event_obj.Position.
Your help will be greatly appreciated.
Thanks,
Eric

any way to have mouse stick to a curve in matlab?

I have a java program with a Gaussian plotted in the range -3 to 3 (f = exp(-x^2/3)). I capture the mouse event and have the mouse can only move along the curve so to pick up the value (f) and the corresponding x. Is that possible to implement the same thing in matlab? I search for mouse event in matlab but seems it doesn't have any low-level mouse control or even response.
As suggested by A. Donda, I tried datacursormode. If I have two curves shown on the same figure, I can easily trace the position of the mouse on either curve, I wonder if it is possible to capture the event upon the tracing so I can return the value of the other curve at the same x-coordinate while I am tracing the other curve? Or if it possible to change the way or content the yellow tip shown? What I really interesting is the sum or difference or product of the function values from two curve at the same x position.
Not exactly the same thing, but you can use "Tools / Data Cursor" in the figure window, also accessible by the "yellow note with crosshairs" icon in the toolbar, or the function datacursormode.
You can't easily set the mouse position with matlab (see here for an example). As mentioned by #A. Donda, the straightforward solution is to use the data cursor.
Set the "stick-to-curve" behavior with your mouse
With datacursormode on, you can right click on the axes and set Selection Style to Mouse Position. Then, select a first point on the curve. A data tip containing (x,y) will appear. Select a second point but keep the mouse button down: the data cursor will stick to the curve and will follow the mouse.
Set the "stick-to-curve" behavior programatically
Get the handle of datacursormode and set the SnapToDataVertex property to off before calling datacursormode on
cursorMode = datacursormode(gcf);
set(cursorMode, 'SnapToDataVertex', 'off');
datacursormode on

MATLAB: Plotting two different axes on one figure

The MATLAB surf plot below is essentially two plots plotted adjacent to each other. For clarity, I have included some code below used to prepare the plot:
band1 = horzcat(band1, eSurface2(:,:,1));
band2 = horzcat(band2, eSurface2(:,:,2));
surf(band2,'DisplayName','band2');
surf(band3,'DisplayName','band2');
I would like for the y axis numbering to restart at the start of the second graph. How do I go about doing that?
You can use the 'YTick' and 'YTickLabel' properties of the axis to control the ticks, this way you can make it start from zero for the second graph. It will require some trail and error to get it right. See the relevant doc here (you'll have to scroll all the way to the bottom of the page).
Take advantage of the following feature of 'YTickLabel': "If you do not specify enough text labels for all the tick marks, MATLAB uses all of the labels specified, then reuses the specified labels".