How to plot 3D grid (cube) in Matlab - matlab

Hi I would like to plot transparent cube-shaped grid with lines in it. Something like this:
However, I managed only to draw a 2D grid:
[X,Y] = meshgrid(-8:.5:8);
Z = X+1;
surf(X,Y,Z)
I use Matlab R2009b.
If it is impossible to plot this in matlab could you recommend me a software I could use.

Consider this vectorized solution. It has the advantage that it creates a single graphic object:
%# these don't all have to be the same
x = -8:2:8; y = -8:2:8; z = -8:2:8;
[X1 Y1 Z1] = meshgrid(x([1 end]),y,z);
X1 = permute(X1,[2 1 3]); Y1 = permute(Y1,[2 1 3]); Z1 = permute(Z1,[2 1 3]);
X1(end+1,:,:) = NaN; Y1(end+1,:,:) = NaN; Z1(end+1,:,:) = NaN;
[X2 Y2 Z2] = meshgrid(x,y([1 end]),z);
X2(end+1,:,:) = NaN; Y2(end+1,:,:) = NaN; Z2(end+1,:,:) = NaN;
[X3 Y3 Z3] = meshgrid(x,y,z([1 end]));
X3 = permute(X3,[3 1 2]); Y3 = permute(Y3,[3 1 2]); Z3 = permute(Z3,[3 1 2]);
X3(end+1,:,:) = NaN; Y3(end+1,:,:) = NaN; Z3(end+1,:,:) = NaN;
%#figure('Renderer','opengl')
h = line([X1(:);X2(:);X3(:)], [Y1(:);Y2(:);Y3(:)], [Z1(:);Z2(:);Z3(:)]);
set(h, 'Color',[0.5 0.5 1], 'LineWidth',1, 'LineStyle','-')
%#set(gca, 'Box','on', 'LineWidth',2, 'XTick',x, 'YTick',y, 'ZTick',z, ...
%# 'XLim',[x(1) x(end)], 'YLim',[y(1) y(end)], 'ZLim',[z(1) z(end)])
%#xlabel x, ylabel y, zlabel z
axis off
view(3), axis vis3d
camproj perspective, rotate3d on

