let me begin by stating that's i'm dreadful at math.
i'm attempting to reposition and rotate a rectangle. however, i need to rotate the rectangle from a point that is not 0,0 but according to how far its coordinates has shifted. i'm sure that doesn't make much sense, so i've made some sketches to help explain what i need.
the image above shows 3 stages of the red rectangle moving from 0% to 100%. the red rectangle's X and Y coordinates (top left of the red rectangle) only moves a percentage of the blue rectangle's height.
the red rectangle can rotate. focusing only on the middle example ("Distance -50%") from above, where the red rectangle is repositioned at -50 of the blue rectangle's height, its new angle in the above image is now -45º. it has been rotated from its 0, 0 point.
now, my problem is that i want its rotational point to reflect its position.
the red and blue rectangles are the same size, but have opposite widths and heights. since the red rectangle's 0,0 coordinates are now -50% of the blue rectangle's height, and since they have opposite widths and heights, i want the rotational point to be 50% of the red rectangle's width (or 50% of the blue rectangle's height, which is the same thing).
rather than specifically telling the red rectangle to rotate at 50% of its width, in order to do what i want, i need to emulate doing so by using a formula that will position the red rectangle's X and Y coordinates so that its rotational point reflects its position.
Here's an illustrated solution to your problem:
I don't exactly understand what you need, but it seems that a procedure to rotate a rectangle around an arbitrary point may help.
Suppose we want to rotate a point (x,y) d radians around the origin (0,0). The formula for the location of the rotated point is:
x' = x*cos(d) - y*sin(d)
y' = x*sin(d) + y*cos(d)
Now we don't want to rotate around the origin, but around a given point (a,b). What we do is first move the origin to (a,b), then apply the rotation formula above, and then move the origin back to (0,0).
x' = (x-a)*cos(d) - (y-b)*sin(d) + a
y' = (x-a)*sin(d) + (y-b)*cos(d) + b
This is your formula for rotating a point (x,y) d radians around the point (a,b).
For your problem (a,b) would be the point halfway on the right side of the blue rectangle, and (x,y) would be every corner of the red rectangle. The formula gives (x',y') for the coordinates of the corners of rotated red rectangle.
It's quite simple really.
1. Let's settle on your point you want to rotate the rectangle about, i.e. the point of rotation (RP) which does not move when you swivel your rectangle around. Let's assume that the point is represented by the diamond in the figure below.
2. Translate the 4 points so that RP is at (0,0). Suppose the coordinates of that point is (RPx,RPy), therefore subtract all 4 corners of the rectangle by those coordinates.
3. Rotate the points with a rotation matrix (which rotates a point anticlockwise around the origin through some angle which is now the point of rotation thanks to the previous translation):
The following figure shows the rectangle rotated by 45° anticlockwise.
4. Translate the rectangle back (by adding RP to all 4 points):
I assume this is what you want :)
It seems like you could avoid a more complex rotation by more crafty positioning initially? For example, in the last example, position the red box at "-25% Blue Height" and "-25% Red Height" -- if I follow your referencing scheme -- then perform the rotation you want.
If you know the origin O and a point P on the side of rotated rectangle, you can calculate the vector between the two:
(source: equationsheet.com)
You can get the angle between the vector and the x-axis by taking the dot product with this vector:
(source: equationsheet.com)
Given this, you can transform any point on the rectangle by multiplying it by a rotation matrix:
(source: equationsheet.com)
Related
How can I get a 3x3 matrix representing all the transformations (scale,rotation) to apply to an image drawn on a canvas given 4 points x1,y1...x4,y4 representing the ROI(sub-image) that I want to zoom and rotate on?
The first coordinates x1,y1 should be transformed to the top left corner(0,0) of the canvas and x2,y2 to the bottom right corner of the canvas(canvas.width, canvas.height).
Thank you very much for your help!
I'm trying to find the angle it would take for me to rotate a polygon so that a specific side is completely horizontal and on the bottom.
For example, a shape like this:
Needs to be rotated so the side with the red square on it is on the bottom and completely horizontal, like this:
So far I've tried several approaches but all end up having strange edge cases where the angle is incorrect.
If you have coordinates of two vertices of this edge (x1,y1) and (x2,y2) in counterclockwise order, then rotation angle is
RotAngle = atan2 (y2-y1, x2-x1)
So let's say I have 2 objects. One with the sprite of a circle, other with the sprite of triangle.
My triangle object is set to the position of mouse in every step of the game, while circle is either standing in place or just moving in its own way, whatever.
What I want to do is to have the TRIANGLE move around the circle, but not on it's own, rather on the way your cursor is positioned.
So basically, calculate degree between circle's center and triangle's center. Whenever they are far from each other I just set triangle position to mouse position, BUT when you hover your mouse too close (past some X distance) you can't get any closer (the TRIANGLE is then positioned at maximum that X distance in the direction from circle center to mouse point)
I'll add a picture and hopefully you can get what I mean.
https://dl.dropboxusercontent.com/u/23334107/help2.png
Steps:
1. Calculate the distance between the cursor and the center of the circle. If it is more than the 'limit' then set the triangle's position to the cursor's position and skip to step 4.
2. Obtain the angle formed between the center of the circle and the cursor.
3. Calculate the new Cartesian coordinates (x, y) of the triangle based of off the polar coordinates we have now (angle and radius). The radius will be set to the limit of the circle before we calculate x and y, because we want the triangle to be prevented from entering this limit.
4. Rotate the image of the triangle to 1.5708-angle where angle was found in step 2. (1.5708, or pi/2, in radians is equivalent to 90°)
Details:
1. The distance between two points (x1, y1) and (x2, y2) is sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
2. The angle (in radians) can be calculated with
double angle = Math.atan2(circleY-cursorY, cursorX-circleX);
The seemingly mistaken difference in order of circleY-cursorY and cursorX-circleX is an artefact of the coordinate system in most programming languages. (The y coordinate increases downwards instead of upwards, as it does in mathematics, while the x coordinate increases in concord with math - to the right.)
3. To convert polar coordinates to Cartesian coordinates use these conversions:
triangle.setX( cos(angle)*limit );
triangle.setY( sin(angle)*limit );
where limit is the distance you want the triangle to remain from the circle.
4. In order to get your triangle to 'face' the circle (as you illustrated), you have to rotate it using the libgdx Sprite function setRotation. It will rotate around the point set with setOrigin.
Now, you have to rotate by 1.5708-angle – this is because of further differences between angles in mathematics and angles in programming! The atan2 function returns the angle as measured mathematically, with 0° at three o'clock and increasing counterclockwise. The setRotation function (as far as I can tell) has 0° at twelve o'clock and increases clockwise. Also, we have to convert from radians to degrees. In short, this should work, but I haven't tested it:
triangle.setRotation(Math.toDegrees(1.4708-angle));
Hope this helps!
I have a rectangle that is W x H.
Within that rectangle is another rectangle that is rotated by ϴ degrees which is always between -45 and 45 degrees, and shares the same center as the outer rectangle. I need to find w and h such that the area of the inner rectangle is maximized.
Here's a (ghetto) image to illustrate a bit. Though, the corners of the rectangles should probably be touching, I assume?
Here is the prototype of the function I'm looking to write:
SizeD GetMaxRectangleSize(double outerWidth, double outerHeight, float angle)
SizeD is just a struct that has a width and height in doubles.
Thanks to the comments for steering me in the right direction!
My solution, though perhaps not mathematically optimal, was to assume that if all four corners of the inner rectangle fall on the outer rectangle then area will be maximized.
Therefore:
H = wSin(ϴ) + hCos(ϴ)
W = wCos(ϴ) + hSin(ϴ)
Solving for w and h and substituting gives:
h = (HCos(ϴ) - WSin(ϴ))/(cos(ϴ)^2 - sin(ϴ)^2)
w = (WCos(ϴ) - HSin(ϴ))/(cos(ϴ)^2 - sin(ϴ)^2)
Which happens to work for ϴ = [0,45), and (-45,0] should act the same.
The tricky part of this question isn't how to calculate the area of an interior rectangle, but which of all the possible interior rectangles has maximum area?
To start with, observe that the box in your image is the same area regardless of how it is slid around horizontally, and if it is slid to the rightmost wall, it allows for an easy parameterization of the problem as follows:
I find it a bit easier to think of this problem, with the fixed box rotated by the offset angle so that the interior box lines up in a standard orientation. Here's a figure (I've changed theta to beta just because I can type it easily on a mac, and also left off the left most wall for reasons that will be clear):
So think of this constructed as follows: Pick a point on the right side of the exterior rectangle (shown here by a small circle), note the distance a from this point to the corner, and construct the largest possible interior with a corner at this point (by extending vertical and horizontal lines to the exterior rectangle). Clearly, then, the largest possible rectangle is one of the rectangles derived from the different values for a, and a is a good parameter for this problem.
So given that, then the area of the interior rectangle is:
A = (a * (H-a))/(cosß * sinß)
or, A = c * a * (H-a)
where I've folded the constant trig terms into the constant c. We need to maximize this, and to do that the derivative is useful:
dA/da = c * (H - 2a)
That is, starting at a=0 (ie, the circle in the figure is in the lower corner of the exterior rectangle, resulting in a tall and super skin interior rectangle), then the area of the interior rectangle increases monotonically until a=H/2, and then the area starts to decrease again.
That is, there are two cases:
1) If, as a increase from 0 to H/2, the far interior corner hits the opposite wall of the exterior, then the largest possible rectangle is when this contact occurs (and you know it's the largest due to the monotonic increase -- ie, the positive value of the derivative). This is your guess at the solution.
2) If the far corner never touches a wall, then the largest interior rectangle will be at a=H/2.
I haven't explicitly solved here for the area of the interior rectangle for each case, since that's a much easier problem than the proof, and anyone who could follow the proof, I assume could easily calculate the areas (and it does take a long time to write these things up).
If I have a given rectangle, with the width w, height h and angle r
How large does another rectangle which contains all points of the rotated rectangle need to be?
I would need this to perform fast bounding box checks for a 2D physics engine I am making
this may be what you need:
Calculate Bounding box coordinates from a rotated rectangle, answered by someone named markus.
You usually should consider rotating rectangles in a collision detection engine, since it will be quite straightforward to implement (I mean considering the rotated rectangle as it is).
In any case if you really want to simplify to have a coarse-level of collision detection the best thing is to embed the rectangle inside a circle, because it's really simple (centered over rectangle center and with a radius of the semi-diagonal of the rectangle) and compared to using a box it can be quite accurate for a coarse detection. Actually you can have an angle threshold to decide if it's better to use a circle or to consider the original rectangle (most degenerating cases are when angle is near to k*PI with k = 0,1,2,3
If you really really want to consider the rotated rectangle you can calculate it easily by choosing the topmost vertex of your rectangle (xT, yT) and the leftmost (xL, yL) (after the rotation of course) to obtain the topleft point that will be (xL, yT). Then you do the same thing for the bottomright corner taking (xR, yB) from the rightmost and lowest point of your rectangle and you have it. It will be the rectangle included in (xL, yY) (xR, yB).