Widen a fibonacci flower using a for cycle - arrays

I was wondering in this example that I've used to practice for loops, I needed to change this code in order to change the image that looks like this, some basic golden angle plot:
to this example
phi = (sqrt(5)+1)/2;% Número áureo %Golden Number
golden_angle = 2*pi/phi;
max_angle = 10000;
theta = 1:golden_angle:max_angle;% ángulo %Angle
r = sqrt(theta);% radio %Radius
[x,y] = pol2cart(theta,r);% coordenadas polares a cartesianas %Polar to cartesian
figure
plot(x,y,'.','MarkerSize',10);axis off;
I know that the number next to 'MarkerSize' wides the flower petals, but I tried changing theta values in the array but with no particular result, only I’ve changed color but not the size. I also tried making these a for cycle, that creates circles as the golden flower petals, I think, but don't know how to implement it. But how to make them more and more small at the iteration goes?, and I think total number of petals is 2575.
for i = 1:10
%plot(x,y,'.',x(i),y(i),'.','MarkerSize',10*abs(y(i)),'MarkerFaceColor','g')

You can use scatter in place of plot: scatter allows to set the marker size as a parameter:
phi = (sqrt(5)+1)/2;% Número áureo %Golden Number
golden_angle = 2*pi/phi;
max_angle = 10000;
theta = 1:golden_angle:max_angle;% ángulo %Angle
r = sqrt(theta);% radio %Radius
marker_size = 10 * r / sqrt(max_angle); % new
[x,y] = pol2cart(theta,r);% coordenadas polares a cartesianas %Polar to cartesian
figure
scatter(x,y,marker_size, 'fill'); axis off; % new: scatter
marker_size data look good on table, increasing from 0 to 10 with theta.
However, on my Matlab (R2013b), the rendering is very gross.

Related

Create 3D matrix in matlab

I want to plot the temporal evolution of the factor of safety (FS, a quantification for the risk of landslides in a certain area).
This is calculated as follows:
effcohesion=0;
rootcohesion=0;
gammat=12.9E3;
gammaw=9810;
c=0;
deltac=0;
m=0.5;
z=2.5;
phi=16;
slope=rand(20,20)*30 % slope of a gridpoint in area
Strength = c + deltac + (gammat - gammaw.*m).*z.*(cosd(slope).^2);
Stress = gammat.*z.*(sind(slope)).*(cosd(slope));
Part = tand(phi);
FS2 = (Strength./Stress).*(Part)
Now. The value of m (= the height of the water table, which determines the FS) varies throughout the year and is thus not constant. I have a file with precipitation, evaporation, etc. data but to make it not too complicated, I here assume that m is just a function of the day of the year:
mnew=zeros(365,1);
for t=1:365
mnew(t)=(m+t)/150;
end
I now have a dataset with FS for 20x20 points where m =0.5 (=FS2) and a file with the evolution of m during the year (= mnew).
How can I now create a 3D matrix where (1) the spatial variation of FS is stored (so the values of FS over the 20x20 matrix) and (2) the temporal evolution of FS in function of m throughout the year. Eventually, I want a matrix that has both the spatial and temporal evolution of FS in it.
Layer 1 = FS at all 20x20 points on day 1
Layer 2 = FS at all 20x20 points on day 2
etc.
Can someone help me?
Thanks in advance!
A "3D matrix" would more properly be called a rank 3 array. To do this, just paste your FS2 calculation inside the time loop. Instead of m, use the appropriate mnew to calculate FS2. Then set that layer of FS3 (the rank 3 array) to FS2.
Then, layer 1 (day 1) is given by FS3(:,:,1), layer 2 by FS3(:,:,2), etc.
m0=0.5;
% Sizes of array
n1 = 20;
n2 = 20;
n3 = 365;
FS3 = zeros(n1, n2, n3);
mnew=zeros(n3,1);
for t=1:n3
mnew(t)=(m0+t)/150;
effcohesion=0;
rootcohesion=0;
gammat=12.9E3;
gammaw=9810;
c=0;
deltac=0;
m = mnew(t);
z=2.5;
phi=16;
slope=rand(n1,n2)*30; % slope of a gridpoint in area
Strength = c + deltac + (gammat - gammaw.*m).*z.*(cosd(slope).^2);
Stress = gammat.*z.*(sind(slope)).*(cosd(slope));
Part = tand(phi);
FS2 = (Strength./Stress).*(Part);
FS3(:,:,t) = FS2;
end

