MATLAB: add a line to 3D plot - matlab

I would like to add a reference line on a 3d plot which follows the surface built with mesh(). I have 3 points in the x and y axis to build the line and so will need to interpolate to find z axis coordinates. Here is my code (with reproducible data) so far:
acceleration_dB = [0 109.3699 118.0084 133.9584 104.3017 110.5423 120.6332 140.6567 144.4194 129.7292]';
frequency = [1 50 50 50 100 100 100 100 100 500]';
voltage = [ 1.0e-04 * 0.0001 0.0968 0.1645 0.2983 0.0278 0.0368 0.0893 0.2785 0.4928 0.0780 ]';
xlin=linspace(0, max(frequency),33);
ylin=linspace(min(acceleration_dB), max(acceleration_dB),33);
[X, Y] = meshgrid(xlin,ylin);
f = scatteredInterpolant(frequency,acceleration_dB,log(voltage));
Z=f(X,Y);
figure();
mesh(X,Y,Z);
hold on
% Add threshold reference line
threshAccel = [97.0870 104.4212 109.5787]
threshFreq = [50 100 500]
Zthresh=f(threshFreq,threshAccel);
plot3(threshFreq,threshAccel,Zthresh,'Color','black','LineWidth',1)
Which gives:
What I would like is the black line following the plane of the surface for the whole length of the x-axis.
Any advice would be greatly appreciated. Thank you!

It is just a problem of range I think. This seems to work pretty well:
threshAccel = [97 97.0870 104.4212 109.5787]
threshFreq = [0 50 100 500]
but I am not sure about that 97 and 0 are the precise values. You should correct them probably.

Related

[matlab]Creating Random Gaussian variables using covariance matrix

