Intersection between curve from points and a line - matlab

I'm new in matlab and I'm trying to find the intersection between a curve (from points) and a line.
I've some points and I've plot the interpolation between this points. Now I want to find the intersection between the interpolation (xi,yi) curve and another line.
x = [94.8;84.4;63.1;49.4;40.6;33.8;23.2;20.1;10.2;9.2;7.9];
y = [0; 11.4;29.7;41.6;47.5;50.1;52.9;50.6;32.2;28.1;0];
xi=94.8:-0.1:7.9;
yi=interp1(x,y,xi,'spline');
plot(x,y,'*');
hold on
plot(xi,yi);
I've researched but everything I've found needs a function. I already tried to convert the curve to a function using polyfit but the fit is not good enought.
It is posible to do this in matlab?
Thanks.

Basically, the error message ask you to input a function handle (similar to function pointer in other languages). It's not necessary to convert it into something that matches a mathematical definition of a function (e.g. polynom):
f=#(xi)(interp1(x,y,xi,'spline'))
This can be evaluated at every xi.
Usage like every other function:
f(1)
f(1:3)

Related

MATLAB: polyval function for N greater than 1

I am trying trying to graph the polynomial fit of a 2D dataset in Matlab.
This is what I tried:
rawTable = readtable('Test_data.xlsx','Sheet','Sheet1');
x = rawTable.A;
y = rawTable.B;
figure(1)
scatter(x,y)
c = polyfit(x,y,2);
y_fitted = polyval(c,x);
hold on
plot(x,y_fitted,'r','LineWidth',2)
rawTable.A and rawTable.A are randomly generated numbers. (i.e. the x dataset cannot be represented in the following form : x=0:0.1:100)
The result:
second-order polynomial
But the result I expect looks like this (generated in Excel):
enter image description here
How can I graph the second-order polynomial fit in MATLAB?
I sense some confusion regarding what the output of each of those Matlab function mean. So I'll clarify. And I think we need some details as well. So expect some verbosity. A quick answer, however, is available at the end.
c = polyfit(x,y,2) gives the coefficient vectors of the polynomial fit. You can get the fit information such as error estimate following the documentation.
Name this polynomial as P. P in Matlab is actually the function P=#(x)c(1)*x.^2+c(2)*x+c(3).
Suppose you have a single point X, then polyval(c,X) outputs the value of P(X). And if x is a vector, polyval(c,x) is a vector corresponding to [P(x(1)), P(x(2)),...].
Now that does not represent what the fit is. Just as a quick hack to see something visually, you can try plot(sort(x),polyval(c,sort(x)),'r','LineWidth',2), ie. you can first sort your data and try plotting on those x-values.
However, it is only a hack because a) your data set may be so irregularly spaced that the spline doesn't represent function or b) evaluating on the whole of your data set is unnecessary and inefficient.
The robust and 'standard' way to plot a 2D function of known analytical form in Matlab is as follows:
Define some evenly-spaced x-values over the interval you want to plot the function. For example, x=1:0.1:10. For example, x=linspace(0,1,100).
Evaluate the function on these x-values
Put the above two components into plot(). plot() can either plot the function as sampled points, or connect the points with automatic spline, which is the default.
(For step 1, quadrature is ambiguous but specific enough of a term to describe this process if you wish to communicate with a single word.)
So, instead of using the x in your original data set, you should do something like:
t=linspace(min(x),max(x),100);
plot(t,polyval(c,t),'r','LineWidth',2)

Matlab : Intersect point of curves

Say for example I have data which forms the parabolic curve y=x^2, and I want to read off the x value for a given y value. How do I go about doing this in MATLAB?
If it were a straight line, I could just use the equation of the line of best fit to calculate easily, however I can't do this with a curved line. If I can't find a solution, I'll solve for roots
Thanks in advance.
If all data are arrays (not analytical expressions), I usually do that finding minimal absolute error
x=some_array;
[~,ind]=min(abs(x.^2-y0))
Here y0 is a given y value
If your data are represented by a function, you can use fsolve:
function y = myfun(x)
y=x^2-y0
[x,fval] = fsolve(#myfun,x0,options)
For symbolic computations, one can use solve
syms x
solve(x^2 - y0)
Assuming your two curves are just two vectors of data, I would suggest you use Fast and Robust Curve Intersections from the File Exchange. See also these two similar questions: how to find intersection points when lines are created from an array and Finding where plots may cross with octave / matlab.

matlab: cdfplot of relative error

The figure shown above is the plot of cumulative distribution function (cdf) plot for relative error (attached together the code used to generate the plot). The relative error is defined as abs(measured-predicted)/(measured). May I know the possible error/interpretation as the plot is supposed to be a smooth curve.
X = load('measured.txt');
Xhat = load('predicted.txt');
idx = find(X>0);
x = X(idx);
xhat = Xhat(idx);
relativeError = abs(x-xhat)./(x);
cdfplot(relativeError);
The input data file is a 4x4 matrix with zeros on the diagonal and some unmeasured entries (represent with 0). Appreciate for your kind help. Thanks!
The plot should be a discontinuous one because you are using discrete data. You are not plotting an analytic function which has an explicit (or implicit) function that maps, say, x to y. Instead, all you have is at most 16 points that relates x and y.
The CDF only "grows" when new samples are counted; otherwise its value remains steady, just because there isn't any satisfying sample that could increase the "frequency".
You can check the example in Mathworks' `cdfplot1 documentation to understand the concept of "empirical cdf". Again, only when you observe a sample can you increase the cdf.
If you really want to "get" a smooth curve, either 1) add more points so that the discontinuous line looks smoother, or 2) find any statistical model of whatever you are working on, and plot the analytic function instead.