If you don't mind a few for loops, something like this will work:
clf
figure(1)
for g = 0:.2:2
for i = 0:.2:2
plot3([g g], [0 2], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([0 2], [g g], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([i i], [g g], [0 2])
hold on
end
end
You will just need to make the grid transparent by probably changing line properties, I don't think you can change alpha values to accomplish this. Hope that is helpful.

A more vectorized version of Stephen's answer might be the following:
i = 0:0.2:2;
[X Y] = meshgrid(i,i);
x = [X(:) X(:)]';
y = [Y(:) Y(:)]';
z = [repmat(i(1),1,length(x)); repmat(i(end),1,length(x))];
col = 'b';
hold on;
plot3(x,y,z,col);
plot3(y,z,x,col);
plot3(z,x,y,col);
Unfortunately, MATLAB does not currently support transparent lines (to my knowledge). If you really need them to be transparent I'd suggest using 'patch'.

I understand this is a late reply but it is still valid in case anyone else is looking at doing the same thing.
Assuming you are plotting cubes (/their edges), an alternative to the answers already provided is to use the 'plotcube' code from Oliver:
plotcube
The advantage of this solution is that you can:
Change the transparency of the faces (FaceAlpha), and/or,
Change the transparency of the edges (EdgeAlpha), and/or,
Change the colour of the lines (EdgeColor).
All of these can be constants, or variables.
(e.g. fixed edge colour, or a colour that changes with Z-value etc.)
To add in functionality of 2. and 3. (above) change the 'cellfun(#patch...' section in Olivers code, adding in the four extra lines of code as follows: (replace the whole cellfun section with this; including the new 'EdgeAlpha' and 'EdgeColor' lines):
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1),...
repmat({'EdgeAlpha'},6,1),...
repmat({0.2},6,1),... % Set this value to whatever you want; even a variable / matrix
repmat({'EdgeColor'},6,1),...
repmat({'black'},6,1)...
);
For more info on 'patch' please see patch documentation.
An important note:
- for large models (many cubes) this is very slow to run.
e.g. running this 'plotcube' function in a 'for' loop in MATLAB over thousands of blocks. I believe this is from calling the 'patch' function multiple times.
A better solution would be to vectorise; to put all your points (vertices/faces/whatever) together in a single matrix first and then call the #patch function only once (no 'for' loop). This would require changing the code somehow to update all the XYZ data.
I hope that helps someone.
Here is the 'plotcube' code in case the link to the original code by Oliver breaks someday:
function plotcube(varargin)
% PLOTCUBE - Display a 3D-cube in the current axes
%
% PLOTCUBE(EDGES,ORIGIN,ALPHA,COLOR) displays a 3D-cube in the current axes
% with the following properties:
% * EDGES : 3-elements vector that defines the length of cube edges
% * ORIGIN: 3-elements vector that defines the start point of the cube
% * ALPHA : scalar that defines the transparency of the cube faces (from 0
% to 1)
% * COLOR : 3-elements vector that defines the faces color of the cube
%
% Example:
% >> plotcube([5 5 5],[ 2 2 2],.8,[1 0 0]);
% >> plotcube([5 5 5],[10 10 10],.8,[0 1 0]);
% >> plotcube([5 5 5],[20 20 20],.8,[0 0 1]);
% Default input arguments
inArgs = { ...
[10 56 100] , ... % Default edge sizes (x,y and z)
[10 10 10] , ... % Default coordinates of the origin point of the cube
.7 , ... % Default alpha value for the cube's faces
[1 0 0] ... % Default Color for the cube
};
% Replace default input arguments by input values
inArgs(1:nargin) = varargin;
% Create all variables
[edges,origin,alpha,clr] = deal(inArgs{:});
XYZ = { ...
[0 0 0 0] [0 0 1 1] [0 1 1 0] ; ...
[1 1 1 1] [0 0 1 1] [0 1 1 0] ; ...
[0 1 1 0] [0 0 0 0] [0 0 1 1] ; ...
[0 1 1 0] [1 1 1 1] [0 0 1 1] ; ...
[0 1 1 0] [0 0 1 1] [0 0 0 0] ; ...
[0 1 1 0] [0 0 1 1] [1 1 1 1] ...
};
XYZ = mat2cell(...
cellfun( #(x,y,z) x*y+z , ...
XYZ , ...
repmat(mat2cell(edges,1,[1 1 1]),6,1) , ...
repmat(mat2cell(origin,1,[1 1 1]),6,1) , ...
'UniformOutput',false), ...
6,[1 1 1]);
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1)...
);
view(3);

you can make the inside line kind of transparent by setting color = [0.65, 0.65, 0.65]. And you can use dash line style for interior lines and solid lines for boundary to make it more like a 3-D object.
In my software package, I code a mesh3 function to plot the 3-D tensor product meshes.

clear all
close all
clc
Nx=11;
Ny=11;
Nz=11;
clf
hold on
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+Nz;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+Ny;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+Nx;
surf(i,j,k)
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+1;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+1;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+1;
surf(i,j,k)
view(30,30)

Related

Order area plots by their visible area, to maximize displayed information

