Plotting and finding the intersection of 2 curves
이전 댓글 표시
i want to plot two curves and find the intersection point of them. Please help me with the code or link to where i can find the answer
댓글 수: 4
Image Analyst
2020년 12월 17일
Are these just lists of numbers (coordinates)? If so attach the arrays so we can help you numerically.
Or do you have analytical formulas that the curves are? If so what are they, so we can help you analytically?
Aizaz Anwer
2020년 12월 17일
Paul Hoffrichter
2020년 12월 17일
편집: Paul Hoffrichter
2020년 12월 17일
Is this what you want? Scenario 1: Someone gives you a .fig file. You get it into Matlab and now you have two curves. (How these curves were created by the sender can be considered unknown.) Now you want to know how to get the (x1, x2) coordinates of the intersection point.
Or is this what you want? Scenario 2:You have two functions, f(x) and g(x). When you plot them, you notice that they interesect. You want a function that gives the intersection point. That is: (x1, x2) = Intersection( x, f, g).
Image Analyst
2020년 12월 17일
Sell = [12,22,28]
Price1 = [15,30,50]
Buy = [10,18,29]
Price2 = [25,42,50]
plot(Sell, Price1, 'b.-', 'LineWidth', 2, 'MarkerSize', 20);
grid on;
hold on;
plot(Buy, Price2, 'r.-', 'LineWidth', 2, 'MarkerSize', 20);
legend('Sell', 'Buy', 'location', 'southeast');

답변 (2개)
Paul Hoffrichter
2020년 12월 17일
0 개 추천
If you have two vectors, x1, y1 that form the curve (x1, y1), and likewise, another curve (x2, y2), then you can get the intersection points using the function by Douglas Schwarz.
or from this function by NS.
Image Analyst
2020년 12월 18일
For the specific case at hand:
Sell = [12,22,28]
Price1 = [15,30,50]
Buy = [10,18,29]
Price2 = [25,42,50]
plot(Sell, Price1, 'b.-', 'LineWidth', 2, 'MarkerSize', 20);
grid on;
hold on;
plot(Buy, Price2, 'r.-', 'LineWidth', 2, 'MarkerSize', 20);
legend('Sell', 'Buy', 'location', 'southwest');
xlabel('Sell or Buy Price in $', 'FontSize', 20);
ylabel('Price1 or Price2 in $', 'FontSize', 20);
% Get equations for the last two line segments.
coeff1 = polyfit(Sell(2:3), Price1(2:3), 1)
coeff2 = polyfit(Buy(2:3), Price2(2:3), 1)
% Find out where the lines are equal.
% ax + b = cx + d. Find x
% x = (d-b) / (a-c)
matchPrice = (coeff2(2) - coeff1(2)) / (coeff1(1) - coeff2(1))
y = coeff1(1) * matchPrice + coeff1(2)
caption = sprintf('Match at x = $%.2f, y = $%.2f', matchPrice, y);
title(caption, 'FontSize', 20);
% Draw lines in dark green color.
darkGreen = [0, 0.5, 0];
line([matchPrice, matchPrice], [0, y], 'Color', darkGreen, 'LineWidth', 2);
line([0, matchPrice], [y, y], 'Color', darkGreen, 'LineWidth', 2);
fprintf('Done running %s.m ...\n', mfilename);

댓글 수: 9
Aizaz Anwer
2020년 12월 19일
Image Analyst
2020년 12월 19일
편집: Image Analyst
2020년 12월 19일
Yes, but that was not the data you originally gave. You didn't say it had to be general and work with any other data so I solved it for only the data you gave.
So how to you think you could solve it? I can think of several ways. Like what if you were to interpolate the curves with a new x axis where each element was one cent. Then use min() to find where they cross. It will be accurate to the nearest cent, which I think is the accuracy that is required.
Aizaz Anwer
2020년 12월 20일
Image Analyst
2020년 12월 20일
So you need it accurate to the nearest nano-cent, even though prices are only used to the nearest cent (as far as I know)?
Aizaz Anwer
2020년 12월 20일
Image Analyst
2020년 12월 20일
If your data is linear, this works:
data = readmatrix('sample data.xlsx');
Sell = data(:, 3);
Price1 = data(:, 2);
Buy = data(:, 1);
Price2 = data(:, 4);
plot(Sell, Price1, 'b-', 'LineWidth', 2, 'MarkerSize', 20);
grid on;
hold on;
plot(Buy, Price2, 'r-', 'LineWidth', 2, 'MarkerSize', 20);
legend('Sell', 'Buy', 'location', 'east');
xlabel('Sell or Buy Price in $', 'FontSize', 20);
ylabel('Price1 or Price2 in $', 'FontSize', 20);
% Get equations for the last two line segments.
coeff1 = polyfit(Sell, Price1, 1)
coeff2 = polyfit(Buy, Price2, 1)
% Find out where the lines are equal.
% ax + b = cx + d. Find x
% x = (d-b) / (a-c)
matchPrice = (coeff2(2) - coeff1(2)) / (coeff1(1) - coeff2(1))
y = coeff1(1) * matchPrice + coeff1(2)
caption = sprintf('Match at x = $%.2f, y = $%.2f', matchPrice, y);
title(caption, 'FontSize', 20);
% Draw lines in dark green color.
darkGreen = [0, 0.5, 0];
line([matchPrice, matchPrice], [0, y], 'Color', darkGreen, 'LineWidth', 2);
line([0, matchPrice], [y, y], 'Color', darkGreen, 'LineWidth', 2);
fprintf('Done running %s.m ...\n', mfilename);

