Estimating an ellipse with a multi-variate Gaussian - matlab

In MATLAB, say I have the parameters for an ellipse:
(x,y) center
Minor axis radius
Major axis radius
Angle of rotation
Now, I want to generate random points that lie within that ellipse, approximated from a 2D gaussian.
My attempt thus far is this:
num_samps = 100;
data = [randn(num_samps, 1)+x_center randn(num_samps, 1)+y_center];
This gives me a cluster of data that's approximately centered at the center, however if I draw the ellipse over the top some of the points might still be outside.
How do I enforce the axis rules and the rotation?
Thanks.

my assumptions
x_center = h
y_center = k
Minor Axis Radius = b
Major Axis Raduis = a
rotation angle = alpha
h=0;
k=0;
b=5;
a=10;
alpha=30;
num_samps = 100;
data = [randn(num_samps, 1)+h randn(num_samps, 1)+k];
chk=(((((data(:,1)-h).*cos(alpha)+(data(:,2)-k).*sin(alpha))./a).^2) +...
(((data(:,1)-h).*sin(alpha)+(data(:,2)-k).*cos(alpha))./b).^2)<=1;
idx=find(chk==0);
if ~isempty(idx)
data(idx,:)=data(idx,:)-.5*ones(length(idx),2);
end

Related

Causing a rotating arc to touch another curve and not intersect it (Matlab code)

I want to write a code where an arc stops rotating as soon as it comes in contact with a semi-circle.
I have written a code to do so, my arc does not just touch the circle but it slightly intersects it.
I have put rotation of arc inside a while loop by using linspace() to change theta. I used polyxpoly() for finding intersection. Condition for the while loop is that as long as I have empty array the loop continues, but as soon as I get a value from polyxpoly() my loop stops.
However, at the place of touch the theta value exceeds what I needed, so as a result I get an intersection.
How do I modify the code so that the arc will touch the semi-circle and not intersect it?
Here is the output. Click the link below
Image of intersection but I need touch and not intersection
clc,clear
R = 5; % radius of a circle
r = 10; % radius of arc
aa = 60*pi/180; % arc angle
ap = 0*pi/180; % arc position angle
% defining the semi-circle about the origin
t = linspace(0,pi);
[x,y] = pol2cart(t,R); % circle data
% Shifting circle centre to (3.5,0)
x=x+3.5;
y=y+0;
% defining the arc about the origin
t1 = linspace(0,aa)-aa/2+ap;
[x1,y1] = pol2cart(t1,r); % arc data
% shifting arc-lower-end to (14,0)
delx=14-x1(1); % Finding the x difference between arc-lower-end x-coordinate & 14
dely=0-y1(1); % Finding the y difference between arc-lower-end y-coordinate & 0
x1=x1+delx;
y1=y1+dely;
theta =linspace(0,pi,1000);
i=1;
xc=[];
yc=[];
while isempty(xc)&& isempty(yc)
% create a matrix of these points, which will be useful in future calculations
v = [x1;y1];
% choose a point which will be the center of rotation
x_center = 14;
y_center = 0;
% create a matrix which will be used later in calculations
center = repmat([x_center; y_center], 1, length(x1));
% define a 60 degree counter-clockwise rotation matrix
R = [cos(theta(i)) -sin(theta(i)); sin(theta(i)) cos(theta(i))];
% do the rotation...
s = v - center; % shift points in the plane so that the center of rotation is at the origin
so = R*s; % apply the rotation about the origin
vo = so + center; % shift again so the origin goes back to the desired center of rotation
% this can be done in one line as:
% vo = R*(v - center) + center
% pick out the vectors of rotated x- and y-data
x_rotated = vo(1,:);
y_rotated = vo(2,:);
[xc,yc] = polyxpoly(x_rotated,y_rotated,x,y)
[xc1,yc1] = polyxpoly(x1,y1,x,y)
i=i+1;
end
% make a plot
plot(x,y)
hold on
plot(x1, y1, 'k-', x_rotated, y_rotated, 'r-', x_center, y_center, 'bo');
axis equal
I need to find way it contacts a circle and does not intersect it.
The code is in matlab.
Any suggestions are welcome.
This is the problem of collision detection. Most, if not all, methods I know of in collision detection requires the computer to check for intersections of some sort. It's very difficult (if not impossible) to have two objects "just touch" in simulations, because you'll need the precise (analytically solved) location of the boundaries of those objects.
polyxpoly() is a function to return the intersection of two polygons. So unfortunately, if you insist that the arc cannot touch, then you cannot use polyxpoly(). In that extreme case, you'll have to solve some mathematical equation for when the tip of the arc coincides with a point on the circle perfectly, then simulate up until that point in time.
But realistically, what you need is a finer simulation (although I personally think what you have alone is good enough). So in every simulation step, you calculate a smaller movement, so that when the arc eventually intersects, only a very small amount of the arc intersects.

