I got an obstacle in generating an NACA Airfoil graph. Here is the code:
% NACA 6414%
clc
clear
format compact
m1=input('Please enter one digit number for maxi camber line:')
p1=input('Please enter one digit number for distance of m and chordline:')
t1=input('Please enter two digit number for thickness of airfoil:')
m=m1*0.01;
p=p1*0.1;
t=t1*0.01;
x1=[0:0.01:p];
x2=[p:0.01:1];
x=[x1,x2]
yc1=(m*(2*p*x1-x1.^2))/(p^2);
yc2=(m/(1-p)^2)*((1-2*p)+2*p*x2-x2.^2);
yt=(t/0.2)*(0.2969*sqrt(x)-0.1260*x-0.3516*x.^2+0.2843*x.^3-0.1015*x.^4)
yc=[yc1,yc2]
ang1=(atan((m/p^2)*(2*p-2*x1)))*180/pi
ang2=(atan((m/(1-p)^2)*(2*p-2*x2)))*180/pi
ang=[ang1,ang2]
xu=x-yt.*sin(ang)
yu=yc+yt.*cos(ang)
xl=x+yt.*sin(ang)
yl=yc-yt.*cos(ang)
xplot=[xu,xl]
yplot=[yu,yl]
plot(xplot,yplot)
Instead of generating an normal airfoil graph, it comes with an very weird graph which contains many circles on the picture. Can any one help me figure out how to fix that?
Thanks.
Here's the problem, I suspect:
ang1=(atan((m/p^2)*(2*p-2*x1)))*180/pi
ang2=(atan((m/(1-p)^2)*(2*p-2*x2)))*180/pi
ang=[ang1,ang2]
xu=x-yt.*sin(ang)
yu=yc+yt.*cos(ang)
xl=x+yt.*sin(ang)
yl=yc-yt.*cos(ang)
The functions sin and cos expect an input in radians. The output of atan is also in radians, but you're converting it to degrees, which means that the output in xu, yu, etc, which you later plot will be wrong. Try to avoid conversion unless you really need the angles in degrees. Alternatively, you could use the other forms of these functions (sind, cosd, atand, etc) and keep everything in degrees throughout.
Related
I am writing a report for a class and am having some issues with the lines of an unstable plot going beyond the boundary of the graph and overlapping the title and xlabel. This is despite specifying a ylim from -2 to 2. Is there a good way to solve this issue?
Thanks!
plot(X,u(:,v0),X,u(:,v1),X,u(:,v2),X,u(:,v3),X,u(:,v4))
titlestr = sprintf('Velocity vs. Distance of %s function using %s: C=%g, imax=%g, dx=%gm, dt=%gsec',ICFType,SDType,C,imax,dx,dt);
ttl=title(titlestr);
ylabl=ylabel("u (m/s)");
xlabl=xlabel("x (m)");
ylim([-2 2])
lgnd=legend('t=0','t=1','t=2','t=3','t=4');
ttl.FontSize=18;
ylabl.FontSize=18;
xlabl.FontSize=18;
lgnd.FontSize=18;
EDIT: Minimum reproducible example
mgc=randi([-900*10^10,900*10^10], [1000,2]);
mgc=mgc*1000000;
plot(mgc(:,1),mgc(:,2))
ylim([-1,1])
This is odd. It really looks like a Bug... partly
The reason is probably that the angle of the lines are so narrow that MATLAB runs into rounding errors when calculating the points to draw for your limits very small limits given very large numbers. (You see that you don't run into this problem when you don't scale the matrix mgc.
mgc = randi([-900*10^10,900*10^10], [1000,2]);
plot(mgc(:,1),mgc(:,2))
ylim([-1,1])
but if you scale it further, you run into this problem...
mgc = randi([-900*10^10,900*10^10], [1000,2]);
plot(mgc(:,1)*1e6,mgc(:,2)*1e6)
ylim([-1,1])
While those numbers are nowhere near the maximum number a double can represent (type realmax in the command window to see that this is a number with 308 zeros!); limiting the plot to [-1,1] on one of the axes -- note that you obtain the same phenom on the x-axis -- let MATLAB run into precision problems.
First of all, you see that it plots much less lines than before (in my case)... although, I just said to zoom on the y-axis. The thing is, that MATLAB does not recalculate the lines for the section but it really zooms into it (I guess that this may cause resolution errors with regard to pixels?)
Well, lets have a look at the data (Pro-tip, you can get the data of a line from a MATLAB figure by calling this snippet
datObj = findobj(gcf,'-property','YData','-property','XData');
X = datObj.XData;
Y = datObj.YData;
xlm = get(gca,'XLim'); % get the current x-limits
) We see that it represents the original data set, which is not surprising as you can also zoom out again.
Note that his only occurs if you have such a chaotic, jagged line. If you sort it, it does not happen.
quick fix:
Now, what happens, if we calculate the exact points for this section?
m = diff(Y)./diff(X); % slope
n = Y(1:end-1)-m.*X(1:end-1); % offset
x = [(-1-n); (1-n)]./m;
y = ones(size(x))./[-1 1].';
% plot
plot([xMinus1;xPlus1],(ones(length(xMinus1),2).*[-1 1]).')
xlim(xlm); % limit to exact same scale as before
The different colors indicate that they are now individual lines and not a single wild chaos;)
It seems Max pretty much hit the nail on the head as it pertains to the reason for this error is occurring. Per Enrico's advice I went ahead and submitted a bug report. MathWorks responded saying they were unsure it was "unexpected behavior" and would look into it more shortly. They also did suggest a temporary workaround (which, in my case, may be permanent).
This workaround is to put
set(gca,'ClippingStyle','rectangle');
directly after the plotting line.
Below is a modified version of the minimum reproducible example with this modification.
mgc=randi([-900*10^10,900*10^10], [1000,2]);
mgc=mgc*1000000;
plot(mgc(:,1),mgc(:,2))
set(gca,'ClippingStyle','rectangle');
ylim([-1,1])
I'm having an issue with filling a 401x401 matrix. I know exactly what I want to do but I'm struggling to implement it.
I would like for a specific angle (y axis from 30-70) and a specific wavelength (x axis from 400nm-1000nm) the matrix is filled to 401 x 401 to contain the associated reflection coefficient (I have the equations and they're all good).
I thought this would work#
for i=1:length(ANGLE)
angle=ANGLE(i);
etc etc
for i=1:length(wavelengths)
lambda=wavelengths(i);
etc etc
REF(i)=ref;
end
end
I hope you can help, sorry if this is badly worded.
Thanks
Carmel
As m_power pointed out, you should use a different iterator for the internal for loop (and also try to avoid using i and j, as they are commonly used to represent imaginary values). In addition to this, you should reference both a row and column entry for each reflection coefficient entry. Since you want angle in the vertical direction and wavelength in the horizontal direction, you could use something like this:
for ii=1:length(ANGLE)
angle=ANGLE(ii);
etc etc
for jj=1:length(wavelengths)
lambda=wavelengths(jj);
etc etc
REF(ii,jj)=ref;
end
end
Hope this helps.
In Matlab, I've got several points in the 3D space. Those points represent a rope and I would like to draw a line linking all those points. Here is my problem: How the oraganization of those points should be done to have a "simple" and "more or less straigth line". In other words I would like to draw a line linking all the points from the first to the last one but not "going back". Maybe with a simple image i can explain better my problem:
This is what the code should do:
This is what the code shouldn't do:
Some idea of how can I achieve the intended result? How can I organize the points? I'm working with Matlab but if you know any paper where I can read how to do this it will be fine. Thank you.
If you just don't want to go back in the upper direction, the solution that #Dan suggested should be fine. Sort them in that direction before connecting.
However, if that is not a requirement but you are actually looking for a solution without ugly crossings that is as short as possible, you may want to look into solutions for the travelling salesman problem.
If you define the distance between 1 and 9 to be zero, the solution you find to the travelling salesman problem should give you a nice and short rope.
If you want to go for the TSP approach but get a little lost, just try a 'furthest insertion' start position or '2 opt' improvements as that is likely going to give a big improvement over random path selection already with minimal effort.
OK. I've found the right answer (by Gunther Struyf): Sort Coordinates Points in Matlab
In order to visualize the final result just add to Gunther's code the following lines:
row=data(:,1);
col=data(:,2);
figure
scatter(row,col,'r');
hold on
line(row(result),col(result));
The following code shows the same algorithm but for a 3D implementation:
close all;
data = [2,2, 2; 2,3,2 ; 1,2,3 ; 1,3,3 ; 2,1,3 ; 1,1,3 ; 3,2,4 ; 3,3,4 ; 3,1,5; 5,4,6; 7,3,8; 8,9,7; 9,4,7; 6,2,5; 5,8,6; 9,3,8;6,9,2];
row=data(:,1);
col=data(:,2);
frame=data(:,3);
dist = pdist2(data,data);
N = size(data,1);
result = NaN(1,N);
result(1) = 1; % first point is first row in data matrix
for ii=2:N
dist(:,result(ii-1)) = Inf;
[~, closest_idx] = min(dist(result(ii-1),:));
result(ii) = closest_idx;
end
figure
%Ploting the points directly (without sorting)
subplot(2,1,1);
scatter3(row,col,frame,'r');
hold on;
line(row,col,frame);
%Ploting after sorting
subplot(2,1,2);
scatter3(row,col,frame,'r');
hold on
line(row(result),col(result),frame(result));
I have a csv file which contains data like below:[1st row is header]
Element,State,Time
Water,Solid,1
Water,Solid,2
Water,Solid,3
Water,Solid,4
Water,Solid,5
Water,Solid,2
Water,Solid,3
Water,Solid,4
Water,Solid,5
Water,Solid,6
Water,Solid,7
Water,Solid,8
Water,Solid,7
Water,Solid,6
Water,Solid,5
Water,Solid,4
Water,Solid,3
The similar pattern is repeated for State: "Solid" replaced with Liquid and Gas.
And moreover the Element "Water" can be replaced by some other element too.
Time as Integer's are in seconds (to simplify) but can be any real number.
Additionally there might by some comment line starting with # in between the file.
Problem Statement: I want to eliminate the first dip in Time values and smooth out using some quadratic or cubic or polynomial interpolation [please notice the first change from 5->2 --->8. I want to replace these numbers to intermediate values giving a gradual/smooth increase from 5--->8].
And I wish this to be done for all the combinations of Elements and States.
Is this possible through some sort of coding in Matlab etc ?
Any Pointers will be helpful !!
Thanks in advance :)
You can use the interp1 function for 1D-interpolation. The syntax is
yi = interp1(x,y,xi,method)
where x are your original coordinates, y are your original values, xi are the coordinates at which you want the values to be interpolated at and yi are the interpolated values. method can be 'spline' (cubic spline interpolation), 'pchip' (piece-wise Hermite), 'cubic' (cubic polynomial) and others (see the documentation for details).
You have alot of options here, it really depends on the nature of your data, but I would start of with a simple moving average (MA) filter (which replaces each data point with the average of the neighboring data points), and see were that takes me. It's easy to implement, and fine-tuning the MA-span a couple of times on some sample data is usually enough.
http://www.mathworks.se/help/curvefit/smoothing-data.html
I would not try to fit a polynomial to the entire data set unless I really needed to compress it, (but to do so you can use the polyfit function).
There are 2 column vectors A,B containing 100 data values. I intend to plot the MSE(mean square error ) using the following code but all I get is a single dot instead of a line plot. Please help how to go about it.
A=x(:,1);
B=y(:,1);
er=(double(A)-double(B)).^2;
row_er=mean(er,2); % variable changed
plot(row_er);
This script works fine.
A = randn(10, 1);
B = randn(10, 1);
er=(double(A)-double(B)).^2;
row_e=mean(er,2);
plot(row_e)
Probably you have a typo (row_er)
row_e=mean(er,2);
plot(row_er);
Please notice that the command mean returns the mean of a vector (which is one simple value). If you want to plot plot the square error then you just plot((A-B).^2).
But... If you are interested in plotting the mean square error with, say, 10 samples average, you will have a plot with only 10 points (100 / 10 because each 10 data points are averaged to give you one point).
The command would be
plot(blkproc((A-B).^2,[10,1],'mean'))
hope it helps.