I have two datasets. One detailing a list of angles (which I am plotting onto a rose plot):
angles
-0.8481065519
0.0367932161
2.6273740453
...
n
The other, detailing directional statistics from this group of angles:
angle,error
-0.848106563,0.8452778824
Where angle essentially defines the directional mean, and error the circular variance, essentially an error bar either side of the angle
I have thus far plotted a rose histogram using the set of angles, as such:
h = rose(angles,36)
I would like to create a plot of the directional statistic angle (it does not need a length/magnitude - just to the edge of the circle plot) with the error around it.
As an example:
I added the lines by hand in Matlab. If possible it would be good to perhaps have shading within the arc too. Alternatively, (and possibly preferred) would be to have just a sliver above the rose plot bins (so it doesn't cover the data) with a centre line (showing the angle and shading surrounding for the error.
Thanks in advance.
How about this?
%// Data
angles = 2*pi*.8*randn(1,1e4);
angle = -0.848106563;
error = 0.8452778824;
%// Plot rose
rose(angles, 36);
axis image %// make axis square
hold on
%// Plot mean
a = axis;
a = a(2); %// size of axis
plot([0 cos(angle)*a], [0 sin(angle)*a], 'r')
%// Plot error as many shaded triangles that compose a circular wedge
t = linspace(-error/2+angle,error/2+angle,100); %// increase "100" if needed
for k = 1:numel(t)-1
h = patch([0 cos(t(k))*a cos(t(k+1))*a 0], ...
[0 sin(t(k))*a sin(t(k+1))*a 0], [.5 0 0], 'edgecolor', 'none');
%// change color [.5 0 0] to something else if desired. Note also alpha
set(h,'Facealpha',.3) %// make transparent
end
%// Place rose on top by rearranging order of axis children
ch = get(gca,'children');
set(gca,'children',[ch(2:end); ch(1)]);
For this to work, you need to use a figure renderer capable of transparency. So you may need to adjust the figure's renderer property.
Related
Getting right to the question: How can I make my plot go from looking like this:
to something like this:
where a right-handed Cartesian coordinate system (with axis labels at the end of the arrows, e.g., in this example the x-axis label is = $x_1^G$)
Some elaboration and prefacing: First, I am new to matlab and "matrix math". I tried searching on this site for questions similar to what I have posed above but did not see anything (but I may have missed), so hopefully this is not a duplicate.
Here is the code I have used to develop my rotated ellipsoid (since I'm new to matlab I would appreciate any comments on my code):
%Insert the components of the 3x3 matrix (i.e. the scalar values of the 2nd-rank symmetric tensor)
Pmatrix = [115.9547 12.03765 4.68235; 12.03765 116.3702 -2.47985; 4.68235 -2.47985 134.5488];
[R,D]=eig(Pmatrix); %find the eigenvectors (R) and eigenvalues (D) of the 2nd-rank tensor
[x, y, z] =sphere; %generate coordinates of a sphere, using the sphere command
%Stretch the coordinates of the sphere to form the tensor's representation ellipsoid, do this by multiplying the x, y, z coordinates by the square-roots of the eigenvalues
x1 = x*sqrt(D(1,1));
y1 = y*sqrt(D(2,2));
z1 = z*sqrt(D(3,3));
figure;
hmesh = mesh(x1,y1,z1);
set(hmesh,'FaceColor',[0.5,0.5,0.5],'FaceAlpha',0.5) %set color to gray, make mostly transparent
axis equal; %Make tick mark increments on all axes equal
xlabel('x');
ylabel('y');
zlabel('z');
theta1 = -asind(R(3,1)); %rotation around y-axis in degrees
psi1 = atan2d(R(3,2)/cos(theta1),R(3,3)/cos(theta1)); %rotation around x-axis in degrees
phi1 = atan2d(R(2,1)/cos(theta1),R(1,1)/cos(theta1)); %rotation around z-axis in degress
direction = [1 0 0]; %rotate the surface plot psi1 degrees around its x-axis
rotate(hmesh,direction,psi1)
direction = [0 1 0]; %rotate the surface plot theta1 degrees around its y-axis
rotate(hmesh,direction,theta1)
direction = [0 0 1]; %rotate the surface plot phi1 degrees around its z-axis
rotate(hmesh,direction,phi1)
view([-36 18]); %Change the camera viewpoint
To add to my question, I would like to add other (similar) items to my plot, so that the final product would look like this:
In the development of the image above, a set of axes collinear with the ellipsoid's eigenvectors are added (the red, green, blue arrows):
Then these axes are extended in the opposite direction, through the origin, where these portions of the axes are shown as a dashed lines:
Then, the angles between the global coordinate axes (black arrows) and the ellipsoid's axes (colored arrows) are notated as shown here:
To comment on this last addition, someone has built some matlab code with these features (see youtube video here). In the video's description it says the matlab code can be found here. Being new to matlab, I don't see where the code is, e.g., I don't see where on this page (screenshot below) the code is to build that matlab plot seen in the youtube video. If you can guide me on how to navigate that mathworks-fileexchage page that would be appreciated.
I am working on creating 3D images from 3 individual binary images, that were taken with 3 cameras. I have a corresponding calibration and know the setup (see below). Since the image preprocessing is mostly done in MATLAB I would like to implement everything there.
The current idea of my code is to extrude the 2D binary image according to the camera calibration. Here's what a typical binary image looks like:
And an extruded image looks like this in MATLAB:
With all 3 cameras extruded and a binning algorithm, I can create my final 3D-shape. This works fine so far, but takes a long time to compute, since I need to create a lot of extrusion steps to get a good surface.
I was thinking now to speed this up by recreating the process I would do in a 3D-modeling software like Blender. There I also extrude the outline of the binary image and create an intersection easily by just creating a spline for the outline, extrude them and use a boolean operator. Here's a Blender example with 2 extruded images:
I have no idea how to implement something like this in MATLAB. I wanted to create two instances of my binary contour at the top and bottom end of the extrusion "tube" and then define faces between the individual points and create an intersection afterwards. The point creation is no problem but the face definition and the intersection (boolean operator) are. Does anyone have an idea how this could be implemented?
This might not be an easy thing to do in MATLAB, but it's possible. I'll outline one set of steps here, using two intersecting cylinders as an example...
Creating a tetrahedral mesh:
The first step is to create a tetrahedral mesh for your extrusion. If your 2D binary image that you're extruding is convex and has no holes, you could do this using the delaunayTriangulation function:
DT = delaunayTriangulation(P);
Here, P contains the coordinate points of the "end caps" of your extrusion (i.e. the faces on each end of your tube). However, when generating tetrahedral meshes, delaunayTriangulation doesn't allow you to specify constrained edges, and as such it can end up filling in holes or concavities in your extrusion. There may be some better mesh-generation alternatives in other toolboxes, such as the Partial Differential Equations Toolbox, but I don't have access to them and can't speak to their applicability.
If automated mesh-generation options don't work, you'll have to build your tetrahedral mesh yourself and pass that data to triangulation. This could be tricky, but I'll show you some steps for how you can do this for a cylinder, which may help you figure it out for more involved shapes. Below, we build a set of coordinate points P1 and an M-by-4 matrix T1 where each row contains indices into the rows of P1 which define one tetrahedron:
% Create circle coordinates for the end caps:
N = 21;
theta = linspace(0, 2*pi, N).';
x = sin(theta(1:(end-1)));
y = cos(theta(1:(end-1)))+0.5;
z = ones(N-1, 1);
% Build tetrahedrons for first cylinder, aligned along the z axis:
P1 = [0 0.5 -1; ... % Center point of bottom face
x y -z; ... % Edge coordinates of bottom face
0 0.5 1; ... % Center point of top face
x y z]; % Edge coordinates of top face
cBottom = ones(N-1, 1); % Row indices for bottom center coordinate
cEdgeBottom1 = (2:N).'; % Row indices for bottom edge coordinates
cEdgeBottom2 = [3:N 2].'; % Shifted row indices for bottom edge coordinates
cTop = cBottom+N; % Row indices for top center coordinate
cEdgeTop1 = cEdgeBottom1+N; % Row indices for top edge coordinates
cEdgeTop2 = cEdgeBottom2+N; % Shifted row indices for top edge coordinates
% There are 3 tetrahedrons per radial slice of the cylinder: one that includes the
% bottom face and half of the side face (all generated simultaneously by the first row
% below), one that includes the other half of the side face (second row below), and one
% that includes the top face (third row below):
T1 = [cEdgeBottom1 cEdgeBottom2 cEdgeTop1 cBottom; ...
cEdgeBottom2 cEdgeTop1 cEdgeTop2 cBottom; ...
cEdgeTop1 cEdgeTop2 cTop cBottom];
TR1 = triangulation(T1, P1);
To better visualize how the cylinder is being divided into tetrahedrons, here's an animation of an exploded view:
Now we can create a second cylinder, offset and rotated so it aligns with the x axis and intersecting the first:
% Build tetrahedrons for second cylinder:
P2 = [P1(:, 3) -P1(:, 2) P1(:, 1)];
T2 = T1;
TR2 = triangulation(T2, P2);
% Plot cylinders:
tetramesh(TR1, 'FaceColor', 'r', 'FaceAlpha', 0.6);
hold on;
tetramesh(TR2, 'FaceColor', 'g', 'FaceAlpha', 0.6);
axis equal;
xlabel('x');
ylabel('y');
zlabel('z');
And here's the plot to visualize them:
Finding the region of intersection:
Once we have tetrahedral representations of the volumes, we can generate a grid of points covering the region of intersection and use the pointLocation function to determine which points are within both cylinders:
nGrid = 101;
[X, Y, Z] = meshgrid(linspace(-1, 1, nGrid));
QP = [X(:) Y(:) Z(:)];
indexIntersect = (~isnan(pointLocation(TR1, QP))) & ...
(~isnan(pointLocation(TR2, QP)));
mask = double(reshape(indexIntersect, [nGrid nGrid nGrid]));
We now have volume data mask that contains zeroes and ones, with the ones defining the region of intersection. The finer you make your grid (by adjusting nGrid), the more accurately this will represent the true region of intersection between the cylinders.
Generating a 3D surface:
You may want to create a surface from this data, defining the boundary of the intersection region. There are a couple ways to do this. One is to generate the surface with isosurface, which you could then visualize using featureEdges. For example:
[F, V] = isosurface(mask, 0.5);
TR = triangulation(F, V);
FE = featureEdges(TR, pi/6).';
xV = V(:, 1);
yV = V(:, 2);
zV = V(:, 3);
trisurf(TR, 'FaceColor', 'c', 'FaceAlpha', 0.8, 'EdgeColor', 'none');
axis equal;
xlabel('x');
ylabel('y');
zlabel('z');
hold on;
plot3(xV(FE), yV(FE), zV(FE), 'k');
And the resulting plot:
Another option is to create a "voxelated" Minecraft-like surface, as I illustrate here:
[X, Y, Z, C] = build_voxels(permute(mask, [2 1 3]));
hSurface = patch(X, Y, Z, 'c', ...
'AmbientStrength', 0.5, ...
'BackFaceLighting', 'unlit', ...
'EdgeColor', 'none', ...
'FaceLighting', 'flat');
axis equal;
view(-37.5, 30);
set(gca, 'XLim', [0 101], 'YLim', [25 75], 'ZLim', [0 102]);
xlabel('x');
ylabel('y');
zlabel('z');
grid on;
light('Position', get(gca, 'CameraPosition'), 'Style', 'local');
And the resulting plot:
I have a vector of values that I want to plot as brightness on a circle through the radius of it (I.e. If it was 0 3 1 5 I'd want a circle that was dark at the centre, then a bright ring around it, then a slightly darker ring, then a brighter ring).
To do this I've attempted to rotate my radial vector (E) around the y axis, as such
[X,Y,Z] = cylinder(E);
h = surf(X,Y,Z),
However I'm clearly not doing it right, as this appears to be rotating my curve around the x axis. I've tried just swapping X and Y, but it still rotates it around the x axis. Any help would be greatly appreciated.
One way would be to rotate your vector and create a surface. The Z data of the surface (your rotated vector) will be color coded according to the colormap you choose, if you display the surface from the top you get your circles at the different brightness.
If you are really only interested from the "top view" of this surface, then no need to create a full surface, a simple pcolor will do the job.
example:
%% // input data (and assumptions)
E=[0 3 1 5 2 7];
nBrightness = 10 ; %// number of brightness levels
r = (0:numel(E)) ; %// radius step=1 by default for consecutive circles
%// otherwise define different thickness for each circle
So if I use stairs([E 0]) you get your different brightness levels:
I had to add a last 0 to the vector to "close" the last level, we'll have to do that again in the solution below.
Now to rotate/replicate that around Y, color code the height, and look at it from the top:
%% // replicate profile around axis
ntt = 50 ; %// define how many angular division for the plot
theta = linspace(0,2*pi,ntt) ; %// create all the angular divisions
[rr,tt]=meshgrid(r,theta) ; %// generate a grid
z = repmat( [E 0] , ntt , 1 ) ; %// replicate our "E" vector to match the grid
[xx,yy,zz] = pol2cart(tt,rr,z) ; %// convert everything to cartesian coordinates
pcolor(xx,yy,zz) %// plot everything
colormap(gray(nBrightness)) %// make sure we use only "nBrightness" colors (Shades of gray)
caxis([0 nBrightness])
shading flat ; axis equal %// refine the view (axis ratio and "spokes" not visible) etc...
colorbar
axis off
will yield the following :
Note that your problem was not fully defined, I had to take assumptions on:
What radius each brightness circle should have ? (I made them all the same but you can modify that)
How many brightness levels you want ? (You can also modify that easily though).
Have you tried the rotate function?
direction = [0 1 0];
rotate(h,direction,90);
In this example a 90 degree rotation is performed around the y axis.
Using this library http://www.mathworks.com/matlabcentral/fileexchange/45952-circle-plotter
%http://www.mathworks.com/matlabcentral/fileexchange/45952-circle-plotter
x0 = 0;
y0 = 0;
colors = [0 3 1 5];
maxC = max(colors);
sz = numel(colors);
for i=fliplr(1:sz)
c = colors(i);
circles(x0,y0,i,'facecolor',[c/maxC c/maxC 0]) % http://au.mathworks.com/help/matlab/ref/colorspec.html
end
I have trajectory information in 3 dimensions in matlab. These are of a gesture someone is making. When I connect the points in matlab by using plot3, I can see the trajectory nicely.
However, the trajectory is a line in the plot, but I don't know in which direction the gesture has been made as the time is not visualized. Is it possible to visualize this in a 3d plot (where the dimensions are x, y and z)? For example, the colour at the start is bright red and the colour at the end is black.
Thanks for your help,
Héctor
You need the comet3 plot (if you don't mind animations).
If you do mind animations, and you're looking for a static figure, I'd use a quiver.
Example:
% value of the parameter in the parametric equation
t = 0:0.5:2*pi;
% modified coordinate axes
u = [1 0 0].';
v = [0 2 0].';
% coordinates of the ellipse
Ell = bsxfun(#plus, bsxfun(#times, u, cos(t)), bsxfun(#times, v, sin(t)));
% difference vectors between all data points will be used as "velocities"
dEll = diff(Ell, 1,2);
% Quiver the ellipse
quiver3(...
Ell(1,1:end-1), Ell(2,1:end-1), Ell(3,1:end-1), ...
dEll(1,:), dEll(2,:), dEll(3,:), ...
2, 'r') % = scale, LineSpec
axis tight equal
Result:
I was trying use the code shown below to plot in such a way that each iso-surface will be different in color and there will be a color bar at the right. I made a ss(k) color matrix for different colors. Number of iso-surfaces is 10 but I have only 8 colors. That's why I wrote ss(9)='r' and ss(10)='r'.
I need a solution to plot the iso-surface with different color and bar at the right side.
ss=['y','m','c','r','g','b','w','k','r','r']
k=1;
for i=.1:.1:1
p=patch(isosurface(x,y,z,v,i));
isonormals(x,y,z,v,p)
hold on;
set(p,'FaceColor',ss(k),'EdgeColor','none');
daspect([1,1,1])
view(3); axis tight
camlight
lighting gouraud
k=k+1;
end
Another possibility is to draw the patches with direct color-mapping (by setting the property 'CDataMapping'='direct'), while assigning the 'CData' of each patch to an index in the colormap of your choice. This is in fact recommended for maximum graphics performance.
Consider the following example:
%# volumetric data, and iso-levels we want to visualize
[x,y,z,v] = flow(25);
isovalues = linspace(-2.5,1.5,6);
num = numel(isovalues);
%# plot isosurfaces at each level, using direct color mapping
figure('Renderer','opengl')
p = zeros(num,1);
for i=1:num
p(i) = patch( isosurface(x,y,z,v,isovalues(i)) );
isonormals(x,y,z,v,p(i))
set(p(i), 'CData',i);
end
set(p, 'CDataMapping','direct', 'FaceColor','flat', 'EdgeColor','none')
%# define the colormap
clr = hsv(num);
colormap(clr)
%# legend of the isolevels
%#legend(p, num2str(isovalues(:)), ...
%# 'Location','North', 'Orientation','horizontal')
%# fix the colorbar to show iso-levels and their corresponding color
caxis([0 num])
colorbar('YTick',(1:num)-0.5, 'YTickLabel',num2str(isovalues(:)))
%# tweak the plot and view
box on; grid on; axis tight; daspect([1 1 1])
view(3); camproj perspective
camlight; lighting gouraud; alpha(0.75);
rotate3d on
I also included (commented) code to display the legend, but I found it to be redundant, and a colorbar looks nicer.
Matlab usually plots different iso-surfaces in different colors automatically, so you don't need to care about that. What kind of bar do you need? A colorbar or a legend? Either way, it is just to use the colorbar or legend function..
%Create some nice data
[x y z] = meshgrid(1:5,1:5,1:5);
v = ones(5,5,5);
for i=1:5
v(:,:,i)=i;
end
v(1:5,3:5,2)=1
v(1:5,4:5,3)=2
%Plot data
for i=1:5
isosurface(x,y,z,v,i)
end
%Add legend and/or colorbar
legend('one','Two','Three','Four')
colorbar
Since the color bar encodes value->color, it is impossible to do what you ask for, unless there is no intersection in z-values between all pairs of surfaces. So the solution below assumes this is the case. If this is not the case, you can still achieve it by adding a constant value to each surface, so to separate the surfaces along the z axis, and eliminate any intersection.
The solution is based on constructing a colormap matrix of piecewise constant values, distributed similarly to the z values of your surfaces. So for example, if you have 3 surfaces, the first has z values between 1 and 10, the 2nd between 11 and 30, and the 3rd between 31 and 60, you should do something like this (I plot in 2D for simplicity)
r = [1 0 0];
g = [0 1 0];
b = [0 0 1];
cmap = [r(ones(10,1),:); g(ones(20,1),:); b(ones(30,1),:)];
z1 = 1:10;
z2 = 11:30;
z3 = 31:60;
figure; hold on
plot(z1,'color',r)
plot(z2,'color',g)
plot(z3,'color',b)
colorbar
colormap(cmap)
More complex colormaps (i.e, more colors) can be constructed with different mixtures of red, green, and blue (http://www.mathworks.com/help/techdoc/ref/colorspec.html)