Algorithm for rotation a point along with the frame (relatively) - algorithm

We have an application where we design a label, and then create an image from the design which is sent to a printer. The image is made into a byte stream before being sent over TCP/IP.
The short story is that we have a rotation setting that automatically calculates the position of the different elements on the label. And it is not working properly.
I was wondering if there is an easy way to calculate position of an element relative to height/width of the containing rectangle (label size). It also needs to take into account that this is a bitmap, so the top left corner is (0,0). This is what confuses me, because most of the rotation algorithms I have found operates on an a regular X/Y axis.
So, say I have a label 500 x 300 (Width x height) with a point (text-box) at 100,100 (upper leftish). I want to rotate this 90 degrees, so that the label is now 300 x 500, with the text-box at 200 x 100 (upper rightish). Note, the rectangle calculation takes care of itself, I just need to find the point relative to the new sides.
I found 180 degrees (width - x, height - y), but having a hard time spotting the algorithm for 90 (and 270)
Probably no rocket surgery involved here, but I have stared myself blind at this problem.

A simple observation can show that for clockwise pi/2 rotation the formula is (hight - y, x). You can arrive to it from the general pi/2 rotation formula, (-y, x). (If you consider that 'origin of coordinates' changes too)
Getting 270-degrees formula is very similar.

If you want to rotate you label counterclockwise by 90 degrees, then each point (x, y) of the label "maps" to (-y, x). In the case of 270 degrees rotation (or 90 degrees clockwise, which is the same) (x, y) becomes (y, -x). Hope this helps.

Related

How to calculate Arc length dependently of start angle?

