Trouble rotating coordinates about origin - matlab

I'm having some difficulty getting a simple script to work. The goal is to rotate an array of points about the origin using some angle. However, the code I'm using seems not to maintain the magnitude of the vector.
Im using a array where the first column is x coordinate and the second is y coordinate:
for ii=1:1000
angleRads=rand()*2*pi;
randRotPoints(ii,1)=1*cos(angleRads)-0*sin(angleRads);
randRotPoints(ii,2)=0*cos(angleRads)+1*sin(angleRads);
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths1=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
for ii=1:1000
angleRads=rand()*2*pi;
randRotPoints(ii,1)=randRotPoints(ii,1)*cos(angleRads)-randRotPoints(ii,2)*sin(angleRads);
randRotPoints(ii,2)=randRotPoints(ii,2)*cos(angleRads)+randRotPoints(ii,1)*sin(angleRads);
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths2=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
After the first loop, there is a coordinates of magnitude of 1 and random orientation. This is confirmed via the scatter plot and the lengths1 array is all 1s.
However, the second loop that attempts to rotate those coordinates by a second random angle results in seemingly randomly located coordinates (based on the scatter plot), and the lengths are no longer all 1.
Please help me figure out where I've gone wrong with this rotation code. I know that this isn't the most efficient code in terms of performance or number of lines, if you want to provide a better way to do it in terms of efficiency that is fine, but please also state what would be needed to fix the code in its current format as well.
Thanks.

In your second loop you have
randRotPoints(ii,1)=randRotPoints(ii,1)*cos(angleRads)-randRotPoints(ii,2)*sin(angleRads);
randRotPoints(ii,2)=randRotPoints(ii,2)*cos(angleRads)+randRotPoints(ii,1)*sin(angleRads);
i.e. you use the overwritten (rotated) x coordinate when computing the y. Try saving the randRotPoints(ii,:) vector before rotating it, and using the saved value on the right hand side.
As for making it more efficient:
The more readable solution
You can make the code much more readable by explicitly defining the rotation matrix for each point
for ii=1:1000
angleRads=rand()*2*pi;
rotmat=[cos(angleRads) -sin(angleRads); sin(angleRads) cos(angleRads)];
randRotPoints(ii,:)=rotmat*[1; 0];
%note that this is equivalent to
%randRotPoints(ii,:)=[cos(angleRads); sin(angleRads)];
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths1=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
for ii=1:1000
angleRads=rand()*2*pi;
rotmat=[cos(angleRads) -sin(angleRads); sin(angleRads) cos(angleRads)];
randRotPoints(ii,:)=rotmat*(randRotPoints(ii,:).');
end
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths2=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
In order to spare some code-duplication you could also define a rotmatfun=#(angleRads) [cos(angleRads) -sin(angleRads); sin(angleRads) cos(angleRads); function, then you can just say rotmat=rotmatfun(angleRads); in the loops.
The more efficient solution
You can do away with your loops entirely by making use of the vectorized notation:
N=1000; %number of points
angleRads=rand(N,1)*2*pi;
randRotPoints=[1*cos(angleRads)-0*sin(angleRads), ...
0*cos(angleRads)+1*sin(angleRads)]; %matrix of size [N,2]
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths1=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);
angleRads=rand(N,1)*2*pi;
randRotPoints=[randRotPoints(:,1).*cos(angleRads)-randRotPoints(:,2).*sin(angleRads), ...
randRotPoints(:,2).*cos(angleRads)+randRotPoints(:,1).*sin(angleRads)];
figure;
scatter(randRotPoints(:,1),randRotPoints(:,2));
lengths2=sqrt(randRotPoints(:,1).^2+randRotPoints(:,2).^2);

Related

Detect parallel lines using Hough transform in matlab

