Given an angle and having drawn a line from the center of a bounding box, how can we compute the coordinates at which the line will intersect the bounding box?
Please have a look at the following diagram:
As you can see, for example, at angle 0 the line intersects point (0.5, 1)
How can we turn this problem into a computable formula that accepts an angle and returns x and y coordinates?
You can solve by using trigonometry and handling each 45 degree section separately:
Given:
xmin, xmax (limits of x axis for boxed region)
ymin, ymax (limits of y axis for boxed region)
a (angle)
output coordinates of x and y
width = (xmax - xmin)
height = (ymax - ymin):
Angle range; x; y
(0<= a <= 45); x = xmin + (tan(a)*(width/2) + width/2; y = ymax
(45<= a <= 90); x = xmax; y = ymin + (tan(90-a)*height/2) + height/2
(90<= a <= 135); x = xmax;y = ymin + (tan(a-90)*height/2) + height/2
(135<= a <= 180); x = xmin + (tan(180-a)*width/2)+width/2; y = ymin
(180<= a <= 225); x = xmin - (tan(a-180)*width/2)+width/2; y = ymin
(225<= a <= 270); x = xmin; y = ymin -(tan(270-a)*height/2)+height/2
(270<= a <= 315); x = xmin; y = ymin + (tan(a-270)*height/2)+height/2
(315<= a <= 360); x = xmin -(tan(360-a)*width/2)+width/2; y = ymax
Related
I am constructing a rectangle based on a point with a parameter of length and width. and I want am trying to rotate this rectangle based on the calculated direction vector
[d1 d2] = [(x_old - X_cur) (Y_old - YCur)]
Code:
% Point coordinates current positon (small dark circle)
P = [2; 2];
% Direction vector
d = [1 1];
% Dimensions of rectangle
l = 20;
w = 10;
% %direction angle:
A = (atan2(d(1), d(2)));
% Original corner points of rectangle (straight rectangle)
x1 = P(1) -w/2;
y1 = P(2)+l;
x2 = P(1)+ w/2;
y2 = P(2)+l;
x3 = P(1)+ w/2;
y3 = P(2);
x4 = P(1) -w/2;
y4 = P(2);
rect = [x1 x2 x3 x4; y1 y2 y3 y4];
%rotated rectangles coordinates:
x1_new = P(1)+ ((x1 - P(1))* cos(A)) - (y1 - P(2))*sin(A);
y1_new = P(2) +(x1-P(1))*sin(A) + (y1-P(2))*cos(A);
x2_new = P(1)+ (x2 - P(1))* cos(A) - (y2 - P(2))*sin(A);
y2_new = P(2) +(x2-P(1))*sin(A) + (y2-P(2))*cos(A);
x3_new = P(1)+ (x3 - P(1))* cos(A) - (y3 - P(2))*sin(A);
y3_new = P(2) +(x3-P(1))*sin(A) + (y3-P(2))*cos(A);
x4_new = P(1)+ (x4 - P(1))* cos(A) - (y4 - P(2))*sin(A);
y4_new = P(2) +(x4-P(1))*sin(A) + (y4-P(2))*cos(A);
new_rect = [x1_new x2_new x3_new x4_new; y1_new y2_new y3_new y4_new];
%
%plot:
figure(1);
plot(P(1), P(2), 'k.', 'MarkerSize', 41);
hold on;
plot([P(1) P(1)+d(1)*10], [P(2) P(2)+d(2)*10], 'b'); %plot the direction
patch(new_rect(1,:),new_rect(2,:), 'b', 'FaceAlpha', 0.2); %plot rotated rectangle
patch(rect(1,:),rect(2,:),'b') %plot straight rectangle
hold off
I know there is some mistake in rotating the rectangle because its rotating on the other side. I tried all the possible combinations while creating the new coordinates.
any suggestions on where I am going wrong would be helpful
You can use a rotation matrix. The rotation will be applied to each coordinate at once:
% Rectangle coordinate
% x y
R = [2, 3
5, 3
5, 8
2, 8]
%Anonymous function that will create the rotation matrix (input in radian)
romat = #(a)[cos(a), -sin(a); sin(a), cos(a)];
%Rotation of the Rectangle, with A = atan2(d(1), d(2));
Rrot = ((R-mean(R))*romat(A))+mean(R)
During the operation we have to substract the center of mass of the rectangle so the rotation will occur around the [0,0] point.
Results:
hold on
%Rectangle
patch(R(:,1),R(:,2),'green')
%Rotated rectangle
patch(Rrot(:,1),Rrot(:,2),'red','facealpha',0.5)
%Euclidian vector
quiver(mean(R(:,1)),mean(R(:,2)),d(1),d(2),...
'ro','MarkerFaceColor','red','linewidth',3)
axis equal
What's wrong with your code:
You apply the following rotation matrix:
M = [cos(a) sin(a)
-sin(a) cos(a)]
instead of
M = [cos(a) -sin(a)
sin(a) cos(a)]
I want to fill this ellipse with N random points inside it
any help I'd be glad
clear ,close all;
xCenter = 15;
yCenter = 10;
xRadius = 3.5;
yRadius = 8;
theta = 0 : 0.01 : 2*pi;
N = 100; % N rand points
x = xRadius * cos(theta) + xCenter;
y = yRadius * sin(theta) + yCenter;
plot(x, y, 'LineWidth', 1);
axis square;
grid on;
I tried this code to generate 100 points inside the ellipse with specific parameters but I did not achieve my goal,
xCenter = 5;
yCenter = 3;
xRadius = 3.5;
yRadius = 8;
theta = 0 : 0.01 : 2*pi;
N = 100;
x = xRadius * cos(theta) + xCenter;
y = yRadius * sin(theta) + yCenter;
xq=(rand(N,1)*(2*yRadius) - yRadius);
yq=(rand(N,1)*(2*yRadius) - yRadius);
in = inpolygon(xq,yq,x,y);
hold on
inX = xq(in);
inY = yq(in);
outX = xq(~in);
outY = yq(~in);
plot(inX, inY , 'ro');
plot(outX, outY, 'b*');
plot(x, y, 'LineWidth', 1);
axis square;
grid on;
Sardar's answer produces points not evenly distributed within the ellipse. This code produces an even distribution of points:
xCenter = 15;
yCenter = 10;
xRadius = 3.5;
yRadius = 8;
N = 100;
% Generate points in the ellipse
t = 2*pi * rand(N,1);
d = sqrt(rand(N,1));
x = xCenter + xRadius * d .* cos(t);
y = yCenter + yRadius * d .* sin(t);
plot(x,y,'o')
The difference is the sqrt on the normalized (0 to 1) distance from the origin d. By computing this square root, you increase the density of points closer to the edge of the ellipse. This compensates for points otherwise being too dense close to the center. The uniform distribution of points along that normalized distance is what causes higher density of points near the center.
Generate random numbers for x and y axes between the specified limits, i.e. xRadius and yRadius, for the respective axes. Read Random Numbers Within a Specific Range to understand how to generate those random numbers.
hold on;
RndAngles = rand(N,1); %Same angle should be used
Xpoints = (xRadius.*rand(N,1) .*cos(2*pi*RndAngles))+ xCenter;
Ypoints = (yRadius.*rand(N,1) .*sin(2*pi*RndAngles))+ yCenter;
plot(Xpoints,Ypoints,'o'); %Plot those points
Output:
I've been trying to generate points along the ring of a 2D disc (both translated and rotated) in 3D space using only the disc's position and normal.
I've been using the following code to generate points and have been testing it in Matlab (but will be utilising this in c#) to check that the points are generated correctly, however it doesn't seem to be generating points correctly.
numPoints = 25;
radius = 1;
pos = [1; 2; 3];
dir = normc([3; 4; 6]); % normalised
function [pointsT, points] = GenerateDiscPoints(numPoints, radius, pos, dir)
points = zeros(numPoints, 3);
pointsT = zeros(numPoints, 3);
% Angle between points
angle = 2 * pi / numPoints;
for i = 1:numPoints+1
% Current point angle
theta = angle * i;
% Generate point in flat disc (y is vertical axis in Unity)
x = radius * cos(theta) + pos(1);
y = 0 + pos(2);
z = radius * sin(theta) + pos(3);
% Save points
points(i, 1) = x;
points(i, 2) = y;
points(i, 3) = z;
% Calculate t value to translate points
t = (dir(1) * pos(1) - dir(1) * x + dir(2) * pos(2) - dir(2) * y + dir(3) * pos(3) - dir(3) * z) / (dir(1)*dir(1) + dir(2)*dir(2) + dir(3)*dir(3));
% Translate points to correct location
xT = x + t*dir(1);
yT = y + t*dir(2);
zT = z + t*dir(3);
% Save translated points
pointsT(i, 1) = xT;
pointsT(i, 2) = yT;
pointsT(i, 3) = zT;
end
% Plot
figure;
hold all;
grid on;
scatter3(points(:,1), points(:,2), points(:,3), 25, 'r');
scatter3(pointsT(:,1), pointsT(:,2), pointsT(:,3), 25, 'g');
p3 = line([pos(1) pos(1)+dir(1)], [pos(2) pos(2)+dir(2)], [pos(3) pos(3)+dir(3)]);
set(p3, 'Color', 'blue');
end
The blue line is the normal of the disc, the red points are the points before being translated, and the green points are the points after being translated. To my eye it appears that the translated points don't seem to be generating in a disc that has the normal specified.
What's wrong with my current algorithm? What would a better way to do this be?
A simple linear translation along the direction of dir is insufficient - you'll end up with the projection of the circle on the plane at pos with normal dir, i.e. an ellipse.
You could either:
Use quaternions to construct a rotation matrix to re-orientate your generated circle to dir.
Creating this quaternion: https://stackoverflow.com/a/1171995/8204776
Converting it to a matrix: https://stackoverflow.com/a/1556470/8204776
or
Construct an orthogonal basis at pos where one axis is dir.
Easy way to do this:
Check if the X-axis is parallel to dir - ideally do abs(dot(dir, X)) < 0.8 (assuming both are normalized), so they are not too close to each other
If (1) is true then take dir2 = Y, else dir2 = X.
To create the first basis vector, A = normalize(cross(dir, dir2)).
To create the second, B = cross(dir, A).
Now you can generate points at each value of theta by pos + radius * (A * cos(theta) + B * sin(theta)) (in vector notation).
Please help me in finding the coordinates of the point marked with green dots in the attached image. The slope of the line is known and the coordinates of the center are known for an image. I want to write a code in MATLAB. Please give me ideas for the same.
The image consists of the center points whose coordinates are known, and green dots coordinates are to be determined knowing the slope of the line passing through the center point.
If the center point is known, I assume, there is no need to do image processing.
What you need is a linear equation.
y = tan(slope) * x
And then you just simply find x1 and x2, because y1 and y2are also known from the photo.
I created vector of coordinates that passes center coordinate, and have the desired slope.
I used went through polar coordinates to create X, Y coordinates vectors.
After finding the coordinates, I searched the green dots on the curve.
My solution is not so simple for understanding (not most elegant)...
Here is my code:
%Input image (for testing).
I = imread('cameraman.tif');
I = cat(3, I, I, I); %Make I it "color" image where (R = G = B).
center = [100, 100];
slope = 1.5;
%Mark the center point with red (for debugging).
I(center(1)-1:center(1)+1, center(2)-1:center(2)+1, 1) = 255;
%Put green dots (for debugging).
x0 = 123;y0 = 65;
x1 = 12;y1 = 232;
I(y0-1:y0+1, x0-1:x0+1, 2) = 255;I(y0, x0, 1) = 0;I(y0, x0, 3) = 0;
I(y1-1:y1+1, x1-1:x1+1, 2) = 255;I(y1, x1, 1) = 0;I(y1, x1, 3) = 0;
% #
% 1.5# #
% # #
% # #
% ## alpha
% ############
% 1
alpha = -atan2(slope, 1);
%Create vector of "radius" (distance from the center).
r = -norm(size(I))/2:0.2:norm(size(I))/2;
%Each (x,y) coordinate is on the line passing through center point
x = r*cos(alpha) + center(2);
y = r*sin(alpha) + center(1);
%Remove x and y outsize image boundaries from x, y arrays.
X = x;Y = y;
X((x < 1) | (x > size(I,2)) | (y < 1) | (y > size(I,1))) = [];
Y((x < 1) | (x > size(I,2)) | (y < 1) | (y > size(I,1))) = [];
%Round X and Y (to be legal pixel coordinates).
X = round(X);
Y = round(Y);
R = zeros(size(X)) + 1; %Coordinate of 1'rd plane (red channel).
G = zeros(size(X)) + 2; %Coordinate of 2'rd plane (green channel).
B = zeros(size(X)) + 3; %Coordinate of 3'rd plane (blue channel).
%V gets values of pixels channel pixels in the curve.
rV = I(sub2ind(size(I), Y, X, R)); %Red channel values.
gV = I(sub2ind(size(I), Y, X, G)); %Green channel values.
bV = I(sub2ind(size(I), Y, X, B)); %Blue channel values.
%Find green dots where r, g, b = 255.
V = (rV == 0) & (gV == 255) & (bV == 0);
%Mark X,Y coordinates with blue color (for debugging).
I(sub2ind(size(I), Y, X, B)) = 255;
figure;imshow(I)
v0 = find(V, 1, 'last');
v1 = find(V, 1);
greenDot0 = [Y(v0), X(v0)]
greenDot1 = [Y(v1), X(v1)]
Result image (used for testing):
I made star using this code:
t = 0:4/5*pi:4*pi;
x = sin(t);
y = cos(t);
star = plot(x, y);
axis([-1 11 -1 11])
Now I need to rotate and move this star at the same time. I tried this:
for i=1:0.1:10;
zAxis = [0 0 1];
center = [0 0 0];
rotate(star, zAxis, 5, center);
x = x+0.1;
y = y+0.1;
set(star, 'x', x, 'y', y);
pause(0.1);
end
But this code only moves star and doesn't rotate it. If I delete "set" command then it rotates. How can I combine those two actions?
This can do the job..
t = 0:4/5*pi:4*pi;
x = sin(t);
y = cos(t) ;
y = y-mean(y);
x = x-mean(x); % # barycentric coordinates
% # rotation and translation
trasl = #(dx,dy) [dy; dx]; % # this vector will be rigidly added to each point of the system
rot = #(theta) [cos(theta) -sin(theta); sin(theta) cos(theta)]; % # this will provide rotation of angle theta
for i = 1:50
% # application of the roto-translation
% # a diagonal translation of x = i*.1 , y = i*.1 is added to the star
% # once a rotation of angle i*pi/50 is performed
x_t = bsxfun(#plus,rot(i*pi/50)*([x;y]), trasl(i*.1,i*.1) );
star = plot(x_t(1,:), x_t(2,:));
axis([-1 11 -1 11])
pause(.1)
end
In principle, homogeneous coordinates (in this case in the 2D projective space) allow one to do the same job in a neater way; in fact, they would allow one to use just one linear operator (3x3 matrix).
Homogeneous coordinates version:
Op = #(theta,dx,dy) [ rot(theta) , trasl(dx,dy) ; 0 0 1];
for i = 1:50
x_t = Op(i*pi/50,i*.1,i*.1)*[x;y;ones(size(x))];
star = plot(x_t(1,:), x_t(2,:));
axis([-1 11 -1 11])
pause(.1)
end
You can just use a rotation matrix to compute the correct transformation on the vectors [x; y]:
theta = 5 * (pi / 180); % 5 deg in radians
Arot = [cos(theta) -sin(theta); sin(theta) cos(theta)];
xyRot = Arot * [x; y]; % rotates the points by theta
xyTrans = xyRot + 0.1; % translates all points by 0.1
set(star, 'x', xyTrans(1, :), 'y', xyTrans(2, :));