Drawing circles around points in a plot

I have two matrices
timeline = [0.0008 0.0012 0.0016 0.0020 0.0024 0.0028];
Origdata =
79.8400 69.9390 50.0410 55.5082 34.5200 37.4486 31.4237 27.3532 23.2860 19.3039
79.7600 69.8193 49.8822 55.3115 34.2800 37.1730 31.1044 26.9942 22.8876 18.9061
79.6800 69.6996 49.7233 55.1148 34.0400 36.8975 30.7850 26.6352 22.4891 18.5084
79.6000 69.5799 49.5645 54.9181 33.8000 36.6221 30.4657 26.2762 22.0907 18.1108
79.5200 69.4602 49.4057 54.7215 33.5600 36.3467 30.1464 25.9173 21.6924 17.7133
79.4400 69.3405 49.2469 54.5249 33.3200 36.0714 29.8271 25.5584 21.2941 17.3159
When I plot them, I get a graph like below.
plot(timeline, Origdata, '.');
How can I draw a circle of radius 0.3524 value around each point? This radius should be relative to the y-axis only.
You can do this easily using viscircles (which requires the Image Processing Toolbox) however I don't think that the output is actually what you're expecting.
radius = 0.3524;
dots = plot(timeline, Origdata, '.');
hold on
for k = 1:numel(dots)
plotdata = get(dots(k));
centers = [plotdata.XData(:), plotdata.YData(:)];
% Ensure the the colors match the original plot
color = get(dots(k), 'Color');
viscircles(centers, radius * ones(size(centers(:,1))), 'Color', color);
end
The reason that it looks like this is because your X data is very close together relative to your y data and for circles to appear as circles, I have forced the x and y scaling of the axes to be equal (axis equal)
Edit
If you only want the radius to be relative to the y axis (distance) then we actually need to draw ellipses with an x and y radius. We want to scale the "x-radius" to make it appear as a circle regardless of your true axes aspect ratio, something like this can actually do that.
The trick to the code below is setting the data and plot aspect ratios (pbaspect and daspect) to manual. This ensures that the aspect ratio of the axes doesn't change during zoom, resizing, etc and makes sure that our "circles" remain circular-looking.
dots = plot(timeline, Origdata, '.');
drawnow
% Force the aspect ratio to not change (keep the circles, as circles)
pbaspect('manual')
daspect('manual')
hold on
aspectRatio = daspect;
t = linspace(0, 2*pi, 100);
t(end+1) = NaN;
radius = 4.3524;
% Scale the radii for each axis
yradius = radius;
xradius = radius * aspectRatio(1)/aspectRatio(2);
% Create a circle "template" with a trailing NaN to disconnect consecutive circles
t = linspace(0, 2*pi, 100);
t(end+1) = NaN;
circle = [xradius*cos(t(:)), yradius*sin(t(:))];
for k = 1:numel(dots)
x = get(dots(k), 'XData');
y = get(dots(k), 'YData');
color = get(dots(k), 'Color');
% Center circle template at all points
circles = arrayfun(#(x,y)bsxfun(#plus, [x,y], circle), x, y, 'uni', 0);
circles = cat(1, circles{:});
plot(circles(:,1), circles(:,2), 'Color', color)
end
Just to demonstrate, if we increase the circle radius to 4.3524 we can see the circles better.
And this works with all resizing etc.
To draw circles in MATLAB, you obviously have to use the rectangle function ;)
As mentioned in my comment, the size of 0.3524 does not match your axis, so I chose different sizes to have the circles actually visible, These are rx and ry
timeline = [0.0008 0.0012 0.0016 0.0020 0.0024 0.0028];
Orgidata =[79.8400 69.9390 50.0410 55.5082 34.5200 37.4486 31.4237 27.3532 23.2860 19.3039
79.7600 69.8193 49.8822 55.3115 34.2800 37.1730 31.1044 26.9942 22.8876 18.9061
79.6800 69.6996 49.7233 55.1148 34.0400 36.8975 30.7850 26.6352 22.4891 18.5084
79.6000 69.5799 49.5645 54.9181 33.8000 36.6221 30.4657 26.2762 22.0907 18.1108
79.5200 69.4602 49.4057 54.7215 33.5600 36.3467 30.1464 25.9173 21.6924 17.7133
79.4400 69.3405 49.2469 54.5249 33.3200 36.0714 29.8271 25.5584 21.2941 17.3159];
ry=1;
rx=0.0001;
dots=plot(timeline, Orgidata , '.');
hold on
for ix=1:size(Orgidata ,1)
for jx=1:size(Orgidata ,2)
rectangle('Position',[timeline(ix)-(rx/2),Orgidata(ix,jx)-(ry/2),rx,ry],'Curvature',[1,1],'EdgeColor',get(dots(jx), 'Color'));
end
end

