How to patch in a for loop - matlab

i want to patch points to obtain a square and do it for all other points on the axis, but i want to do it in a for loop.. Thereafter, i would apply some transformation properties to the patched points. This is what i have done so far. Any help will be well appreciated.
whitebg('g')
axis on
% first patch point on the axis
pts2 = [0 0 1 1 0;0 1 1 0 0];
% last patch point on the axis
pts3 = [29 29 30 30 29;29 30 30 29 29];
[n m] = size(pts2);
[o p] = size(pts3);
axis([0 30 0 30])
shg
theta=0;
dx=0;
dy=0;
d=patch(pts1(1,1:end),pts1(2,1:end),'b*-');
for pts1 = pts2:pts3
if (d==patch(pts1(1,1:end),pts1(2,1:end),'b*-'))
delete(d)
end
%function to process
rot = [cosd(theta) sind(theta);-sind(theta) cosd(theta)];
trans = [1 0 dx;0 1 dy; 0 0 1];
homogeneous_rot = eye(3);
homogeneous_rot(1:2,1:2) = rot;
homogeneous_pts1 = [pts1; ones(1,5)];
trans_pts1 = trans*homogeneous_rot*homogeneous_pts1;
hold off
f=patch(trans_pts1(1,1:end),trans_pts1(2,1:end),'r*-');
draw now
end

Related

matlab - line equation to 2D matrix with values of 1 and 0

As the title says, I want to covert a line(or any equation) to 2D matrix.
For example: If I have a line equation y = x, then I want it to be like:
0 0 0 0 0 1
0 0 0 0 1 0
0 0 0 1 0 0
0 0 1 0 0 0
0 1 0 0 0 0
1 0 0 0 0 0
and the length of rows and columns can be variable.
Is there a function or method to implement that?
use meshgrid to get x-y grids:
% set resolution parameters
xmin = 1;
xmax = 100;
dx = 0.1;
ymin = 1;
ymax = 100;
dy = 0.1;
% set x-y grid
[xg, yg] = meshgrid(xmin:dx:xmax, ymin:dy:ymax);
% define your function
f = #(x) (x - 30).^2;
% apply it on the x grid and get close y values
D = abs(f(xg) - yg);
bw = D <= 1;
figure;
imshow(bw);
% flip y axis
set(gca,'YDir','normal')
you get:
and then you can further dilate/erode/skeletonize the output
Given x and y coordinates, how to fill in a matrix with those coordinates? As it is said, just do it in a for loop, or use the "sub2ind" function.
% x,y coordinates
x=0:.01:30;
y=10*sin(2*pi*.1*x);
% add offset so that (x,y)-coordinates are always positive
x=x+abs(min(x))+1;
y=y+abs(min(y))+1;
figure,plot(x,y,'.');axis tight
x=ceil(x); y=ceil(y);
im=zeros(max(y),max(x));
ind=sub2ind(size(im),y,x);
im(ind)=1;
figure,imagesc(im),axis image, axis xy;colormap gray;axis tight
xlabel('x'); ylabel('y')
Why not doing it on your own? You loop through all x-coordinates of the matrix that you (probably scaled) use as the x for your function and get an y out, that you (probably scaled) can round and then use as a y coordinate for your matrix to set the 1.

Insert picture from file in pcolor cells

I have a matrix a and I want to add pictures from my computer to certain cells whenever I display pcolor. I want to add pictures where the ones are. How would I go about that if the picture is in the same directory as the matlab file?
code:
a=[
1 0 0;
1 1 0;
0 0 0];
b=[NaN NaN NaN];
a = [a;b];
b = [b NaN];
b = b.';
a = [a b];
Cmap = [1 1 1];
colormap(Cmap);
pcolor(a)
I also have been noticing with pcolor that it shifts the matrix by 180 degrees, why is it that so?
This is the pcolor plot that I get:
I need something like this:
Here you see the image within pcolor cells, how can I accomplish this?
I will answer my own question this was what I did. I hope this can also help others.
a=[
1 0 0 0;
1 1 0 0;
0 0 0 0;
0 0 0 0];
aa = a;
ac = aa;
b=[NaN NaN NaN NaN];
a = [a;b];
b = [b NaN];
b = b.';
a = [a b];
I = imread('redirt.jpg');
J = imresize(I, 3, 'nearest');
[x , y] = size(aa);
delete(findall(gcf,'Tag','8puzzle'))
pos=get(gca,'position'); % getting the position
% calculating position
width=pos(3)/(y);
height =pos(4)/(x);
Cmap = [1 1 1];
colormap(Cmap);
pcolor(a)
axis off
% loop over the positions/cells you want to place image
for i=1:x
for j=1:y
if(aa(i,j) == 1)
% image position
axes('pos',[pos(1)+width*(i-1),pos(1)+height*(j-1),width,height], 'Tag','8puzzle');
% Show image
imshow(J)
end
if (i == 4 && j == 4)
axes('pos',[pos(1)+width*(i-1),pos(1)+height*(j-1),width,height], 'Tag','8puzzle');
% Show image
imshow('vacum.jpg')
end
end
end
set(gca, 'Ydir', 'reverse');
The image overlaps the cells just a little however, it is does not interfere with the display.