Suppose there is a binary image of a black background and white lines "plotted" on it, i.e., they aren't burnt onto the image. For example:
I need to retain only the lines that are parallel to atleast one of the other lines in the picture. If not perfectly parallel, at least close enough to be parallel(perhaps a variable that can control the degree of parallelism would help with that). In other words, if I choose a particular line and it has one or more lines that are parallel to it, I retain it, else I discard it. I need to do that for all lines in the image.
I came across Hough transform but I'm having trouble understanding how to use the bins to check the orientations and determine parallel lines. Or is there a better way to go about this?
Also, since the lines aren't a part of the image and are just plotted on it, I don't have an image to feed into the Hough Transform function. Can I use the output of the plot function as input directly? This is the code I wrote to plot the white lines:
Location1 is a m-by-2 matrix that contains the coordinates to draw the lines.
figure; imshow(blackImage);
hold on ;
for i=1:size(Location1,1)-1
h = plot([Location1(i,1) Location1(i+1,1)], [Location1(i,2) Location1(i+1,2)]) ;
set(h,'linewidth', .1, 'color', 'b') ;
end
Any help would be appreciated.
Given that
for i=1:size(Location1,1)-1
% one line = Location1(i,:) to Location1(i+1,:)
end
then
theta = atan2(diff(Location1(:,2)),diff(Location1(:,1)));
But since lines are parallel even if their theta is in the opposite direction, you want to map all angles to half a circle:
theta = mod(theta,pi/2);
Now theta is in the range [-π/2,π/2].
To find similar angles:
[s,i] = sort(theta);
k = find(diff(s)<0.01); % diff(s) is always positive because s is sorted
i = i([k,k+1]);
theta(i) % <-- sets of similar angles
% Location1(i,:),Location1(i+1,:) <- corresponding lines

MATLAB Plotting Contour Map from Different Plots

I am trying to write a MATLAB script to give me a contour map. The contour map must be created from inputs that I generated from 100 images.
The story is like this:
I have 100 images on which I ran an image processing algorithm for optimization. Now, I got their energy curves. So, I have 100 energy curves. I want to create a contour map that will show me where the points are denser on the plot. (the energy curves are plotted as energy vs. iteration with fixed number of iterations)
The following is my variable:
energy(iteration,numImages)
Hope I explained it well.
Thanks in advance.
I interpret your question to boil down to how can I create a surface plot with colors according to the energy found in energy. I would solve this by using the contour function with a grid generated using meshgrid. If each image is described in 1000 data points with 100 files the plot can be generated as follows:
% using stuff as random junk instead of energy
numPoints = 1000;
numFiles = 100;
stuff = rand(1000,100); % replace with actual information
[X, Y] = meshgrid(1:numFiles, 1:numPoints);
contour(X,Y,stuff);
You can also create a 3D surface plot using surf and the same logic.
From what i see of you graph (and using the comments also), one possible way is to use plot3 to plot a line in 3D for every plot.
For doing so, you can use something like this code:
x=(0:0.01:1)';
aexp=zeros(100,numel(x));
hold on
for ii=1:100;
% aexp(ii,:)=exp((-x+ii/10)); %exponential
aexp(ii,:)=exp(-(x-ii/100).^2); %~gaussian
% aexp(ii,:)= x*ii; %linear increase
plot3(x,aexp(ii,:),ii*ones(1,numel(x)));
end
% set(gca,'yscale','log'); % uncomment if you need logscale.
giving
I have a few options of plot. It always plot from the XY view. I changed by hand, but you can use the view command. Notice that i used a simple counter to make the spacing in the z direction.
In a similar manner, you can plot using the contour. For my code, after the data have been generated in the for loop, remove/comment the plot3 and add:
contour(aexp) %outside the for loop,
giving
Notice that i have not really take care what i'm plotting. You can find more info on contour in the Matlab page .
You commented that the x-axis should be number of iterations, y-axis should be energy and z-axis should be the information containing how many lines are passing through from some areas. For this, make a qq variable, being it qq=number_of_lines(number of iterations,energy) . Make a discrete grid for the energy if you don't have one. Number of iterations is probably discrete anyway. The function is you who need to devise, but i would go for something which checks the number of lines for every energy and every iteration. In this case you will have the z-function that depends on y and x, that is the case to use contour or surface.
My function above make a line for every ii point, to have a 3d function. An edition for another extra loop is not hard. Just remember to have the same regular grid for every point, otherwise you will have trouble.