How translate a point on a circle?

I am trying to create a circle from the given radius and translate the circle.
edia = 10; %diameter
theta=linspace(0,2*pi, 100); %100 evenly spaced points.
radius = edia./2;
x = radius.*cos(theta);
y = radius.*sin(theta);
plot(x,y, 'k')
axis equal
axis([-edia, edia, -edia, edia]);
After creating a circle using the code, I have to translate it but I have no idea how to do it.
This is the circle that I have
and this is what I am suppose to get after translating
Thank you.
for this simple case, just add the shift directly.
close all
edia = 10; %diameter
theta=linspace(0,2*pi, 100); %100 evenly spaced points.
radius = edia./2;
x = radius.*cos(theta);
y = radius.*sin(theta);
plot(x,y, 'k')
axis equal
axis([-edia, edia, -edia, edia]);
newX=3; newY=4;
hold on;
plot(x+newX,y+newY, '-.')

How to draw a circle with perspective transformation

I want to draw a circle with perspective tansformation in Matlab. Here I have used sample of code to draw a circle. If I rotate this circle using perspective tansform this must be ellipse. I want to draw both axis rotation(X & Y) of a circle. Now I am struggled to draw a perspetive rotation of this circle.
I need to use radious of the circle, x axis roation angle and y axis roation angle as input parameters.
Rimg = zeros(600,600);
ri = 100;
xcentre = 300;
ycentre = 300;
for r = 0:ri
for rad = 0:(pi/720):(2*pi)
xi = round(xcentre+(r*cos(rad)));
yi = round(ycentre+(r*sin(rad)));
Rimg(xi,yi) = 1;
end
end
imshow(Rimg,[]);
The first image shows my circle and the second image shows the expected result. This is only rotated in x axis. But I need both axis rotation in a single image.

Generating a 3D plot by revolution of a curve

I'm trying to revolve a 2D curve to generate a 3D surface plot.
I've tried using
[X,Z,Y] = cylinder(u);
surf(X,Y,Z), axis square
this, however, revolves my curve around the wrong axis. How do I go about changing the axis?
Thanks alot.
To rotate the axis of the cylinder, you can simply change the order of X, Y, and Z.
[X,Y,Z] = cylinder(u);
surf(X,Y,Z) %# rotation around Z
surf(Z,X,Y) %# rotation around X
surf(Y,Z,X) %# rotation around Y
EDIT
To change the axis of rotation of your curve, you have to calculate the surface. For example, to rotate y = sin(alpha) with alpha = 0:0.1:pi around the y-axis, you can write
r = 0:0.1:pi;
z = sin(r);
theta = 0:pi/20:2*pi;
xx = bsxfun(#times,r',cos(theta));
yy = bsxfun(#times,r',sin(theta));
zz = repmat(z',1,length(theta));
dfig,surf(xx,yy,zz)
axis equal