What do you normally plot on the x and y axes?
Image Analyst
2020년 12월 20일
편집: Image Analyst
2020년 12월 20일
Otherwise I suggest you use Star's interpolation method because it's what I'd do. But instead of 50 interpolated points like he used, I'd try this to get accuracy down to the nearest 1/1000 of a cent:
% Find the overall range
minPrice = min([Sell; Price1; Buy; Price2])
maxPrice = max([Sell; Price1; Buy; Price2])
% Interpolate extra points to get more accuracy for non-linear curves.
% We'll get to the nearest 1/1000 of a cent.
numPoints = (maxPrice - minPrice) * 1000;
Then use numpoints in linspace() instead of 50.
Image Analyst
2020년 12월 21일
Why are there two Sell prices at 49 (elements 25 and 26) yet two different prices for those? It will take extra code to get rid of duplicates and average them.
Image Analyst
2020년 12월 21일
OK, I had to put in some lines to repair bad data, like your duplicated Sell prices at 49 (elements 25 and 26). That data repair is in between the --------- lines. Not only does the data repair make it more robust, but the final result does not depend on the curve having a linear relationship. The buy/sell/price plots could be curved. Yay!
Here is the final code and it will be accurate to 1/1000th of a cent.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
data = readmatrix('sample data.xlsx');
Sell = data(:, 3);
Price1 = data(:, 2);
Buy = data(:, 1);
Price2 = data(:, 4);
p1 = plot(Sell, Price1, 'b-', 'LineWidth', 2, 'MarkerSize', 20);
grid on;
hold on;
p2 = plot(Buy, Price2, 'r-', 'LineWidth', 2, 'MarkerSize', 20);
legend([p1, p2], 'Sell', 'Buy', 'location', 'east');
xlabel('Sell or Buy Price in $', 'FontSize', 20);
ylabel('Price1 or Price2 in $', 'FontSize', 20);
%------------------------------------------------------------------------
% DATA REPAIR - FIX BAD DATA
% Now we have a problem with the supplied "Sell" data and need to fix it.
% If some of the "x" arrays have the same price more than once,
% the interpolation step will fail. So we need to average together any duplicates.
[Sell, sortOrder] = sort(Sell, 'Ascend'); % first sort from least to greatest.
% Now sort Price1 the same way.
Price1 = Price1(sortOrder);
% Now we can average all Price1 that have the same Sell price.
Price1 = splitapply(@mean, Price1, findgroups(Sell));
Sell = unique(Sell);
% Now fix Buy and Price2 the same way: (Actually in the supplied data, these arrays were OK.)
[Buy, sortOrder] = sort(Buy, 'Ascend'); % first sort from least to greatest.
% Now sort Price1 the same way.
Price2 = Price2(sortOrder);
% Now we can average all Price1 that have the same Sell price.
Price2 = splitapply(@mean, Price2, findgroups(Buy));
Buy = unique(Buy);
%------------------------------------------------------------------------
% Find the overall range
minPrice = min([Sell; Price1; Buy; Price2])
maxPrice = max([Sell; Price1; Buy; Price2])
% Interpolate extra points to get more accuracy for non-linear curves.
% We'll get to the nearest 1/1000 of a cent.
numPoints = (maxPrice - minPrice) * 1000;
% Get all possible "x" values.
x = linspace(minPrice, maxPrice, numPoints);
% Interpolate the other arrays at the new x points.
Price1a = interp1(Sell, Price1, x);
Price2a = interp1(Buy , Price2, x);
% Find differences at every x value.
priceDifference = abs(Price2a - Price1a);
% Find there the difference is minimum
[minDiff, indexOfMinDiff] = min(priceDifference)
% Get the x value there.
xMatch = x(indexOfMinDiff);
% Find out where the lines are equal.
% ax + b = cx + d. Find x
% x = (d-b) / (a-c)
matchPrice1 = Price1a(indexOfMinDiff)
matchPrice2 = Price2a(indexOfMinDiff)
yMatch = mean([matchPrice1, matchPrice2])
caption = sprintf('Match at x = $%.2f, y = $%.2f', xMatch, yMatch);
title(caption, 'FontSize', 20);
% Draw lines in dark green color.
darkGreen = [0, 0.5, 0];
line([xMatch, xMatch], [0, yMatch], 'Color', darkGreen, 'LineWidth', 2);
line([0, xMatch], [yMatch, yMatch], 'Color', darkGreen, 'LineWidth', 2);
% Legend will update to show these lines but we don't want them.
% so tell legend to only have the two plot lines.
legend([p1, p2], 'Sell', 'Buy', 'location', 'east');
fprintf('Done running %s.m ...\n', mfilename);

카테고리
도움말 센터 및 File Exchange에서 Creating, Deleting, and Querying Graphics Objects에 대해 자세히 알아보기
제품
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