3D plotting of a time-dependent function in Matlab

I have a function f(x,y,t), where for each time point t I have a 2D line plot of x vs. y. I would like to somehow stack all these 2D plots next to each other so that I see the evolution in time t (but not an animation, just a stationary plot). Both x and y variables hold 100 values, and I repeat the calculation t=3500 times. I've organized the output of a function in a 2x100x3500 matrix.
I know that there is a very simple way to make a 3D plot of this matrix, but I have big trouble finding it. Any help is appreciated.
Use waterfall
figure
[X,Y,Z] = peaks(30);
waterfall(X,Y,Z)

Plot all lines creating mesh in matlab/octave plot

I make point plots like this one:
But now I need to plot all the lines between the points as well to create rectangular mesh under a deformation (i.e. do the connection to the closest neighbors in x and y direction - not connect all the points with all the points).
How can I convince matlab/octave to do that?
The code I have used is here:
%T,H,W and k are defined above, it doesn't matter for the plot.
for ii=1:2:H
for jj=1:2:W
k=0.1;
x=jj;
y=ii;
U(ii,jj)=7*exp(0.05*(y-H))*cos(k*x-T);
V(ii,jj)=4*exp(0.1*(y-H))*sin(k*x-T);
X(ii,jj)=jj;
Y(ii,jj)=ii;
end
end
plot(X+U,Y+V,'k.');
A plot as you want it is easily done with mesh(X,Y,Z).
The problem with your code is that you have a lot of zeros in your matrices. These might be intentional. In that case I could provide another solution. But mesh() connects neighboring points in a matrix. Therefore having the 0 in every second line and row would connect every point to (0,0). The easiest way is to just let your ii,jj grow in steps of 1.
%T,H,W and k are defined above, it doesn't matter for the plot.
H = 20;
W = 40;
T = 2*pi;
for ii=1:1:H
for jj=1:1:W
k=0.1;
x=jj;
y=ii;
U(ii,jj)=7*exp(0.05*(y-H))*cos(k*x-T);
V(ii,jj)=4*exp(0.1*(y-H))*sin(k*x-T);
X(ii,jj)=jj;
Y(ii,jj)=ii;
end
end
plot(X+U,Y+V,'k.');
hold on
mesh(X+U, Y+V, zeros(size(X)));

Contouring a mesh and assigning magnitude arrows in Matlab

I want to assign vector to a contourf graph, in order to show the direction and magnitude of wind.
For this I am using contourf(A) and quiver(x,y), where as A is a matrix 151x401 and x,y are matrices with the same sizes (151x401) with magnitude and direction respectively.
When I am using large maps i get the position of the arrows but they are to densily placed and that makes the graph look bad.
The final graph has the arrows as desired, but they are to many of them and too close, I would like them to be more scarce and distributed with more gap between them, so as to be able to increase their length and at the same time have the components of the contour map visible.
Can anyone help , any pointers would be helpful
i know its been a long time since the question was asked, but i think i found a way to make it work.
I attach the code in case someone encounters the same issues
[nx,ny]= size(A) % A is the matrix used as base
xx=1:1:ny; % set the x-axis to be equal to the y
yy=1:1:nx; % set the y-axis to be equal to the x
contourf(xx,yy,A)
hold on, delta = 8; %delta is the distance between arrows)
quiver(xx(1:delta:end),yy(1:delta:end),B(1:delta:end,1:delta:end),C(1:delta:end,1:delta:end),1) % the 1 at the end is the size of the arrows
set(gca,'fontsize',12);, hold off
A,B,C are the corresponding matrices ones want to use