Generating a 3D binary mask of geometric shapes in Matlab

I would like to generate a 3D binary mask which represents an ellipsoid with centers xc,yc,zc and radiuces xr,yr,zr.
I noticed that the function ellipsoid generates a mesh of points given these parameters. However, I want the data to be represented by a binary matrix (in my case, of size [100,100,100]), and not a mesh.
My Parameters are:
mask = zeros(100,100,100);
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
Thanks in advance!
To generate a binary mask of shapes which can use an equation you can follow the steps:
Generate a mesh (with ndgrid). Make sure the domain limits includes the volume/surface mask, and choose the mesh resolution according to your needs.
Use the volume/surface equation to generate a binary mask, by doing a simple logical comparison of the coordinates with the equation.
Simple 2D example:
Let's define a simple ellipse (in 2D).
%% // Simple 2D example
xc = 5 ; yc = 6 ; %// ellipse center = (5,6)
xr = 3 ; yr = 2 ; %// ellipse radiuses
xbase = linspace(0,10,11) ; %// temporary variable used to send to "ndgrid"
[xm,ym] = ndgrid( xbase , xbase ) ; %// generate base mesh
mask = ( ((xm-xc).^2/(xr.^2)) + ((ym-yc).^2/(yr.^2)) <= 1 ) %// get binary mask
Gives you the binary mask:
mask =
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Granted you can hardly recognise an ellipse in the mask but I kept the resolution low to be able to display it as text. You can easily increase the resolution by defining a finer mesh.
3D Ellipsoid:
Well, it's exactly the same method, except we are going to add one dimension to the mesh, and use the 3D equation of the ellipsoid. So for your precise case:
%% // 3D ellipsoid
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
xbase = linspace(1,100,100) ;
[xm,ym,zm] = ndgrid( xbase , xbase , xbase) ;
mask = ( ((xm-xc).^2/(xr.^2)) + ((ym-yc).^2/(yr.^2)) + ((zm-zc).^2/(zr.^2)) <= 1 ) ;
I cannot show you a text output with these kind of 3D arrays, but your mask is now a 3D logical array containing true inside the ellipsoid and false elsewhere.
If I understood your question correctly, this should work:
mask = zeros(100, 100, 100);
%//your ellipsoid properties
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
for x=1:100
for y=1:100
for z=1:100
if ( ((x-xc)/xr)*((x-xc)/xr) + ((y-yc)/yr)*((y-yc)/yr) + ((z-zc)/zr)*((z-zc)/zr) < 1 )
mask(x,y,z) = 1; %//set elements within ellipsoid to 1
end
end
end
end
You can do this with Heaviside functions, this probably needs a bit more thought to get exactly what you want but as a start,
close all
clear all
%Setup Domain
maxdomain = 100;
mindomain = 0.;
step = 1.0;
X = mindomain:step:maxdomain;
Y = mindomain:step:maxdomain;
Z = mindomain:step:maxdomain;
[x,y,z] = meshgrid(X,Y,Z);
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
r2 = xr/2;
r = sqrt((x-xc).^2/xr + (y-yc).^2/yr + (z-zc).^2/zr);
u = heaviside(r-r2);
%Plot Surface of sphere
p = patch(isosurface(x,y,z,u));
isonormals(x,y,z,u,p)
set(p,'FaceColor','red','EdgeColor','none');
camlight ; alpha(0.6);
xlabel('x'); ylabel('y'); zlabel('z');
daspect([1,1,1]); view(3);
axis tight; camlight; camlight(-80,-10);
lighting gouraud;
which for your values above looks like,
and forxr = 15; yr = 45; zr = 15;,
The Heaviside function can be defined using,
function [out]=heaviside(x)
out=0.5.*(sign(x)+1.0);
end
if the Symbolic Math Toolbox is not available.

How do I create a plot like this grid in MATLAB?

