Drawing star-like figure in Matlab - matlab

I had to plot this in matlab :
so I wrote the following code:
x=[0.9 1 0.9 -0.9 0.7 0.7 -0.9 0.9];
y=[-1 0 1 -0.5 -0.8 0.8 -0.4 -1];
plot(x,y);
but this gives me:
Is this method insufficient to draw the first figure....Is there some other short method for this...

You can do better positioning your data points
nPoints = 7;
th = linspace(-2*pi, 2*pi, 2*nPoints+1);%// extra point to close the curve
r = 1;
x = r*cos(th);
y = r*sin(th);
scatter( x, y, 'ro' );
hold on;
plot( x(1:2:end), y(1:2:end), 'b-' );
axis equal;
Resulting with:
BTW, this code works for any odd nPoints - just try ;)

It seems to me that you want to construct a star polygon, which has the property that all points are equidistant to its neighboring points, and all points lie on the same circle.
First, we generate the desired angles a (measured from the x-axis to a line that connects the origin with the desired point, see wikipedia). Based on the polygon, we rearrage the angles in such a way that a desired number of points is skipped (in the code below, this is done by using among others repmat - but many alternatives exist).
To convert the angles to actual points in the plane, we take sine and cosine values, and then we can plot the dots and lines. Putting this together results in the following code, which results in the dersired figure
n = 7;
a = linspace(0,2*pi,n+1);
skip = 1;
b = [repmat(a(1:end-1),1,skip+1) a(end)];
a = b(1:skip+1:end);
figure;
clf;
hold on;
plot(cos(a),sin(a),'b-');
plot(cos(a(1:end-1)),sin(a(1:end-1)),'ro');
axis([-1 1 -1 1])
axis equal
A little less involved would be to compute the vector a like this:
a = mod(linspace(0,(skip+1)*2*pi,n+1),(skip+1)*2*pi);

I tried manually:
x = [-0.4 0.6 1 0.6 -0.4 -0.8 -0.8];
y = [-0.9 -0.7 0 0.7 0.9 0.4 -0.4];
x_ = [x,x];
y_ = [y,y];
figure;
hold on;
for ii=1:numel(x),
scatter(x(ii),y(ii),'ro');
plot([x_(ii),x_(ii+1+1)],[y_(ii),y_(ii+1+1)],'b-');
end
axis([-1 1 -1 1]);
And I get his:

Related

Linewidth of 3D plot in Matlab relative to axis