I'm trying to plot a series of area plots in front of each others (not stacked). The problem is they sometimes hide each other. Take a look at this example:
clc; close all; clear variables;
%% generate some data
p = {[0 1 0 1.1];
[0 1 0 1];
[0 1 0 0.2];
[0.1 0.9 0 1.1]};
t = linspace(0, 2*pi);
y = cell2mat(cellfun(#(p) abs(p(1) + p(2)*sin(p(3)+p(4)*t)), p, 'UniformOutput', 0));
%% area plots without any order
n = size(p, 1);
C = lines(n);
h(1) = figure; hold on
for i=1:n
area(t, y(i, :), 'facecolor', C(i, :))
end
I tried to sort surfaces by their area to get a better result:
%% order surfaces by their area
integral = sum(y, 2);
[~, order] = sort(integral, 'descend');
h(2) = figure; hold on
for i=1:n
area(t, y(order(i), :), 'facecolor', C(order(i), :))
end
But the result is not satisfactory yet. I think the objective here is to maximize the area of least visible surface.
%% order surfaces by VISIBLE area
betterOrderIMO = [3 1 4 2 ];
h(3) = figure; hold on
for i=1:n
area(t, y(betterOrderIMO(i), :), 'facecolor', C(betterOrderIMO(i), :))
end
%% test visible area
N = zeros(3, n);
C = floor(C*256);
for i=1:3
f = getframe(h(i));
I = (f.cdata);
for j=1:n
N(i, j) = sum(sum(I(:, :, 1)==C(j, 1)& I(:, :, 2)==C(j, 2)&I(:, :, 3)==C(j, 3)));
end
end
min(N, [], 2)
ans = -> No. of pixels of the least visible surface
2363 -> not ordered
3034 -> ordered by area
4146 -> ordered manually
I can run an optimization (e.g. ga), but that seems overkill.
So are there any other options to get the bast order of a series of area plots, that maximizes the area of least visible plot?
It appears that your problem is to display a lot of signals/functions at the same time, based on your comments. How about you use a 3-dimensional perspective?
%% generate some data
p = {[0 1 0 1.1];
[0 1 0 1];
[0 1 0 0.2];
[0.1 0.9 0 1.1]};
t = linspace(0, 2*pi);
y = cell2mat(cellfun(#(p) abs(p(1) + p(2)*sin(p(3)+p(4)*t)), p, 'UniformOutput', 0));
%% area plots without any order
n = size(p, 1);
C = lines(n);
h(1) = figure; hold on
for i=1:n
patch( i*ones([1 numel(t)+2]), [t(1) t t(end)], [0 y(i,:) 0], C(i,:) );
end
view(3);
grid on;
You may want to replace the tick labels along the x axis with something more meaningful.
Another option would be this:
%% generate some data
p = {[0 1 0 1.1];
[0 1 0 1];
[0 1 0 0.2];
[0.1 0.9 0 1.1]};
t = linspace(0, 2*pi);
y = cell2mat(cellfun(#(p) abs(p(1) + p(2)*sin(p(3)+p(4)*t)), p, 'UniformOutput', 0));
%% area plots without any order
n = size(p, 1);
C = lines(n);
h(1) = figure;
h_patch=waterfall( [t(1) t t(end)], 1:n, [zeros([n 1]) y zeros([n 1])], (1:n).'.*ones([n numel(t)+2]) );
colormap(C);
set(h_patch,'FaceColor','none');
set(h_patch,'LineWidth',2);
view(-15,75);

How do I resolve this issue with 3D image visualization?

I have this 3D image data that I need to visualize. I have been able to visualize it with 2D slices using imshow3D, but I would like to see the image data in 3D space.
The code I used is as follows (courtesy: How do i create a rectangular mask at known angles?), but I can't tell why it isn't displaying:
% create input image
imageSizeX = 120;
imageSizeY = 200;
imageSizeZ = 50
% generate 3D grid
[columnsInImage, rowsInImage, pagesInImage] = meshgrid(1:imageSizeX, 1:imageSizeY, 1:imageSizeZ);
% create the sphere in the image.
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
diameter = 56;
radius = diameter/2;
sphereVoxels = (rowsInImage - centerY).^2 ...
+ (columnsInImage - centerX).^2 + (pagesInImage - centerZ).^2 <= radius.^2;
% change image from logical to numeric labels.
Img = double(sphereVoxels);
for ii = 1:numel(Img)
if Img(ii) == 0
Img(ii) = 2; % intermediate phase voxels
end
end
% specify the desired angle
angle = 60;
% specify desired pixel height and width of solid
width = imageSizeX;
height = imageSizeY;
page = imageSizeZ;
% Find the row point at which theta will be created
y = centerY - ( radius*cos(angle * pi/180) )
% determine top of the solid bar
y0 = max(1, y-height);
% label everything from y0 to y to be = 3 (solid)
Img(y0:y, 1:width, 1:page)=3;
% figure, imshow3D(Img);
% axis on;
% grid on;
% display it using an isosurface
fv = isosurface(Img, 0);
patch(fv,'FaceColor',[0 0 .7],'EdgeColor',[0 0 1]); title('Binary volume of a sphere');
view(45,45);
axis tight;
grid on;
xlabel('x-axis [pixels]'); ylabel('y-axis [pixels]'); zlabel('z-axis [pixels]')
Although, the solid bar is not diagonal as the figure attached below, I would expect the image to be something similar to this:
I do not know exactly what I am doing wrong here.
With regard to the problem in your code, it appears that you set points inside the sphere to 1, then set all the remaining points outside the sphere to 2, then a section through the y plane to 3. There is no value of 0 in the volume in this case, so trying to get an isosurface at the value of 0 isn't going to find anything.
However, if you'd rather create a "voxelated" Minecraft-like surface, like in your sample image showing the facets of your voxels, then I have another option for you...
First, I created a set of volume data as you did in your example, with the exception that I omitted the for loop that sets values to 2, and instead set the values of the solid bar to 2.
Next, I made use of a function build_voxels that I've used in a few 3D projects of mine:
function [X, Y, Z, C] = build_voxels(roiMask)
maskSize = size(roiMask);
% Create the ROI surface patches pointing toward -x:
index = find(diff(padarray(roiMask, [1 0 0], 'pre'), 1, 1) > 0);
[X1, Y1, Z1, C1] = make_patches([-1 -1 -1 -1], [1 1 -1 -1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward +x:
index = find(diff(padarray(roiMask, [1 0 0], 'post'), 1, 1) < 0);
[X2, Y2, Z2, C2] = make_patches([1 1 1 1], [-1 -1 1 1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward -y:
index = find(diff(padarray(roiMask, [0 1 0], 'pre'), 1, 2) > 0);
[X3, Y3, Z3, C3] = make_patches([-1 -1 1 1], [-1 -1 -1 -1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward +y:
index = find(diff(padarray(roiMask, [0 1 0], 'post'), 1, 2) < 0);
[X4, Y4, Z4, C4] = make_patches([1 1 -1 -1], [1 1 1 1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward -z:
index = find(diff(padarray(roiMask, [0 0 1], 'pre'), 1, 3) > 0);
[X5, Y5, Z5, C5] = make_patches([1 1 -1 -1], [-1 1 1 -1], [-1 -1 -1 -1]);
% Create the ROI surface patches pointing toward +z:
index = find(diff(padarray(roiMask, [0 0 1], 'post'), 1, 3) < 0);
[X6, Y6, Z6, C6] = make_patches([-1 -1 1 1], [-1 1 1 -1], [1 1 1 1]);
% Collect patch data:
X = [X1 X2 X3 X4 X5 X6];
Y = [Y1 Y2 Y3 Y4 Y5 Y6];
Z = [Z1 Z2 Z3 Z4 Z5 Z6];
C = [C1 C2 C3 C4 C5 C6];
function [Xp, Yp, Zp, Cp] = make_patches(Xo, Yo, Zo)
[Xp, Yp, Zp] = ind2sub(maskSize, index);
Xp = bsxfun(#plus, Xp, Xo./2).';
Yp = bsxfun(#plus, Yp, Yo./2).';
Zp = bsxfun(#plus, Zp, Zo./2).';
Cp = index(:).';
end
end
This function accepts a 3D matrix, ideally a logical mask of the volume region(s) to create a surface for, and returns 4 4-by-N matrices: X/Y/Z matrices for the voxel face patches and an index matrix C that can be used to get values from the volume data matrix for use in coloring each surface.
Here's the code to render the surfaces:
[X, Y, Z, C] = build_voxels(Img > 0);
rgbData = reshape([1 0 0; 1 1 0], [2 1 3]);
hSurface = patch(X, Y, Z, rgbData(Img(C), :, :), ...
'AmbientStrength', 0.5, ...
'BackFaceLighting', 'unlit', ...
'EdgeColor', 'none', ...
'FaceLighting', 'flat');
axis equal;
axis tight;
view(45, 45);
grid on;
xlabel('x-axis (voxels)');
ylabel('y-axis (voxels)');
zlabel('z-axis (voxels)');
light('Position', get(gca, 'CameraPosition'), 'Style', 'local');
And here's the plot:
Note that the sphere and bar surfaces are colored differently since they are labeled with values 1 and 2, respectively, in the volume data Img. These values are extracted from Img using C and then used as an index into rgbData, which contains red (first row) and yellow (second row) RGB triplets. This will create an N-by-1-by-3 matrix of polygon face colors.

delete a line in a for loop with MATLAB

i'm struggling with this matter probably
i'm just starting with Matlab.this is my code,i
wanna rotate a two links arm,using rotation matrix:
clear all
close all
clc
myaxes = axes('Xlim',[-1 1 ],'Ylim',[-1 1],'Zlim',[-1 1]);
view(3);
grid on;
axis equal;
hold on
xlabel('X')
ylabel('y')
zlabel('Z')
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 =(0:0.5:15) ;
for i = 1:length(alfa_1)
M3(:,:,i) = [cosd(alfa_1(i)) -sind(alfa_1(i)) 0
sind(alfa_1(i)) cosd(alfa_1(i)) 0
0 0 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5;0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1;0; 0];
figure(1)
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
hold on
M3_1(:,:,i) = [cosd(alfa_2(i)) -sind(alfa_2(i)) 0
sind(alfa_2(i)) cosd(alfa_2(i)) 0
0 0 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)],[P_1(2,i,i) P_2_2(2,i,i)],[P_1(3,i,i) P_2_2(3,i,i)],'color','r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
hold on
end
should i use delete function to obtain an animation without plotting
all the lines but only the current line?!?.
thanks in advance for your help and support.
You can use the drawnow function in MATLAB for this purpose. This function can be used inside a for loop to force a plot to be rendered every iteration, instead of being stored in a buffer until after the loop.
Update figure window and execute pending callbacks
An example: for a simpler code consider a object moves on circle
t = 0:0.05:2*pi;
x = cos(t);
y = sin(t);
for k=1:length(t)
plot(x(k),y(k),'ko')
axis([-1.2 1.2 -1.2 1.2])
axis square
drawnow
end
Please note the axis function in this method. If the axis lines are deleted from the code then, in every iteration, the axis limits will change and the animation is not smooth.
What about your code:
clear all
close all
clc
view(3);
xlabel('X');
ylabel('y');
zlabel('Z');
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 = (0:0.5:15) ;
for i = 1:length(alfa_1)
% Calculate new values for plotting
M3(:,:,i) = [cosd(alfa_1(i)), -sind(alfa_1(i)), 0
sind(alfa_1(i)), cosd(alfa_1(i)), 0
0 , 0 , 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5; 0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1; 0; 0] ;
% Clear figure 1 and hold for all plots
figure(1)
clf
% Hold only needs to be applied around plots on same axes
hold on
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
% Recalculate plotting values
M3_1(:,:,i) = [cosd(alfa_2(i)), -sind(alfa_2(i)), 0
sind(alfa_2(i)), cosd(alfa_2(i)), 0
0 , 0 , 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)], [P_1(2,i,i) P_2_2(2,i,i)], [P_1(3,i,i) P_2_2(3,i,i)], 'color', 'r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
% Set axis limits for consistency in all plots, show grid
axis([-2 2 -2 2])
grid on
% Hold off is good practice to avoid later accidental plotting on same axes
hold off
% Draw from the buffer
drawnow
end
you can save(if you want) this animation with getFrame function and play it with movie function
and another function may helps you is comet.

Matlab colormap symmetric about 1

I have data that is constructed as a ratio, and therefore I'd like to use a red/white/blue colormap where white is assigned to 1 and red and blue surround it. Is there an easy way to do this?
You can easily construct a blue-white-read colormap using interp1. Here's a little anonymous function which takes an integer as input and constructs a colormap.
bwr = #(n)interp1([1 2 3], [0 0 1; 1 1 1; 1 0 0], linspace(1, 3, n), 'linear')
colormap(bwr(64));
To control where the white calls, you'll want to set the CLim of the axes. You will want to center your clims around the value that you want to be white.
set(gca, 'clim', [0 2])
And as a full example:
data = reshape(linspace(0, 100, 16), [4 4]) ./ 50;
figure
imagesc(data);
colormap(bwr(64));
colorbar;
set(gca, 'clim', [0 2])
Keep in mind though that since you have a ratio, all of the values between 0 and 1 will be compressed whereas the values > 1 can theoretically go all the way to infinity.
As an example:
data = reshape(linspace(1, 200, 16), [4 4]) ./ 50;
To correct for this you could log-transform your data prior to plotting and then change the colorbar tick marks to represent your initial ratio values.
LData = log(data);
imagesc(LData)
colormap(bwr(64));
cbar = colorbar();
set(gca, 'clim', [-1 1] * max(abs(LData(:))))
cticks = get(cbar, 'Ticks');
cticklabels = arrayfun(#(x)sprintf('%0.2f', x), exp(cticks), 'uniformoutput', false);
set(cbar, 'TickLabels', cticklabels);

connect four matlab

Ok, right now i'm trying to create a connect four game through Matlab coding; now the game is still infant but my problem is that I either can't get the figure to plot in each grid square or I can't get the 'circle' figure to plot at all. Please help in any way possible. Also if anyone knows about any connect four matlab tutorials, it would be greatly appreciated.
function [] = Kinect4(nrRows, nrCols)
board = zeros(nrRows, nrCols);
nrMoves = 0;
set(gca, 'xlim', [0 nrCols]);
set(gca, 'ylim', [0 nrRows]);
for r = 1 : 1 : nrRows - 1
line([0, nrCols], [r, r], ...
'LineWidth', 4, 'Color', [0 0 1]);
end
for c = 1 : 1 : nrCols - 1
line([c, c], [0, nrRows], ...
'LineWidth', 4, 'Color', [0 0 1]);
end
DrawBoard(nrRows, nrCols)
hold on;
while nrMoves < nrRows * nrCols %Computes ability to move polygon
[x, y] = ginput(1);
r = ceil(y); % convert to row index
c = ceil(x); % convert to column index
angles = 0 : 1 : 360;
x = cx + r .* cosd(angles);
y = cy + r .* sind(angles);
plot(x, y, 'Color', [1 1 1], 'LineWidth', 3);
axis square;
end
end
Here are some fixes to the code.
removed the line DrawBoard(nrRows, nrCols). Not sure if you put it there as a comment as you have already drawn the board or if DrawBoard is a separate function.
Changed the calculation for r and c to give the center of the cell you wan the put the peg in. This is done by subtracting 0.5 from each.
Changed the line x = cx + r .* cosd(angles); to x = c + 0.5*cosd(angles);. In the previous one, variable cx is undefined and instead of r being the radius of the peg, I used 0.5 you can replace it by appropriate variable. But the idea is to draw a circle of radius 0.5 (so that it fits in a cell) with the center offset by c along x-axis. Similar change for y to offset the peg along y-axis.
Changed the color in plot command to [0 0 0], which is black. [1 1 1] is white and is impossible to see on white background :). I would suggest using 'k' for black, 'b' for blue and so on. See matlab documentation for basic color specifications.
I am guessing you are yet to implement gravity so that the peg moves down. Also you need to check is a cell is already filled. All these and other improvements (like removing unnecessary for-loops, better way to draw pegs, etc.) are left once you get to a working code.
Here's a "working" code:
function [] = Kinect4(nrRows, nrCols)
board = zeros(nrRows, nrCols);
nrMoves = 0;
set(gca, 'xlim', [0 nrCols]);
set(gca, 'ylim', [0 nrRows]);
for r = 1 : 1 : nrRows - 1
line([0, nrCols], [r, r], ...
'LineWidth', 4, 'Color', [0 0 1]);
end
for c = 1 : 1 : nrCols - 1
line([c, c], [0, nrRows], ...
'LineWidth', 4, 'Color', [0 0 1]);
end
axis square;
hold on;
while nrMoves < nrRows * nrCols %Computes ability to move polygon
[x, y] = ginput(1);
r = ceil(y) - 0.5;
c = ceil(x) - 0.5;
angles = 0 : 1 : 360;
x = c + 0.5*cosd(angles);
y = r + 0.5*sind(angles);
plot(x, y, 'Color', [0 0 0], 'LineWidth', 3);
end
end