[(Workspace)][1]I created random variables using covariance Matrix. I want to generate 300 random two dimensional feature data (length & weight) of each specie ω1 (salmon) and ω 2(bass).
Salmon (ω 1): mean: 65 cm, 22 kg covariance: [20 0.1; 0.1 70]
Sea bass (ω 2): mean : 80 cm, 31 kg covariance: [40 5; 5 50]
After I created Samples, I computed covariance Matrix again just to check out. But I found it totally wrong from the original covariance matrix. Can somebody help me out please? Attached is my code and different result. Please Help Me :(
I believe you might be creating the wrong data, try creating it this way:
% 0. INITILIZATION
clc, clear all, close all
rng default % For reproducibility
N = 200; %Number of samples
% 1. Data info
mu1 = [65 22]';
mu2 = [80 31]';
mu = [mu1 mu2];
covar1 = [20 0.1;0.1 70];
covar2 = [40 5;5 50];
% Data generation
Dset1 = mvnrnd(mu1,covar1,N)';
Dset2 = mvnrnd(mu2,covar2,N)';
figure('name', 'Data set X and X'''), hold on
% Plot the data
plot(Dset1(1,:),Dset1(2,:), 'b.',Dset2(1,:),Dset2(2,:), 'r.')
Also, if you want to check if the data has indeed the proper covariance, use a bigger N, say 5000 for example.

Translating 2D image with RGB colours along axes

I am trying to create my own voronoi diagram. I have an arbitrary shape defined by their x and y coordinates stored in separate vectors. Inside this shape are some points of interest (with known coordinates) that belong to two different groups and act as seeds to the voronoi diagram. As an example, the whole diagram ranges from x=-10 to x=90 and y=-20 to y=60. The boundary shape is not rectangular but falls within the axes range above.
What I have done so far is to create a 3D matrix (100 X 80 X 3), C, with all ones so that the default colour will be white. I then looped through from i=1:100, j=1:80, testing individual pixels to see if they fall within the shape using inpolygon. If they do, I then find out which point is the pixel closest to and assign it a colour based on whether the closest point belongs to group 1 or 2.
All is good so far. I then used imagesc to display the image with a custom axis range. The problem is that the voronoi diagram has the general shape but it is off in terms of position as the pixel coordinates are different from the actual world coordinates.
I tried to map it using imref2d but I do not know how it really works or how to display the image after using imref2d. Please help me on this.
I am open to other methods too!
Thank you!
Edit:
As requested, let me give a more detailed example and explanation of my problem.
Let us assume a simple diamond shape boundary with the following vectors and 4 points with the following coordinate vectors:
%Boundary vectors
Boundary_X = [-5 40 85 40 -5];
Boundary_Y = [20 50 20 -10 20];
%Point vectors
Group_One_X = [20 30];
Group_One_Y = [10 40];
Group_Two_X = [50 70];
Group_Two_Y = [5 20];
Next I plot all of them, with different groups having different colours.
%Plot boundary and points
hold on
plot(Boundary_X,Boundary_Y)
scatter(Group_One_X,Group_One_Y,10,'MarkerFaceColor','Black',...
'MarkerEdgeColor','Black')
scatter(Group_Two_X,Group_Two_Y,10,'MarkerFaceColor','Red',...
'MarkerEdgeColor','Red')
hold off
axis([-10, 90, -20, 60])
This is the result:
Boundary with points
Next I test the whole graph area pixel by pixel, and colour them either cyan or yellow depending on whether they are closer to group 1 or 2 points.
%Create pixel vector with default white colour
C=ones(100,80,3);
Colour_One = [0 1 1];
Colour_Two = [1 1 0];
%Loop through whole diagram
for i=1:100
for j=1:80
x=i;
y=j
if inpolygon(x,y,Boundary_X,Boundary_Y)
%Code for testing which point is pixel closest to
%If closest to group 1, assign group 1 colour, else group 2
%colour
end
end
end
%Display image
hold on
imagesc(C)
hold off
This is the result
Failed Voronoi Diagram
The shape is somewhat correct for the right side but not for the others. I understand that this because my world coordinates start from negative values but the pixel coordinates start from 1.
Hence I am at a lost as to how can I solve this problem.
Thank you!
One thing to notice is that you have to convert between image and plot coordinates. The plot coordinates are (x,y) where x goes to the right, and y goes up. The matrix coordinates are (i,j) where i goes down, and j to the right. An easy way to do this is with the use of vec_X,vec_Y as shown below.
Another solution for the newer Matlab versions would be - as you said - using imref2d but unfortunately I have no experience with that command.
%Boundary vectors
Boundary_X = [-5 40 85 40 -5];
Boundary_Y = [20 50 20 -10 20];
%Point vectors
Group_One_X = [20 30];
Group_One_Y = [10 40];
Group_Two_X = [50 70];
Group_Two_Y = [5 20];
%Coordinate system
min_X = -10;
max_X = 90;
min_Y = -20;
max_Y = 60;
axis([min_X, max_X, min_Y, max_Y])
%Create pixel vector with default white colour
rows_N = 100;
columns_N = 80;
C=ones(rows_N,columns_N,3);
%These vectors say where each of the pixels is in the plot coordinate
%system
vec_X = linspace(min_X,max_X,columns_N);
vec_Y = linspace(min_Y,max_Y,rows_N);
Colour_One = [0 1 1];
Colour_Two = [1 1 0];
%Loop through whole diagram
for i=1:100
for j=1:80
if inpolygon(vec_X(j),vec_Y(i),Boundary_X,Boundary_Y)
%calculate distance to each point
Distances_One = zeros(size(Group_One_X));
Distances_Two = zeros(size(Group_Two_X));
for k=1:numel(Group_One_X);
Distances_One(k) = norm([Group_One_X(k),Group_One_Y(k)]-[vec_X(j),vec_Y(i)]);%assuming euclidean norm, but can be adjusted to whatever norm you need
end
for k=1:numel(Group_Two_X);
Distances_Two(k) = norm([Group_Two_X(k),Group_Two_Y(k)]-[vec_X(j),vec_Y(i)]);%assuming euclidean norm, but can be adjusted to whatever norm you need
end
if min(Distances_One) < min(Distances_Two);
C(i,j,:) = Colour_One;
else
C(i,j,:) = Colour_Two;
end
end
end
end
%Display image
imagesc(vec_X,vec_Y,C) %lets you draw the image according to vec_X and vec_Y
%Plot boundary and points
hold on
plot(Boundary_X,Boundary_Y)
scatter(Group_One_X,Group_One_Y,10,'MarkerFaceColor','Black',...
'MarkerEdgeColor','Black')
scatter(Group_Two_X,Group_Two_Y,10,'MarkerFaceColor','Red',...
'MarkerEdgeColor','Red')
hold off

Unwanted line shows up in matlab 3d triplet line

I am plotting 3d lines using MATLAB's plot3 command.
I have arranged my data into X, Y, Z triplets to run through the function as such:
Where points is an array with 6 columns.
The 1st three columns in row one are the coordinates of the i'th node of the 1st element. Similarly the 2nd three columns are the j'th node's coordinates.
points =
[x1 y1 z1 x2 y2 z2]
0 0 0 60 0 0
60 0 0 90 0 0
60 0 30 60 0 0
60 0 30 60 30 30
60 30 30 60 30 0
plot3 ( [x1 ;x2] , [y1 ; y2] , [z1 ; z2], '-or')
With some other processing my result is this:
Looking closely at the points table, there is no such line that goes from between points [60 0 0] and [60 30 30]
Does anyone have any advice for how I might remove this unsightly artefact?
Note: The analysis using these elements and nodes are not affected, I suspect it is purely graphical.
Yes, you are correct. It is graphical.
The way MATLAB plots points is that it connects a line between successive points. Therefore, it joins a line between points 1 and 2, then 2 and 3, 3 and 4, etc.
If you want to achieve what you want, so without the diagonal line, you'll need to plot the lines in a particular order. What I would do is first plot the line parallel to the z = 0 axis, then draw the square shape after.
%// Draw parallel line
plot3([90 0], [0 0], [0 0], '-or');
%// Draw square shape
x = [60 60 60 60];
y = [0 0 30 30];
z = [0 30 30 0];
hold on;
plot3(x, y, z, '-or');
axis ij; %// Invert y axis
Take a look at how I defined the square shape. I started from the left of the shape, then traced around in a clockwise manner. I first plot the parallel line, then the square shape after.
This is what I get:
I am trying to plot a system of links that are between nodes, connections are made at nodes, both links and nodes are defined explicitly. For example, one must have nodes1 N1 and N2 to create a link L1(N1,N2). I form this information into an array where row1 = [N1 N2] where N contains a 3 column vector with the cartesian coordinate. I have partitioned out the X,Y,Z vectors from this matrix and attempted to pass them all together into the plot3 command. As shown in a simple case, this lead to the plot of another line segment that was unintentional (frankly I am still not clear as to why). The surefire way that I have found is by looping over the X,Y,Z vectors and plotting the segments individually.
hold on
for i = 1:length(x1)
plot3 ( [x1(i) ;x2(i)] , [y1(i) ; y2(i)] ,[z1(i);z2(i)], '-or')
end
hold off

Reconstruct 3D graph with surf in matlab?

I usually use surf function to plot 3D figures in matlab, but now the data is different, so I am using plot3 and I have the below figure. Do you have any idea how I reconstruct this figure to be more understandable even if by using different function.
To be more concise, I have X values, with each X value there is a value of Y and value of Z.
X = [ 1 ;2 ;4; 8; 16; 32; 64];
Z = [ 1; 1.8 ; 3.46 ; 6.74 ; 13.18 ; 24.34 ; 39.33]
Y = [0 ; 56.92 ; 91 ; 109.95 ; 119 ; 123.57 ; 125.51]
fig = plot3(log(X),Y,Z,'b.-');
XLABEL=[ 1 2 4 8 16 32 64];
set(gca,'XTickLabel',XLABEL);
set(gca,'XTick',log(XLABEL));
YLABEL= [ 0 30 60 90 120 150 180];
set(gca,'YTickLabel',YLABEL);
set(gca,'YTick',YLABEL);
ZLABEL= [0 5 10 15 20 25 30 35 40 45 50 55];
set(gca,'ZTickLabel',ZLABEL);
set(gca,'ZTick',(ZLABEL));
ylim([0 180]);
zlim([0,55]);
grid on
It's difficult to say, because we don't have a context. Common options are:
Plotting x/y and x/z in two separate plots. Precisely readable but difficult to get the connection between y and z. subplot
Plotyy, same as previous but in one plot. Y and Z values which correspond to the same x-value are aligned. plotyy
Use a plot3 as shown above, but connect each point to the x/z plane. (details below)
Project the line on one or multiple planes and draw it there. (Plot the line again, setting x, y or z to 7 0 or 180, which is the location of your axis)
If two axis are of major importance, use a simple 2d plot and represent the third dimension using color/dotsize/annotations etc...
Code for Option 3:
At the end of your code, add the following code:
X2=[X';X';nan(size(X'))];
X2=X2(:);
Y2=[Y';Y';nan(size(Y'))];
Y2=Y2(:);
Z2=[Z';zeros(size(Z'));nan(size(Z'))];
Z2=Z2(:);
hold on
plot3(log(X2),Y2,Z2,'--')
To understand it, you have to know that matlab skips nans while plotting. Thus the code above generates a independent line segment for each point, connecting it to the ground plane.

MATLAB Data Interpolation - Basics

I have a dataset consisting of a position and a signal - the signal is sampled at scattered positions (0, 115, 230....):
0 1.709219858
115 1.676595745
230 1.643026005
345 1.609456265
460 1.574940898
575 1.540898345
690 1.506855792
806 1.473286052
I would like to smooth this data and then interpolate it to fill in the intervening positions i.e.:
0 x
1 x
2 x
3 x
4 x
5 x
6 x
7 x
8 x
9 x
10 x
Where x is the smoothed signal. I've been smoothing data with the commands:
>> hann250=hanning(250);
>> smooth250=conv(signal,hann250,'same');
But I am not sure at all how to interpolate the data - what commands can I use and what would I type? I'm totally new to MATLAB! I am also not sure what interpolation method I need but I intend to try various one's and see (once I know how!). Thanks,
T
You could try spline interpolation:
http://www.mathworks.com/help/matlab/ref/spline.html
% read x, y from your file
xx = linspace(min(x), max(x), 1000); % generate 1000 equally spaced points
yy = spline(x,y,xx); % interpolate
plot(x,y); % original
hold all;
plot(xx,yy); % new
You can use interp1:
data = [0 1.7092
115.0000 1.6766
230.0000 1.6430
345.0000 1.6095
460.0000 1.5749
575.0000 1.5409
690.0000 1.5069
806.0000 1.4733];
index_interp = 0:806; %// indices on which to interpolate
data_interp = interp1(data(:,1),data(:,2),index_interp,'linear');
There are other interpolation methods available in addition to 'linear'; see the above link.