Matlab: datacursormode and calculate slope - matlab

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

Related

Matlab interactive calculation of slope between two points

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

Place MATLAB legend such that it does not overlap on the plot

I am generating multiple plots of different datasets in succession using MATLAB. I would like the legend positions to be such that they don't overlap on the plotted lines and it would be ideal if this placement could be done automatically.
I am aware of setting the 'Location' to 'best' to achieve this but the placement of the legend tends to be awkward when 'best' is used (below). Also, I would like the legend to be inside the plot. I also came across a way to make the legend transparent (here) so that it does not render the plotted data invisible, but explicitly placing the legend elsewhere is what I am looking for.
Is there a way to place the legend at the extremes of the image ('NorthWest', 'SouthWest' etc) automatically such that it does not overlap on the plotted data (apart from the methods suggested above)?
So, you have tried using Location instead of Position? For example:
x =1:100;
y = x.^2;
lgd = legend('y = x.^2');
set(lgd,'Location','best')
and you are getting odd results correct? A quick way of solving this would be to still use Location, with best, and extract the coordinates:
lgd.Position
You should get something like this:
ans =
0.7734 0.3037 0.1082 0.0200
which maps to:
[left bottom width height]
You will need to focus on left and bottom. These two values, left and bottom, specify the distance from the lower left corner of the figure to the lower left corner of the legend, and they are analogous to the grid frame you are using.
Then, depending on the size of the frame (I would suggest you use axis([XMIN XMAX YMIN YMAX]) for this, if possible), you can pinpoint the position of the legend within the grid. What you can do next, is check if and which of your graphs in the plot cross paths with the legend (maybe define a relative distance function based on some distance threshold) and if they do, then randomly reposition the legend (i.e. change the values of left and bottom) and repeat until your conditions are met.
If this still troubles you I can write a short snippet. Finally, know that you can always opt for placing the legend on the outside:
set(lgd,'Location','BestOutside')

Matlab how to fill quiver arrow heads

I am making a quiver plot :
[x,y] = meshgrid(0:0.2:2,0:0.2:2);
u = cos(x).*y;
v = sin(x).*y;
figure
quiver(x,y,u,v)
I want the arrow heads to be filled (i.e and not )
From the documentation, it should be pretty straightforward by using
quiver(...,LineSpec,'filled')
However, I still couldn't figure out the right syntax - these do not work :
quiver(x,y,u,v,'LineWidth','filled');
quiver(x,y,u,v,'LineWidth',1,'filled');
Thanks for your help!
edit : Using line specifiers does the following:
quiver(x,y,u,v) %Original
quiver(x,y,u,v,'-sk','filled') %With line specifiers
I am not a MATLAB professional, so please excuse if my answer is clunky. I am sure there are more elegant ways to solve this - the following is the one I found.
I decided to solve this retrieving the positions of the arrow tips, deleting them and repaint them with fill (like Deve suggested). I noticed that I can tell fill that one polygon ends and the next begins through inserting NaN values (thats also the way the original arrow tips are drawn, as you can see inspecting the original XData). Doing so I lost the possibility to influence the color of the objects and they didn´t get filled. As a work-around I painted the new arrow-tips in a loop - I know there might be a better way to do it, so I am happy about any addition.
I used the example you gave, only replacing the last line by
HANDLE = quiver(x,y,u,v); to get the handle to the plot. From there on:
children=get(handle,'children'); % retrieve the plot-children -
% second element are the arrow tips
XData=get(children(2),'XData'); % retrieve the coordinates of the tips
YData=get(children(2),'YData');
hold on
delete(children(2)) % delete old arrow tips
for l=1:4:length(XData)-3 % paint new arrow tips, skipping the NaN-values
ArrowTips((l-1)/4+1)=fill(XData(l:l+2),YData(l:l+2),'r');
end
You can then find the handles to the arrow-tips in the ArrowTips-variable. Feel free to specify the Edge- and Facecolor in the call to fill, here being black and red respectively.
This code in an answer to a similar question works quite well, actually. It uses annotations.
In Matlab how do I change the arrow head style in quiver plot?

how to do line fitting multiple lines MATLAB?

I'm trying find all straight lines in an image which is border. for example,stamps have four edges and I have already find those edges by edge function in MATLAB. But there is a problem that they are not real straight line. so I need to use line fitting to get all four borders. But polyfit function can only fit one line at one time. Is there any solutions that can fit all lines at one time.
for example:here I upload some pictures,the image with red lines is what I want. Please be ware I need four separate lines.
Judging from the image you won't be trying to smooth some lines, or fill in the gaps. Instead it looks more like you need to put your image in the smallest possible box.
Here is an algorithm that you can try:
Start from all 4 corners.
'walk' one of the corners inwards and determine if all points are still within four corners
If so, save this corner and go to step 2, else go to step 2
Keep repeating step 2 and 3 till you have a steady solution.
Are you trying to get rid of the perforations? In that case I would suggest using thresholding to segment out dark areas of the image, and then using regionprops to get their bounding boxes. Then you can figure out the largest rectangle that excludes them.

Single Axis Simulation in Matlab

Hi i wanted to generate a single axis graph (dont know if this is called a graph exactly) in matlab something like this
In the above image the numerical values represent time ( 1 till 23) min and the vertical thin black lines represent event A . Some of the vertical black lines have a red circle on top denoting occurrence of an event B along with the event A. Is it possible to generate such a simulated image in matlab ? If so what keywords should i look for. Any suggestions to get me quickly started on generating such a graph/Simulation. (Note: I havent actually used matlab a lot.. certainly never generated graphs in it)
You probably want a stem graph, and then do something like:
stem(event_times, ones(size(event_times));
You can overlay multiple graphs to get the red circles, etc.