You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
I need to find the angle from horizontal that tangents to a curve make for multiple points
26 views (last 30 days)
Show older comments
Hi All,
I have [x,y] coordinates that form a convex shape, I need to find the tangent and subsequently the angle from horizontal that each tangent makes at each [x,y] coordinate.
I have used two different approaches so far but I have struggled with both. Firstly, I attempted to use polyfit to create an equation from the points, then polyder to find the derivative and finally polyval to find the gradients at each point. I got really small values for the gradient that don't make sense to me.
Secondly, I am attempting to use a system whereby I find the slope with s(i) = ( y(i+1)-y(i-1) ) / ( x(i+1) - x(i-1) ). Then I need to find the expression for the line. I am struggling with how to set up a for loop where I can select the +1 and -1 values of x and y within the same loop and how to create an equation for the line.
The 2nd image that I have attached explains exactly what I am trying to acheive.
Can anyone help me out?
global rmax deltar npi npj th gamma Ma T_inf V_inf cp_air rho_air R_air
rmax = rmax + deltar;
x = rmax.*cos(th);
y = rmax.*sin(th);
coord = [x, y];
p = polyfit(x,y,2);
d = polyder(p);
val = polyval(d, x);
Accepted Answer
Star Strider
on 8 Aug 2020
I am not certain what you want to do, or the result you want.
See if this approaches what you want to do:
rmax = 0.25;
th = linspace(pi/2, -pi/2, 25);
h = diff(th(1:2));
x = rmax.*cos(th);
y = rmax.*sin(th);
dx = gradient(x, h); % Numerical Derivative: dx
dy = gradient(y, h); % Numerical Derivative: dy
slope = dy ./ dx;
figure
plot(x, y, '+')
hold on
quiver(x, y, dx, dy, '-r') % Draw ‘quiver’ Arrows
hold off
axis('equal')
The advantage of using gradient rather than diff is that gradient is more accurate, and the output is the same size as the input.
21 Comments
Laurence Maskell
on 8 Aug 2020
Thanks for the reply, apologies that it was not clear what I am attempting to achieve. I only have [x,y] coordinates. I have attached a 2nd image to more accurately describe what I am trying to achieve.
Star Strider
on 8 Aug 2020
My pleasure!
Try this:
rmax = 0.25;
th = linspace(pi/2, -pi/2, 25);
h = diff(th(1:2));
x = rmax.*cos(th);
y = rmax.*sin(th);
dx = -gradient(x, h); % Numerical Derivative: dx
dy = -gradient(y, h); % Numerical Derivative: dy
slope = -atan2d(dy, dx); % Angle Calculation (Degrees)
figure
plot(x, y, '+')
hold on
quiver(x, y, dx, dy, '-r') % Draw ‘quiver’ Arrows
hold off
axis('equal')
angstr = sprintfc('\\angle %.0f \\circ',slope);
text(x, y, angstr, 'HorizontalAlignment','left')
You may need to experiment with this to get the exact result you want. (I restricted the points to 25 to avoid the plot becoming too cluttered.)
Note that in both of the plots you posted, the semicircle is distorted because of the axis aspect ratio. To display it as a true circle, it is necessary to equalise the axis units, as I have in my plot.
.
Laurence Maskell
on 9 Aug 2020
Wow! Thank you so much, I really appreciate you taking the time to provide such a thorough answer. I have a couple of questions if you wouldn't mind helping me out.
What is being achieved with h, I'm not sure what the purpose of this is in regards to the th(1:2) part. I am also receiving a warning message with your solution that I cannot seem to remove. Any ideas why this might be happening? I'm getting the same warning message for all angles.
h = diff(th(1:2));
Warning: Error updating Text.
String scalar or character vector must have valid interpreter syntax:
\angle 8 \circ
> In defaulterrorcallback (line 12)
In ablationModel>plotResults (line 555)
In ablationModel (line 204)
Star Strider
on 9 Aug 2020
Edited: Star Strider
on 9 Aug 2020
My pleasure!
The gradient function needs the step size (difference between adjacent elements of the first argument) in order to calculate the numerical derivative correctly. The ‘h’ value (here being -0.1309) provides that. The value defaults to 1, however that may not provide the correct result.
I am not certain what the problem is with the text call, since it worked when I ran it. (I am using R2020a, although this should work for all recent releases.) It might be necessary to specify the interpreter:
text(x, y, angstr, 'HorizontalAlignment','left', 'Interpreter','tex')
Without the quiver arrows, and with the plot call changed slightly to:
plot(x, y, '-+')
the plot should look like this:
and with them:
See if it works with that change.
EDIT — (8 Aug 2020 at 22:54)
If it does not work, just use:
angstr = sprintfc('Angle = %.0f °', slope)
instead.
Laurence Maskell
on 10 Aug 2020
Hi, that's solved it! Thank you so much! I do have another problem with the code I'm writing if you wouldn't mind helping me out?
For the angle calculator code part to run, I have to use the variables X and Y. These are listed in the plotResults() function at the bottom of my code. I get the error listed below. The only work around with this I can do is if I comment out the angle calculator section in cp() and then run the code, then remove the comments and run the code again, thus allowing me to select the variables X and Y for the angle calculator. How can I change my code so that I do not recieve this error? I've attached the code below.
Thank you again!
Index in position 1 exceeds array bounds.
Error in ablationModel>cp (line 267)
x_cp = X(npi, :)';
Error in ablationModel (line 110)
cp()
Star Strider
on 10 Aug 2020
As always, my pleasure!
I cannot figure out what ‘X’ is, since it is a global variable, so I have no idea what the problem may be. This is because your code makes extensive use of global variables, and it is essentially impossible to troubleshoot it because of that.
When I add this line just before the line that throws the error:
SizeX = size(X)
the result is:
SizeX =
0 0
so ‘X’ is empty. It is not possible to address any of its contents because it has no contents.
Pass the appropriate values to your functions according to the values those functions require, and completely eliminate all the global variables. This will require an extensive re-write of your code, however it will then at least be possible to understand what the problem is with that line.
If you need to return results from your functions, that is straightforward to do, by declaring your functions with outputs. If all the outputs are requested in the calling workspace, all the results will appear in the workspace that calls the function, and it is then possible to use those results in other parts of the code.
.
Laurence Maskell
on 10 Aug 2020
I see, that is a lesson learnt for sure.
I've just realised, I need to produce different angles for the lower section of the face. Is it possible to change the angle calculation in someway so that the angles past the perpendicular point are negative values of the upper section? As the zoomed in image of the front face that I have attached shows?
Thanks again,
Laurence
Star Strider
on 10 Aug 2020
Probably the easiest way is just to add this line after the initial ‘slope’ calculation assignment:
slope(slope>90) = slope(slope>90) - 180;
so the full code is then:
rmax = 0.25;
th = linspace(pi/2, -pi/2, 25);
h = -diff(th(1:2));
x = rmax.*cos(th);
y = rmax.*sin(th);
dx = gradient(x, h); % Numerical Derivative: dx
dy = gradient(y, h); % Numerical Derivative: dy
slope = -atan2d(dy, dx); % Angle Calculation (Degrees)
slope(slope>90) = slope(slope>90) - 180;
figure
plot(x, y, '+')
hold on
quiver(x, y, dx, dy, '-r') % Draw ‘quiver’ Arrows
hold off
axis('equal')
angstr = sprintfc('\\angle %.0f \\circ',slope);
text(x, y, angstr, 'HorizontalAlignment','left')
That will work for the angles under consideration here.
Laurence Maskell
on 20 Aug 2020
Hi Star Strider,
Apologies for restarting this thread so late after you provided your answer but I was hoping you might be able to provide some assistance with re-writing my code and removing global variables, particularly with the following issue: I define many of my variables at the start of the script, then I call functions and use global variables to perform calculations with those global variables. My question is this, is it still possible to define variables outside of my function and use those same defined variables within the function without using global variables?
Thanks,
Laurence
Star Strider
on 20 Aug 2020
Define the variables once in your workspace, then use the techniques described in Passing Extra Parameters to pass them to each function as necessary.
This way, you know what was passed, and what the values are. If you want to change any of those values, define them specifically inside the function that changes them, and then include them as outputs in the declaration for that function. That also allows you to control their names in the calling workspace, so if you don’t want to overwrite an existing variable with a new value, you don’t have to. You can simply give it a new name or define it as a different array element.
Laurence Maskell
on 20 Aug 2020
That is exactly what I was looking for, thank you. This has created another question, how can I now access the outputs of the function elsewhere in the script to be applied to further functions?
Kind Regards,
Laurence
Star Strider
on 20 Aug 2020
As always, my pleasure.
I thought I explained that. Calculate them within the function, and define them specifically as outputs in the function declaration statement for the function. You need to specifically request them as outputs when you call the function. You can then do whatever you want to witth the new values.
Laurence Maskell
on 22 Aug 2020
Hi Star Strider, I have a further question for you if you wouldn't mind offering some advice. I'm still attempting to eradicate global variables from my script.
In my script, I have a radial face, I perform some calculations that allow me to calculate a new radial distance after some amount of heat input to the face, this radial distance of face removed is called deltar. This allows me to get a final radial distance by calculating [1], (see code lines below), where deltar is a negative [72x1] matrix. I perform this analysis for 10000 iterations, called timeIter and write the results into [2]. When I originally used global variables, I was able to declare X and Y as global at the end of the script, then call upon them to perform the subject of the original question, where we were trying to find the tangent to the horizontal of the position. I am struggling to find a way in which I can call upon the [X, Y] variables so that I can carry out the above code you provided. I cannot think of a way of doing this without using global variables. Would you mind having a look at my code and seeing if you can identify a solution? I would be very grateful.
Kind Regards,
Laurence
rmax = rmax + deltar %{1]
histr(timeIter,:,:) = r; %[2]
for i = timeIter:timeIter
Rgrid = squeeze(histr(i,:,:));
X = Rgrid.*cos(Thgrid);
Y = Rgrid.*sin(Thgrid);
Star Strider
on 22 Aug 2020
Your code is very difficult to follow. You may be stuck with ‘X’ and ‘Y’ being global, because of the way you constructed your code.
Ideally, calculate ‘X’ and ‘Y’ (or create them before any function calls that use them as appropriately-sized matrices of zeros) and return them as outputs from the function that calculates them before you first use them as arguments to other functions, then pass them as arguments to other functions.
I have no idea what your code is supposed to do. I cannot get it to run even with the global matrices, since it immediately throws an error that also does not make sense to me, and stops.
Laurence Maskell
on 24 Aug 2020
Hi Star Strider,
Thank you for the advice, I am going to try an alternative method, I have made a change to the script but am now receiving the erorr below. I have looked at the forums but have been unable to resolve my problem. Perhaps another eye on it might spot something I haven't. I've attached my code as well.
I used a breakpoint on line 77 as the rest of the script still needs further work.
Kind Regards,
Laurence
Error using Ablation_analysis>Cpcalc
Too many input arguments.
Error in Ablation_analysis (line 69)
[Cp_max, Cp, T_0, p_inf, p_0_inf, p_0_1, p_e, p_w, Ma_e, T_e, T_0_e, V_e] = Cpcalc(gamma, Ma, slope, T_inf,
V_inf, cp_air, rho_air, R_air, T_inf);
Star Strider
on 24 Aug 2020
Without looking at anything else, the error is obvious: you are passing too many input arguments to ‘Cpcalc’. That is not something I can solve, since only you know what arguments should be passed to it and what arguments should not.
More Answers (0)
See Also
Categories
Find more on Entering Commands in Help Center and File Exchange
Tags
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)