Outline your hand with splines (Matlab)

I'm trying to write a script so that one can put his hand on the screen, click a few points with ginput, and have matlab generate an outline of the persons hand using splines. However, I'm quite unsure how you can have splines connect points that result from your clicks, as they of course are described by some sort of parametrization. How can you use the spline command built into matlab when the points aren't supposed to be connected 'from left to right'?
The code I have so far is not much, it just makes a box and lets you click some points
FigHandle = figure('Position', [15,15, 1500, 1500]);
rectangle('Position',[0,0,40,40])
daspect([1,1,1])
[x,y] = ginput;
So I suppose my question is really what to do with x and y so that you can spline them in such a way that they are connected 'chronologically'. (And, in the end, connecting the last one to the first one)
look into function cscvn
curve = cscvn(points)
returns a parametric variational, or natural, cubic spline curve (in ppform) passing through the given sequence points(:j), j = 1:end.
An excellent example here:
http://www.mathworks.com/help/curvefit/examples/constructing-spline-curves-in-2d-and-3d.html
I've found an alternative for using the cscvn function.
Using a semi-arclength parametrisation, I can create the spline from the arrays x and y as follows:
diffx = diff(x);
diffy = diff(y);
t = zeros(1,length(x)-1);
for n = 1:length(x)-1
t(n+1) = t(n) + sqrt(diffx(n).^2+diffy(n).^2);
end
tj = linspace(t(1),t(end),300);
xj = interp1(t,x,tj,'spline');
yj = interp1(t,y,tj,'spline');
plot(x,y,'b.',xj,yj,'r-')
This creates pretty decent outlines.
What this does is use the fact that a curve in the plane can be approximated by connecting a finite number of points on the curve using line segments to create a polygonal path. Using this we can parametrize the points (x,y) in terms of t. As we only have a few points to create t from, we create more by adding linearly spaced points in between. Using the function interp1, we then find the intermediate values of x and y that correspond to these linearly spaced t, ti.
Here is an example of how to do it using linear interpolation: Interpolating trajectory from unsorted array of 2D points where order matters. This should get you to the same result as plot(x,y).
The idea in that post is to loop through each consecutive pair of points and interpolate between just those points. You might be able to adapt this to work with splines, you need to give it 4 points each time though which could cause problems since they could double back.
To connect the start and end though just do this before interpolating:
x(end+1) = x(1);
y(end+1) = y(1);

How to plot a graph by using looping in time?

I want to plot a graph of position, velocity and acceleration of a robot joint, but I don't know how to plot it. This is my equation:
(position)
for 0<=t<=tblend,
y = theta1s+((0.5.*acc1).*(t^2));
for tblend<t<tf-tblend,
y = -195.21+(52.08.*t);
for tf-tblend<t<=tf,
y = 20-15.*((5-a)^2);
What command must I use to plot this graph? If possible, I want to display the equation of y too.
First create the grid of t values assuming a stepsize (here I picked 0.1) and the final value you mention called tf:
t = 0:0.1:tf;
Then use logical indexing to apply different functions to different regions of this grid of values:
y = ( theta1s+((0.5.*acc1).*(t^2)) ).*(0 <= t).*(t<=tblend) + ...
( -195.21+(52.08.*t)).*( tblend<t).*(t<tf-tblend) + ...
( 20-15.*((5-a)^2) ).*(tf-tblend<t).*(t<=tf);
This will apply the piecewise definitions of the function y by multiplying each difference piece by a logical that is 1 only on the region where it applies and 0 elsewhere. Then a simple
plot(t,y)
will show you the plot. For printing this functions, you'll need to format the title of your plot figure window using Matlab's native LaTeX syntax. Look up and use the LaTeX command \begin{cases} ... \end{cases} for the piecewise function stuff. You can pass most of this straight to the title() command.
For another solution, if you have the signal processing toolbox, you can just use the built-in
heaviside(t)
function. Suitably change the value of t for each left endpoint of a new segment of the piecewise function and then subtract and corresponding heaviside() term for each right endpoint of a segment. If you don't have the built-in heaviside() function, you can easily find third-party implementations at the Matlab central file exchange.