I have data like this
-1 -1 -1 1 0 0 1 1 -1 0 1 -1 0 1
where each element of the vector is one of a several states. In this case (which is arbitrary and obviously only an example), are -1 0 1. I'm trying to make a plot like this grid:
The closest I was able to get was with a combination of spy and various tweaks:
%% ARBITRARY example data
states = [-1 0 1];
data = [-1 -1 -1 1 0 0 1 1 -1 0 1 -1 0 1];
%% Approximate plot using sparse matrix and spy
T = size(data, 2);
num_states = size(states, 2);
g = zeros(num_states, T);
for idx = 1:T
jdx = find(data(idx) == states, 1, 'first');
g(jdx, idx) = 1;
end
g = sparse(g);
%% Tweak plot
obj = figure();
obj.Color = 'white';
spy(g, 30)
s = obj.Children(1);
s.XLim = [1 T];
s.YLim = [1 num_states];
s.XLabel.String = '';
s.XGrid = 'on';
s.YTick = 1:num_states;
s.YTickLabel = num2cell(states);
s.GridLineStyle = '-';
s.YGrid = 'on';
However, this is far from ideal, since a) it's not actually a shaded grid, and b) the ticks on the y-axis are in descending order, starting from the bottom, because this is how spy functions, among other problems. How do I make a plot like this? I'm using MATLAB 2015b on a Windows 7 64-bit machine.
You'll want to play around with colours and grids, but this should be sufficient to get started:
data = [-1 -1 -1 1 0 0 1 1 -1 0 1 -1 0 1];
states = flipud(unique(data)');
im = bsxfun(#eq,data,states);
image(im);
colormap([1 1 1;0 0 0]);
axis equal;
axis tight;
set(gca,'XTick',1:length(data));
grid minor
set(gca,'YTickLabel',states);
The above results in

Why does my 3 axes system coordinate orientation change x with y values?

I am using Matlab and Euler Angles in order to reorient a 3axes coordinate system. Specifically,
Rz = [cos(ψ) sin(ψ) 0;-sin(ψ) cos(ψ) 0;0 0 1];
Ry = [cos(φ) 0 -sin(φ);0 1 0;sin(φ) 0 cos(φ)];
Rx = [1 0 0;0 cos(θ) -sin(θ);0 sin(θ) cos(θ)];
Rtotal = Rz*Ry*Rz
Then I loop through my old system coordinates (x,y,z) and make a vector coord_old. Then I get the reoriented system with (xn,yn,zn)
for i=1:size(num,1)
coord_old = [x(i,1);y(i,1);z(i,1)];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
My issue is that when θ,φ,ψ≃0 then x->-y and y->x and when θ,φ≃0 and ψ=90 then x and y will not rotate! That means that when x,y should rotate they don't and when they shouldn't rotate they stay as they were!
--EDIT--
For example, when ψ=20.0871, φ=0.0580 and θ=0.0088 I get these results
See that x->-y and y->x while z doesn't change at all!
Any thoughts?
Ok, I see two main problems here:
Rtotal = Rz*Ry*Rz is probably not what you want since Rz is multiplied twice. I think you mean Rtotal = Rz*Ry*Rx.
Your rotation matrix seems to be incorrect. Check this Wikipedia artice to get the correct signs.
Here a corrected rotation matrix:
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rx;
With this matrix I get the correct results:
x=1; y=2; z=3;
psi=0; phi=0; theta=0;
[xn,yn,zn] >> 1 2 3
x=1; y=2; z=3;
psi=90/180*pi; phi=0; theta=0;
[xn,yn,zn] >> -2 1 3
And here a full graphical example of a cube in 3d-space:
% Create cube (not in origin)
DVert = [0 0 0; 0 1 0; 1 1 0; 1 0 0 ; ...
0 0 1; 0 1 1; 1 1 1; 1 0 1];
DSide = [1 2 3 4; 2 6 7 3; 4 3 7 8; ...
1 5 8 4; 1 2 6 5; 5 6 7 8];
DCol = [0 0 1; 0 0.33 1; 0 0.66 1; ...
0 1 0.33; 0 1 0.66; 0 1 1];
% Rotation angles
psi = 20 /180*pi; % Z
phi = 45 /180*pi; % Y
theta = 0 /180*pi; % X
% Rotation matrix
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rz;
% Apply rotation
DVertNew = Rtotal * DVert';
% Plot cubes
figure;
patch('Faces',DSide,'Vertices',DVert,'FaceColor','flat','FaceVertexCData',DCol);
patch('Faces',DSide,'Vertices',DVertNew','FaceColor','flat','FaceVertexCData',DCol);
% Customize view
grid on;
axis equal;
view(30,30);
When I use your code and insert 0 for all angles, I get Rtotal:
Rtotal =
1 0 0
0 1 0
0 0 1
This is the identity matrix and will not change your values.
You have an error in your matrix multiplication. I think you should multiply: Rtotal*coord_old. I think you are missing the _old. depending on what is in you coordvariable, this may be the bug.
When I run:
for i=1:size(1,1)
coord_old = [1;2;3];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
I get the correct result:
coord_new =
1
2
3
Thank you both #Steffen and #Matt. Unfortunately, my reputation is not high enough to vote Up your answers!
The problem was not with Rtotal as #Matt correctly stated. It should be as it was Rz*Ry*Rx. However, both your ideas helped me test my code with simple examples (5 sets of coordinates and right hand rule), and realize where my (amateur) mistake was.
I had forgotten I had erased parts of codes where I was expressing my angles to degrees... I should be using sind & cosd instead of sin and cos.