I have 3D coordinates of two beams. Their coordinates are set in meters.
I also know the diameter of the beams. What I want to do is plot the linewidth of the beam to be with same units as the length.
(In my real problem I have over 40 beams)
Here is my draft.
clear;clc;
coordinates(:,:,1) = [1 0 1 ; 2 0 0]; % meters
coordinates(:,:,2) = [0 1 2 ; 1 0 2]; % meters
width = [0.05 , 0.09] % meters
[q,w,e] = size(coordinates);
for i = 1:e
plot3(coordinates(:,1,i), coordinates(:,2,i), coordinates(:,3,i), 'LineWidth',width(i); % <- Defining different linewidth.
hold on
end
If this isn't possible I would like to be able to set linewidth for each beam from a vector.

Plotting unit circles in matlab and using the hold on to insert individual data points and plotting the intersection with circle

I was trying to produce the following figure:
as similar as possible. I was having difficulties because I wasn't sure how to plot the unit circle. How does one do that? I tried using the polar function but I couldn't then make it also plot the blue crosses and red crosses. Anyone has an idea?
Edited answer
Here is a part of the code:
% --- Plot everything on the same axes
hold on
% --- Plot the unit circle:
theta = linspace(0, 2*pi, 360);
plot(cos(theta), sin(theta), 'k--');
% --- Plot the blue points
x = [0.2 0.4 0.4 0.8];
y = [0.4 0.2 0.8 0.4];
scatter(x, y, 'bs');
% --- Plot the red points:
x = [0.4 0.8];
y = [0.4 0.8];
scatter(x, y, 'ro');
There are still many modifications to do to get the final plots, but at least this is a starting point.
Second edit
To answer your question about the intersection of a line and a circle, you have to start with the maths behind. Line and circle are defined by the following equations:
y = a.x + b % Cartesian definition of a line
(x-x0)² + (y-y0)² = r² % Cartesian definition of a circle
If you combine the two, you realize that finding the intersection is similar to finding the solution of:
(a²+1).x² + 2(a(b-y0)-x0).x + x0²+(b-y0)²-r² = 0
i.e. the roots of a polynom. As this is a trinom, there are 3 possibilities: 0 solution (no intersection), 1 solution (line is tangent to the circle) and 2 solutions (line crossing the circle).
So, in practice you have to:
Get the parameters a, b, x0, y0 and r of your problem
Find the roots of the polynom (for instance, with the function roots)
Decide what to do based on the number of roots.
Hope this helps,
%% Construct polar grid (put inside another function)
range = 0.2:0.2:1;
n = 50;
for i=1:length(range)
ro = ones(1,n);
ro = ro.*range(i);
th = linspace(0,pi*2,n);
[xx,yy] = pol2cart(th,ro);
plot(xx,yy, 'color',[.9 .9 .9]), grid on, hold on
n = round(n * 1.5);
end
%% Plot like normal
x1 = [.2 .4 .4 .8];
y1 = [.4 .2 .8 .4];
x2 = [.4 .8];
y2 = [.4 .8];
plot(x1,y1, 'bx',...
x2,y2, 'ro');
xlim([-.05 1]);
ylim([-.05 1]);

How to plot a intersection operation on two vectors MatLab

I'm trying to represent a the intersection of two fuzzy sets as a 3d mesh in MatLab.
Here are my sets of vectors:
x = [0.3 0.5 0.7]
y = [0.5 0.7 0.1]
Followed by these statements:
[u,v] = meshgrid(x,y)
w = min(u,v)
mesh(u,v,w)
The x and y ticks seem to be all over the place and do not correlate to the actual index number of each vector i.e. 1 to 3, and the graph should represent the shape of a small triangle/T-norm.
At the moment it looks like this:
Here is an example out of my book I'm following:
Ignore what looks like fractions, they are delimiters. Here is the resulting graph:
After looking up fuzzy sets and intersections, here's what I've come up with. First, let's reproduce the textbook example:
% possible values and associated degrees of truth for F
Fv = 1 : 5;
Ft = [0 0.5 1 0.5 0];
% possible values and associated degrees of truth for D
Dv = 2 : 4;
Dt = [0 1 0];
% determine degrees of truth for fuzzy intersection
It = bsxfun(#min, Ft', Dt);
% plot
h = mesh(Dv, Fv, It);
set(h, 'FaceColor', 'none')
set(h, 'EdgeColor', 'k')
xlim([0 4.5])
ylim([0 5])
xlabel D
ylabel F
view(37.5, 30)
The result is:
Not as pretty as in your book, but the same thing.
Applying the same code to your example yields:
Via the arguments u,v you are telling mesh to use the values in them, i.e. the values from x and y, for the positioning of the data points and corresponding ticks. If you just want positions and ticks at 1, 2, 3, leave these arguments out.
mesh(w)

MATLAB contourf plot for an irregular domain

I am stuck with this problem for a long time now. I have a polygonal region (lets say, a hexagon). I can calculate the values of certain function at any point inside the polygon. Now I need to create a filled contour (using contourf in MATLAB) of this data. How do I go about it. I found some discussion on this topic at the link below (page 121)
http://www-personal.umich.edu/~jpboyd/eng403_chap4_contourplts.pdf
This works somewhat ok but it still produces jagged edges which I don't want. Anyone has any suggestion on this problem? Thanks. Here is my code
close all
Node = [ 1.0 0
0.5 0.8660
-0.5 0.8660
-1.0 0
-0.5 -0.8660
0.5 -0.8660];
[x,y] = meshgrid(-1:0.1:1,-1:0.1:1);
N = zeros(size(x));
for i=1:size(x,2)
for j=1:size(y,2)
p = [x(i,j) y(i,j)];
IN = inpolygon(p(1),p(2),Node(:,1),Node(:,2));
if IN
N(i,j)= rand;
else
N(i,j)= NaN;
end
end
end
figure
contourf(x,y,N,'LineStyle','none'), hold on;
xlabel('X'), ylabel('Y'), axis equal; axis off; colorbar;
line([Node(:,1);Node(1,1)],[Node(:,2);Node(1,2)],'Color',[1 1 1],'LineWidth',2.0)
clear IN i j p x y
You're using a square grid to sample a hexagonal area. This will indeed lead to boundary problems.
A better solution (but still not quite optimal) is to use a hexagonal grid:
%# define hexagon
Node = [ 1.0 0
0.5 0.8660
-0.5 0.8660
-1.0 0
-0.5 -0.8660
0.5 -0.8660];
%# Generate hexagonal grid
Rad3Over2 = sqrt(3) / 2;
[x, y] = meshgrid(0:51);
n = size(y,1);
x = Rad3Over2 * x;
y = y + repmat([0 0.5],[n,n/2]);
%# re-scale to -1..1
x = 2*x/max(x(:))-1;
y = 2*y/max(y(:))-1;
%# insode-polygon check
N = zeros(size(x));
for i=1:size(x,2)
for j=1:size(y,2)
p = [x(i,j) y(i,j)];
IN = inpolygon(p(1),p(2),Node(:,1),Node(:,2));
if IN
N(i,j)= rand;
else
N(i,j)= NaN;
end
end
end
%# make contour plot
figure(1)
contourf(x,y,N,'LineStyle','none'), hold on;
xlabel('X'), ylabel('Y'), axis equal; axis off; colorbar;
line([Node(:,1);Node(1,1)],[Node(:,2);Node(1,2)],'Color',[1 1 1],'LineWidth',2.0)
If you want even better coverage, you'll have to devise a grid that better covers your area and/or up the number of sample points.
For arbitrary irregular areas, you might want to experiment with irregular/random grids, distributed such that there are more points close to the boundaries, than there are in the middle of the area.
Suppose you have a function defined on a hexagon. Then take some square that contains the hexagon.
A simple first test could be to extend your function on the square to take the value = 0 for points outside of the hexagon.
Depending on the range of your function this may, or may not, give you a good answer.
If this doesn't work, then find the min of the function on the hexagon using min(min(A))) for an nxn matrix A. Then define the function to be min(min(A)) - 1.0 outside of the hexagon but in the square.
Then use contourf(x, y, z, v) where v is a vector of values for the output, so take v(1) = min(min(A)) - 1.0, and v(2:n) = linspace(min(min(A)), max(max(A)), n) for some integer n. You can probably specify the color of the level set min(min(A)) - 1.0 to be white, but I've never done this. I've had to do something like this before, and setting the function = 0 outside of he hexagon was enough.
If your function can only be evaluated inside the polygonal region, then my hexagonal grid answer still stands. However, if your function can be (or modified to be) evaluated outside the polygon, you might want to use a cheat:
figure(1), clf, hold on
%# External contour, square.
x1 = [-3 -3 +3 +3 -3]/2;
y1 = [-3 +3 +3 -3 -3]/2;
%# internal contour, some polygon
x2 = [1.0 0.5 -0.5 -1.0 -0.5 0.5];
y2 = [0 0.8660 0.8660 0 -0.8660 -0.8660];
%# convert to patches
[f, v] = poly2fv({x1, x2}, {y1, y2});
patch(...
'Faces' , f,...
'Vertices' , v,...
'FaceColor', get(0, 'defaultuicontrolbackgroundcolor'), ...
'EdgeColor', 'none'...
);
%# Generate function for contourplot
[x, y] = meshgrid(-2.8/2:0.1:2.8/2);
N = rand(size(x));
%# make contour plot
contourf(x,y,N,'LineStyle','none'), hold on;
xlabel('X'), ylabel('Y'), axis equal;
axis off; colorbar;
It basically creates your contour plot on a square region, and overlays a mask with a hexagonal hole in it, so it looks like it's only a contour of the hexagonal. I suspect it is a lot easier to tweak your function to allow function evaluations outside the region, then it is to (re-)invent some sort of grid that contains the boundaries.

3d grayscale volume projection onto 2D plane

I have a 3-D grayscale volume corresponding to ultrasound data. In Matlab this 3-D volume is simply a 3-D matrix of MxNxP. The structure I'm interested in is not oriented along the z axis, but along a local coordinate system already known (x'y'z'). What I have up to this point is something like the figure shown below, depicting the original (xyz) and the local coordinate systems (x'y'z'):
I want to obtain the 2-D projection of this volume (i.e. an image) through a specific plane on the local coordinate system, say at z' = z0. How can I do this?
If the volume was oriented along the z axis this projection could be readily achieved. i.e. if the volume, in Matlab, is V, then:
projection = sum(V,3);
thus, the projection can be computed just as the sum along the 3rd dimension of the array. However with a change of orientation the problem becomes more complicated.
I've been looking at radon transform (2D, that applies only to 2-D images and not volumes) and also been considering ortographic projections, but at this point I'm clueless as to what to do!
Thanks for any advice!
New attempt at solution:
Following the tutorial http://blogs.mathworks.com/steve/2006/08/17/spatial-transformations-three-dimensional-rotation/ and making some small changes, I might have something which could help you. Bear in mind, I have little or no experience with volumetric data in MATLAB, so the implementation is quite hacky.
In the below code I use tformarray() to rotate the structure in space. First, the data is centered, then rotated using rotationmat3D to produce the spacial transformation, before the data is moved back to its original position.
As I have never used tformarray before, I handeled datapoints falling outside the defined region after rotation by simply padding the data matrix (NxMxP) with zeros all around. If anyone know a better way, please let us know :)
The code:
%Synthetic dataset, 25x50x25
blob = flow();
%Pad to allow for rotations in space. Bad solution,
%something better might be possible to better understanding
%of tformarray()
blob = padarray(blob,size(blob));
f1 = figure(1);clf;
s1=subplot(1,2,1);
p = patch(isosurface(blob,1));
set(p, 'FaceColor', 'red', 'EdgeColor', 'none');
daspect([1 1 1]);
view([1 1 1])
camlight
lighting gouraud
%Calculate center
blob_center = (size(blob) + 1) / 2;
%Translate to origin transformation
T1 = [1 0 0 0
0 1 0 0
0 0 1 0
-blob_center 1];
%Rotation around [0 0 1]
rot = -pi/3;
Rot = rotationmat3D(rot,[0 1 1]);
T2 = [ 1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1];
T2(1:3,1:3) = Rot;
%Translation back
T3 = [1 0 0 0
0 1 0 0
0 0 1 0
blob_center 1];
%Total transform
T = T1 * T2 * T3;
%See http://blogs.mathworks.com/steve/2006/08/17/spatial-transformations-three-dimensional-rotation/
tform = maketform('affine', T);
R = makeresampler('linear', 'fill');
TDIMS_A = [1 2 3];
TDIMS_B = [1 2 3];
TSIZE_B = size(blob);
TMAP_B = [];
F = 0;
blob2 = ...
tformarray(blob, tform, R, TDIMS_A, TDIMS_B, TSIZE_B, TMAP_B, F);
s2=subplot(1,2,2);
p2 = patch(isosurface(blob2,1));
set(p2, 'FaceColor', 'red', 'EdgeColor', 'none');
daspect([1 1 1]);
view([1 1 1])
camlight
lighting gouraud
The arbitrary visualization below is just to confirm that the data is rotated as expected, plotting a closed surface when the data passed the value '1'. With blob2, you should know be able to project by using simple sums.
figure(2)
subplot(1,2,1);imagesc(sum(blob,3));
subplot(1,2,2);imagesc(sum(blob2,3));
Assuming you have access to the coordinate basis R=[x' y' z'], and that those vectors are orthonormal, you can simply extract the representation in this basis by multiplying your data with the the 3x3 matrix R, where x',y',z' are column vectors.
With the data stored in D (Nx3), you can get the representation with R, by multiplying by it:
Dmarked = D*R;
and now D = Dmarked*inv(R), so going back and forth is stragihtforward.
The following code might provide help to see the transformation. Here I create a synthetic dataset, rotate it, and then rotate it back. Doing sum(DR(:,3)) would then be your sum along z'
%#Create synthetic dataset
N1 = 250;
r1 = 1;
dr1 = 0.1;
dz1 = 0;
mu1 = [0;0];
Sigma1 = eye(2);
theta1 = 0 + (2*pi).*rand(N1,1);
rRand1 = normrnd(r1,dr1,1,N1);
rZ1 = rand(N1,1)*dz1+1;
D = [([rZ1*0 rZ1*0] + repmat(rRand1',1,2)).*[sin(theta1) cos(theta1)] rZ1];
%Create roation matrix
rot = pi/8;
R = rotationmat3D(rot,[0 1 0]);
% R = 0.9239 0 0.3827
% 0 1.0000 0
% -0.3827 0 0.9239
Rinv = inv(R);
%Rotate data
DR = D*R;
%#Visaulize data
f1 = figure(1);clf
subplot(1,3,1);
plot3(DR(:,1),DR(:,2),DR(:,3),'.');title('Your data')
subplot(1,3,2);
plot3(DR*Rinv(:,1),DR*Rinv(:,2),DR*Rinv(:,3),'.r');
view([0.5 0.5 0.2]);title('Representation using your [xmarked ymarked zmarked]');
subplot(1,3,3);
plot3(D(:,1),D(:,2),D(:,3),'.');
view([0.5 0.5 0.2]);title('Original data before rotation');
If you have two normalized 3x1 vectors x2 and y2 corresponding to your local coordinate system (x' and y').
Then, for a position P, its local coordinate will be xP=P'x2 and yP=P'*y2.
So you can try to project your volume using accumarray:
[x y z]=ndgrid(1:M,1:N,1:P);
posP=[x(:) y(:) z(:)];
xP=round(posP*x2);
yP=round(posP*y2);
xP=xP+min(xP(:))+1;
yP=yP+min(yP(:))+1;
V2=accumarray([xP(:),yP(:)],V(:));
If you provide your data, I will test it.