Connecting random points in MATLAB without intersecting lines

I need help with solving this problem. I have randomly generated points (example on Picture #1) and I want to connect them with lines (example on Picture #2). Lines can't be intersected and after connection, the connected points should look like an irregular area.
%Generating random points
xn = randi([3 7],1,10);
yn = randi([3 6],1,10);
%Generated points
xn = [6,3,7,7,6,6,6,4,6,3];
yn = [5,3,4,3,3,6,5,4,6,3];
Picture #1:
Result should be like this:
Picture #2:
Any idea how to solve this?
I suppose for the general case it can be very difficult to come up with a solution. But, assuming your points are scattered "nicely" there is quite a simple solution.
If you sort your points according to the angle above the x axis of the vector connecting the point and the center of the point cloud then:
P = [xn;yn]; %// group the points as columns in a matrix
c = mean(P,2); %// center point relative to which you compute the angles
d = bsxfun(#minus, P, c ); %// vectors connecting the central point and the dots
th = atan2(d(2,:),d(1,:)); %// angle above x axis
[st si] = sort(th);
sP = P(:,si); %// sorting the points
And that's about it. To plot the result:
sP = [sP sP(:,1)]; %// add the first point again to close the polygon
figure;plot( sP(1,:), sP(2,:), 'x-');axis([0 10 0 10]);
This algorithm will fail if several points has the same angle w.r.t the center of the point cloud.
An example with 20 random points:
P = rand(2,50);
You could adapt the code from another answer I gave for generating random simple polygons of an arbitrary number of sides. The difference here is you already have your set of points chosen and thus implicitly the number of sides you want (i.e. the same as the number of unique points). Here's what the code would look like:
xn = [6,3,7,7,6,6,6,4,6,3]; % Sample x points
yn = [5,3,4,3,3,6,5,4,6,3]; % Sample y points
[~, index] = unique([xn.' yn.'], 'rows', 'stable'); % Get the unique pairs of points
x = xn(index).';
y = yn(index).';
numSides = numel(index);
dt = DelaunayTri(x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
while numEdges ~= numSides
if numEdges > numSides
triIndex = vertexAttachments(dt, boundaryEdges(:,1));
triIndex = triIndex(randperm(numel(triIndex)));
keep = (cellfun('size', triIndex, 2) ~= 1);
end
if (numEdges < numSides) || all(keep)
triIndex = edgeAttachments(dt, boundaryEdges);
triIndex = triIndex(randperm(numel(triIndex)));
triPoints = dt([triIndex{:}], :);
keep = all(ismember(triPoints, boundaryEdges(:,1)), 2);
end
if all(keep)
warning('Couldn''t achieve desired number of sides!');
break
end
triPoints = dt.Triangulation;
triPoints(triIndex{find(~keep, 1)}, :) = [];
dt = TriRep(triPoints, x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
end
boundaryEdges = [boundaryEdges(:,1); boundaryEdges(1,1)];
x = dt.X(boundaryEdges, 1);
y = dt.X(boundaryEdges, 2);
And here's the resulting polygon:
patch(x,y,'w');
hold on;
plot(x,y,'r*');
axis([0 10 0 10]);
Two things to note:
Some sets of points (like the ones you chose here) will not have a unique solution. Notice how my code connected the top 4 points in a slightly different way than you did.
I made use of the TriRep and DelaunayTri classes, both of which may be removed in future MATLAB releases in favor of the delaunayTriangulation class.

MATLAB: vectorize filling of 3D-array

I would like to safe a certain amount of grayscale-images (->2D-arrays) as layers in a 3D-array.
Because it should be very fast for a realtime-application I would like to vectorize the following code, where m is the number of shifts:
for i=1:m
array(:,:,i)=imabsdiff(circshift(img1,[0 i-1]), img2);
end
nispio showed me a very advanced version, which you can see here:
I = speye(size(img1,2)); E = -1*I;
ii = toeplitz(1:m,[1,size(img1,2):-1:2]);
D = vertcat(repmat(I,1,m),E(:,ii));
data_c = shape(abs([double(img1),double(img2)]*D),size(data_r,1),size(data_r,2),m);
At the moment the results of both operations are not the same, maybe it shifts the image into the wrong direction. My knowledge is very limited, so I dont understand the code completely.
You could do this:
M = 16; N = 20; img1 = randi(255,M,N); % Create a random M x N image
ii = toeplitz(1:N,circshift(fliplr(1:N)',1)); % Create an indexing variable
% Create layers that are shifted copies of the image
array = reshape(img1(:,ii),M,N,N);
As long as your image dimensions don't change, you only ever need to create the ii variable once. After that, you can call the last line each time your image changes. I don't know for sure that this will give you a speed advantage over a for loop, but it is vectorized like you requested. :)
UPDATE
In light of the new information shared about the problem, this solution should give you an order of magnitudes increase in speed:
clear all;
% Set image sizes
M = 360; N = 500;
% Number of column shifts to test
ncols = 200;
% Create comparison matrix (see NOTE)
I = speye(N); E = -1*I;
ii = toeplitz([1:N],[1,N:-1:(N-ncols+2)]);
D = vertcat(repmat(I,1,ncols),E(:,ii));
% Generate some test images
img1 = randi(255,M,N);
img2 = randi(255,M,N);
% Compare images (vectorized)
data_c = reshape(abs([img2,img1]*D),M,N,ncols);
% Compare images (for loop)
array = zeros(M,N,ncols); % <-- Pre-allocate this array!
for i=1:ncols
array(:,:,i)=imabsdiff(circshift(img1,[0 i-1]),img2);
end
This uses matrix multiplication to do the comparisons instead of generating a whole bunch of shifted copies of the image.
NOTE: The matrix D should only be generated one time if your image size is not changing. Notice that the D matrix is completely independent of the images, so it would be wasteful to regenerate it every time. However, if the image size does change, you will need to update D.
Edit: I have updated the code to more closely match what you seem to be looking for. Then I throw the "original" for-loop implementation in to show that they give the same result. One thing worth noting about the vectorized version is that it has the potential to be very memory instensive. If ncols = N then the D matrix has N^3 elements. Even though D is sparse, things fall apart fast when you multiply D by the non-sparse images.
Also, notice that I pre-allocate array before the for loop. This is always good practice in Matlab, where practical, and it will almost invariably give you a large performance boost over the dynamic sizing.
If question is understood correctly, I think you need for loop
for v=1:1:20
array(:,:,v)=circshift(image,[0 v]);
end

Print images stored in cell array in matlab

Background:
I am programming SIFT in matlab. I have computed the Difference of Gaussians and have stored them in a 2D cell array. The images in column 2 are half the size of column 1 and so on.
Questions.
Now that I have all of the images stored in my 2D cell array I would like to print them all in one figure.
Im been browsing the web for quite a bit but I haven't seen anything that could help. If anyone could point me in the right direction or provide an example it would be greatly appriciated.
Cheers
If you want a really simple solution then just make a composite image and fill in the regions with the images in the gaussian pyramid. I've given an example code below the works for my case but needs to be adapted for yours.
Code:
% Get total width and height
width_total = 0;
height_total = 0;
for i = 0:3 % Cycle over scales - 4 total
width_total = width_total+size(obj.gaussianpyramid{i+1,1},2);
height_total = height_total+size(obj.gaussianpyramid{i+1,1},1);
end
% Form composite gaussian
compositegaussian = zeros(width_total,height_total);
ind_x = 0;
for i = 0:3 % Cycle over octaves - 4 total
for j = 0:4 % Cycle over scales - 5 total
ind_y = j*size(obj.gaussianpyramid{i+1,j+1},1);
compositegaussian(ind_y+1:ind_y+size(obj.gaussianpyramid{i+1,j+1},1),ind_x+1:ind_x+size(obj.gaussianpyramid{i+1,j+1},2)) = obj.gaussianpyramid{i+1,j+1};
end
ind_x = ind_x + size(obj.gaussianpyramid{i+1,1},2);
end
figure, imshow(compositegaussian,[]);
Output:
Lets generate random 5x2 cell array where the first columns contains 10x10 images and the second - 5x5 images:
c = cell(5,2);
for k=1:5
c{k,1} = uint8(255 * rand(10));
c{k,2} = uint8(255 * rand(5));
end
The following code illustrates them:
figure;
n = size(c, 1);
for k = 1 : n
subplot(n, 2, k * 2 - 1);
image(c{k,1});
subplot(n, 2, k * 2);
image(c{k,2});
end
If the images are upside down, use set(gca,'YDir','normal'); after each image() call.

Calculate initial velocity to move a set distance with inertia

I want to move something a set distance. However in my system there is inertia/drag/negative accelaration. I'm using a simple calculation like this for it:
v = oldV + ((targetV - oldV) * inertia)
Applying that over a number of frames makes the movement 'ramp up' or decay, eg:
v = 10 + ((0 - 10) * 0.25) = 7.5 // velocity changes from 10 to 7.5 this frame
So I know the distance I want to travel and the acceleration, but not the initial velocity that will get me there. Maybe a better explanation is I want to know how hard to hit a billiard ball so that it stops on a certain point.
I've been looking at Equations of motion (http://en.wikipedia.org/wiki/Equations_of_motion) but can't work out what the correct one for my problem is...
Any ideas? Thanks - I am from a design not science background.
Update: Fiirhok has a solution with a fixed acceleration value; HTML+jQuery demo:
http://pastebin.com/ekDwCYvj
Is there any way to do this with a fractional value or an easing function? The benefit of that in my experience is that fixed acceleration and frame based animation sometimes overshoots the final point and needs to be forced, creating a slight snapping glitch.
This is a simple kinematics problem.
At some time t, the velocity (v) of an object under constant acceleration is described by:
v = v0 + at
Where v0 is the initial velocity and a is the acceleration. In your case, the final velocity is zero (the object is stopped) so we can solve for t:
t = -v0/a
To find the total difference traveled, we take the integral of the velocity (the first equation) over time. I haven't done an integral in years, but I'm pretty sure this one works out to:
d = v0t + 1/2 * at^2
We can substitute in the equation for t we developed ealier:
d = v0^2/a + 1/2 * v0^2 / a
And the solve for v0:
v0 = sqrt(-2ad)
Or, in a more programming-language format:
initialVelocity = sqrt( -2 * acceleration * distance );
The acceleration in this case is negative (the object is slowing down), and I'm assuming that it's constant, otherwise this gets more complicated.
If you want to use this inside a loop with a finite number of steps, you'll need to be a little careful. Each iteration of the loop represents a period of time. The object will move an amount equal to the average velocity times the length of time. A sample loop with the length of time of an iteration equal to 1 would look something like this:
position = 0;
currentVelocity = initialVelocity;
while( currentVelocity > 0 )
{
averageVelocity = currentVelocity + (acceleration / 2);
position = position + averageVelocity;
currentVelocity += acceleration;
}
If you want to move a set distance, use the following:
Distance travelled is just the integral of velocity with respect to time. You need to integrate your expression with respect to time with limits [v, 0] and this will give you an expression for distance in terms of v (initial velocity).

Resources