I am building a road editor where one can drag predefined road segments together and combine them to a connected road. One of those segments is a right curve.
The curve is drawn as SVG (using D3 arc path function) and has two handles to change the radius and the length directly within the SVG (small black circle changes length and small black square changes the radius). I use a d3 drag handler on the handles.
To calculate the new central angle I do as follows:
get YOffset from center point of the arc
flip YOffset (to match screen y and math)
get corresponding x value with Pythagoras (x = Math.sqrt(r^2 - YOffset^2))
get the respective central angle (Math.PI / 2 - Math.atan2(YOffset, x);
This will only work if the arc starts at PI/2 like in the figure. If I add further arcs with arbitrary start angles (see next figure, red arc), my solution wont work.
I'm looking for a general solution so it will work for any arc regardless of its start angle.
To me it seems this is not much of a programming problem, but of math. What I understand is: given a start point (x₁, y₁), an end pont(x₂, y₂) and a radius r, what is the angle α?
You can compute the distance d between the two points. Half its length is the far leg of a right triangle with r as its hypothenuse. d/2r is the sinus of the near angle; double that and you have the angle between the end points.
(And, having α expressed in radians, the path length is simply α * r.)

Calculating the rotation vector of a sphere

I'm trying to calculate the axis of rotation of a ball which is moving and spinning at the same time, i.e. I want the vector along the axis that the ball is spinning on.
For every frame I know the x, y and z locations of 3 specific points on the surface of the sphere. I assume that by looking at how these 3 points have moved in successive frames, you can calculate the axis of rotation of the ball, however I have very little experience with this kind of maths, any help would be appreciated!
You could use the fact that the direction a position vector moves in will always be perpendicular to the axis of rotation. Therefore, if you have two position vectors v1 and v2 at successive times (for the same point), use
This gives you an equation with three unknowns (the components of w, the rotation axis). If you then plug in all three points you have knowledge of you should be able to solve these simultaneous equations and work out w.

Limiting atan2 to specific angle ranges

I want my Player sprite to rotate following the position of the mouse cursor.
I'm using atan2 to set up a 360 degree rotation action script for my Player sprite.
atan2(XMouse-XPlayer,YMouse-YPlayer) - 90
Using this, 90 degrees is straight up, 0 is direct right, 270 degrees is straight down. I need the Player sprite to sit on the Left side of the screen and only face the Right side of the screen when it rotates (meaning it can't look backwards).
I need to limit my angles to both conditions; less than 90 degrees OR greater than 270 degrees.
Ideally, I'd like to set 0 degrees to straight up, then I only have to set my conditions to Angles less than 180 degrees (one conditional rather than two).
Can that be done?
Yes. Use min() and max() (although you haven't said what language you're working in...)
If you use radians, then the condition to check for is that abs(theta) < PI/2 is always true. Here's an image from Wikipedia, just to show you what I mean.
In order to have 0 degrees straight up and clockwise movement from 0 to 360 degrees
use the formula:
f(x,y)=180-90*(1+sign(y))* (1-sign(x^2))-45*(2+sign(y))*sign(x)
-180/pi()*sign(x*y)*atan((abs(y)-abs(x))/(abs(y)+abs(x)))

How do you map a point(x,y) on a 2D image to 3D space? (illustration provided)

I have a stack of images (about 180 of them) and there are 2 stars (just basic annotations) on every single image. Hence, the position (x,y) of the two stars are provided initially. The dimensions of all these images are fixed and constant.
The 'distance' between the image is about 1o with the origin to be the center (width/2, height/2) of every single 2D image. Note that, if this is plotted out and interpolated nicely, the stars would actually form a ring of an irregular shape.
The dotted red circle and dotted purple circle are there to give a stronger scent of a 3D space and the arrangement of the 2D images (like a fan). It also indicates that each slice is about 1o apart.
With the provided (x,y) that appeared in the 2D image, how do you get the corresponding (x,y,z) in the 3d space knowing that each image is about 1o apart?
I know that MATLAB had 3D plotting capabilities, how should I go about implementing the solution to the above scenario? (Unfortunately, I have very little experience plotting 3D with MATLAB)
SOLUTION
Based on the accepted answer, I looked up a bit further: spherical coordinate system. Based on the computation of phi, rho and theta, I could reconstruct the ring without problems. Hopefully this helps anyone with similar problems.
I have also documented the solution here. I hope it helps someone out there, too:
http://gray-suit.blogspot.com/2011/07/spherical-coordinate-system.html
I believe the y coordinate stays as is for 3D, so we can treat this as converting 2D x and image angle to an x and z when viewed top down.
The 2D x coordinate is the distance from the origin in 3D space (viewed top down). The image angle is the angle the point makes with respect to the x axis in 3D space (viewed top down). So the x coordinate (distance from orign) and the image angle (angle viewed top down) makes up the x and z coordinates in 3D space (or x and y if viewed top down).
That is a polar coordinate.
Read how to convert from polar to cartesian coordinates to get your 3D x and z coordinates.
I'm not great at maths either, here's my go:
3D coords = (2Dx * cos(imageangle), 2Dy, 2Dx * sin(imageangle))
Given the 2D coordinates (x,y) just add the angle A as a third coordinate: (x,y,A). Then you have 3D.
If you want to have the Anotations move on a circle of radius r in 3D you can just calculate:
you can use (r*cos(phi),r*sin(phi),0) which draws a circle in the XY-plane and rotate it with a 3x3 rotation matrix into the orientation you need.
It is not clear from you question around which axis your rotation is taking place. However, my answer holds for a general rotation axis.
First, put your points in a 3D space, lying on the X-Y plane. This means the points have a 0 z-coordinate. Then, apply a 3D rotation of the desired angle around the desired axis - in your example, it is a one degree rotation. You could calculate the transformation matrix yourself (should not be too hard, google "3D rotation matrix" or similar keywords). However, MATLAB makes it easier, using the viewmtx function, which gives you a 4x4 rotational matrix. The extra (fourth) dimension is dependent on the projection you specify (it acts like a scaling coefficient), but in order to make things simple, I will let MATLAB use its default projection - you can read about it in MATLAB documentation.
So, to make the plot clearer, I assume four points which are the vertices of a square lying on the x-y plane (A(1,1), B(1,-1), C(-1,-1), D(1,-1)).
az = 0; % Angle (degrees) of rotation around the z axis, measured from -y axis.
el = 90; % Angle (degrees) of rotation around the y' axis (the ' indicates axes after the first rotation).
x = [1,-1, -1, 1,1]; y = [1, 1, -1, -1,1]; z = [0,0, 0, 0,0]; % A square lying on the X-Y plane.
[m,n] = size(x);
x4d = [x(:),y(:),z(:),ones(m*n,1)]'; % The 4D version of the points.
figure
for el = 90 : -1 :0 % Start from 90 for viewing directly above the X-Y plane.
T = viewmtx(az, el);
x2d = T * x4d; % Rotated version of points.
plot3 (x2d(1,:), x2d(2,:),x2d(3,:),'-*'); % Plot the rotated points in 3D space.
grid
xlim ([-2,2]);
ylim ([-2,2]);
zlim([-2,2]);
pause(0.1)
end
If you can describe your observation of a real physical system (like a binary star system) with a model, you can use particle filters.
Those filters were developed to locate a ship on the sea, when only one observation direction was available. One tracks the ship and estimates where it is and how fast it moves, the longer one follows, the better the estimates become.

algorithm to determine a rectangle from coordinates

I have user input that consists of a drawn rectangle (freestyle). Now this drawn figure isn't perfect, so I would like to redraw the shape for them based on an algorithm.
I have a bunch of coordinates from the user's drawing. I would like to find the greatest (x,y) and the lowest (x,y) coordinates and use the distance between those to determine the diagonal of the rectangle.
But I'm having difficulty determining the greatest (x,y) coordinate and the lowest (x,y) coordinate.
I can't take the greatest y with the greatest x, or the greatest x with the greatest y for example because maybe the user just made an accidental jut out in their line. (Does that make sense?)
Pretend below is a user drawn line.. if i used the greatest y with the greatest x, I would not have the desired coordinate (because it would find the coordinate in the accidental jut out)
----
/ \
----/ \-------- ----- --
--------------/ \---------------/ \------/ \--
Hope you understand what I'm getting at..
I guess another way of putting it is that I would like the coordinate closest to (0,0) and if my canvas was 1000 x 1000, I would like the second coordinate to be closest to (1000,1000). (the two extreme coordinates)
Can anyone help with this algorithm?
Thanks in advance!
Depending on how well you want the algorithm-generated rectangle to fit the user input, you might try the following:
Average all x and y coordinates to give you the center of your rectangle, (Xc, Yc).
Find your highest and lowest x value, subtract the lowest from the highest and divide by two. Repeat for the y values. Let us call these Xs and Ys (s is for 'side').
The important corners (upper left and lower right) would then become (Xc - Xs, Yc - Ys) and (Xc + Xs, Yc + Ys).
Draw lines as appropriate.
Now, this will give you a bounding-box wherein all user given points are contained. If you are looking for more of a best-fit type algorithm, replace the (max - min) / 2 function in step two with an averaging function. A simple one might involve averaging only points to one side of the center point (either above / below or left / right) and using those as offsets from center. Note that this will give you four offsets, only two of which you will use at any given time.
The rough idea presented here can be tuned to taste, depending on what kind of user input you are expecting (e.g. how distorted you expect it might be). Further improvements can be made using linear regression lines, assuming you are able to distinguish sides either via the points themselves or by user input methods (ex. drawing each side of the rectangle with a discrete action rather than all at once).
Hope this quick example will point you in the right direction.
if you want to find the closest point to (0,0), then just find it!
point FindClosestToOrigin(point[] P)
{
point closest = P[0];
foreach(point p in P)
{
if (DistanceOriginS(p) < DistanceOriginS(closest)) closest = p;
}
return closest;
}
float DistanceOriginS(point p)
{
return p.x*p.x + p.y*p.y;
}
you can easily modify the algo to find points closest to the rest of screen edges.
Just do an average over all points and use it as the position of rectangle sides.. of course this assumes you are able to distinguish the four sides of the rectangle otherwise you could try a way to split the coordinates into 4 sides (by checking the horizontal and vertical variation with some threshold) and then compute the average for each side and adjust it to link sides.

Resources