I have two rectangles: red and green. For each of them, I have the following information:
Center point (x and y coords).
Rotation angle
Width and height
The rectangles will always be moving in positive coordinates. Edit: No coordinate can ever be negative: the rectangles are always located in positive coordinates. Therefore, the center will never be (0,0).
Problem
I have an starting position. To simplify the example, let's say that my red and green rectangles are located as follows:
Now, I rotate the red rectangle using an angle phi which goes between 0º and 90º. However, the green rectangles needs to rotate and keep its position regarding the red rectangle. The green rectangle is not only rotating but also moving.
Let see an image (please excuse the sketch-quality):
My Question:
How can I obtain the new center coords for the green rectangle?
Rotation is about some point (rx, ry).
Edit: As comment says, rotation center (rx, ry) is red center. Formula remains the same.
If green center was at (gx, gy), then after rotation it has coordinates
gx' = rx + (gx - rx) * Cos(Phi) - (gy - ry) * Sin(Phi)
gy' = ry + (gx - rx) * Sin(Phi) + (gy - ry) * Cos(Phi)
Related
I am currently working on raytracing. I have problem with view Ray collisions. I cant figure out how to get intersection point of ray and plane, to be more precise, my problem is not figure out intersection point of ray vs plane, problem is to convert this coordinate into uv coordinate(this rectangle can be rotated anyhow in world) for texture mapping. I know One point on this rectangle, its normal and bounds.
We have 4 vertices of a rectangle lying on a sphere:
A - top left
B - top right
C - bottom right
D - bottom left
Center of the sphere:
O
And intersection point on the sphere inside rectangle ABCD:
I
The idea is to identify all sides of the triangle AID, because it will allow us to know the coordinates of the point I on the plane. So if we move the rectangle on the plane with A(0, rect.height) and D(0, 0) then point I could be found by solving the following system of equations:
x^2+y^2=DI^2 - circle equation with center in point D and radius DI
x^2+(y-rect.height)^2=AI^2 - circle equation with center in point A and radius AI
from which it follows that:
y = (DI^2-AI^2+rect.height) / (2*rect.height)
and x could have 2 values (positive and negative), however we are interested only in positive value, because only it will be inside the rect.
x = sqrt(DI^2-(DI^2-AI^2+rect.height)/(2*rect.height))
Then UV could be calculated the following way uv(x/rect.width, y/rect.height)
However length of AI and DI still not known, but could be calculated using formula of Great-circle distance
AI = (Radius of the Sphere) * (Angular orthodromy length must be in radians)
Radius of the Sphere = sqrt((O.x - A.x)^2+(O.y - A.y)^2+(O.z - A.z)^2)
Angular orthodromy length = arccos(sin(a1)*sin(a2)+cos(a1)*cos(a2)*cos(b2-b1))
a1 is angle AOA1, where A1(A.x, O.y, A.z)
b1 is angle O1OA1, where O1(O.x, O.y, A.z)
a2 is angle IOI1, where I1(I1.x, O.y, I.z)
b2 is angle O2OI1, where O2(O.x, O.y, I.z)
I am using camera to trace one black marker on blue ball as shown in image below.
I can detect marker position on top of ball image reliably but would need to know
how to calculate ball rotation angles based on marker location.
When marker is in the middle as shown both angles should be 0 degrees. When marker is only half visible at left edge as shown horizontal angle should be -90 degrees. I understand calculating angles from 2D-image is non-linear, near the edge similar movement in pixels means bigger change in rotation than in the middle but I just can't come up with the formula.
Rotation about vertical axis:
Phi = ArcSin((Marker.X - Center.X) / Radius)
In general, if you grab initial point with 2D coordinates (x0, y0) at the front surface of ball manipulator with radius 1 and drag it ti end point (x1,y1), then you rotate direction vector
d0 = (x0, y0, Sqrt(1 - x0^2 - y0^2))
to
d1 = (x1, y1, Sqrt(1 - x1^2 - y1^2))
What to do with these vectors? I depends on what approach are you going to use for rotation
I have a rectangle that I need to 'bend' into a ring, i.e. the top edge of the rectangle must map to the outer circle of the ring, the bottom to the inner circle, and the sides of the rectangle should join.
Here's an extremely crude sketch of the rectangle and ring:
If it is helpful or necessary, I can deal with the rectangle as a collection of horizontal lines, and the ring as a collection of circles.
The rectangle has a horizontal gradient from a to b that should map so that the gradient progresses on a circular direction.
I can see that this is a non-linear transform, but am lost as to where to look to learn the techniques to solve this problem. Could anyone with suitable experience in CG point me to anything like the right text, the right name of algorithm or the right graphics library to make my ring?
Try just using polar coordinates. If you map x as r and y as θ (normalising as θ runs from 0 to 2π), then adding some offset to r will vary the radius of the ring and adding an offset to θ will rotate it around the circle.
r = fx + a
g = (max_y - min_y)/(2*pi)
theta = gy + b
where a and b are these offsets, f scales the width of the ring and g normalizes the length of the rectangle to 2π. The transform back from these polar coordinates to cartesian (i.e. the screen) is just:
x' = r cos(theta)
y' = r sin(theta)
You then have 3 coordinate systems: (x,y) for the original rectangle, (r,θ) for the polar coordinates of the ring and (x',y') for the screen coordinates.
I have a square (100px x 100px) with origin at 0,0 (upper left).
When I move the mouse, lets say 10 pixel x and y, I move the origin according to displacement and then origin becomes 10,10, simple. Works fine!
When I rotate the square, my rotation function rotates it fine, but then, after the square is rotated, lets say 10 degrees, the origin point should be move accordingly to the rotation. And now, I have no idea of the formula I have to apply to make it append!
I wikipedia, but I tink it's too complicated.
http://en.wikipedia.org/wiki/Angular_displacement
and
http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine.2C_and_tangent
Example: After a 90 deg rotation to the left, the origin is now at : lower left, now when I move the mouse to to right, the picture go UP!!!!
If I understand your problem correctly, you are applying an offset to the rectangle points based on your mouse position, then rotating the resulting points about the origin.
Instead, try applying your mouse offset after you do your rotation, not before.
Suppose you have a figure and you want to rotate it by angle alpha and translate it so that point (cx, cy) of the figure gets to point (sx, sy) after the transformation.
The transformation is
transformed_x = x*cos(alpha) - y*sin(alpha) + offset_x
transformed_y = x*sin(alpha) + y*cos(alpha) + offset_y
to compute desired offset_x and offset_y values you just need to put your requirement about (cx, cy) and (sx, sy) into the above equations:
sx = cx*cos(alpha) - cy*sin(alpha) + offset_x
sy = cx*sin(alpha) + cy*cos(alpha) + offset_y
and now you can easily extract the offset values from that:
offset_x = sx - cx*cos(alpha) + cy*sin(alpha)
offset_y = sy - cx*sin(alpha) - cy*cos(alpha)
To set up canvas transform for it you need just to call
context.translate(sx - cx*Math.cos(alpha) + cy*Math.sin(alpha),
sy - cx*Math.sin(alpha) - cy*Math.cos(alpha));
context.rotate(alpha);
You can see a little demo of this formula following this link.
I'm writing a script where icons rotate around a given pivot (or origin). I've been able to make this work for rotating the icons around an ellipse but I also want to have them move around the perimeter of a rectangle of a certain width, height and origin.
I'm doing it this way because my current code stores all the coords in an array with each angle integer as the key, and reusing this code would be much easier to work with.
If someone could give me an example of a 100x150 rectangle, that would be great.
EDIT: to clarify, by rotating around I mean moving around the perimeter (or orbiting) of a shape.
You know the size of the rectangle and you need to split up the whole angle interval into four different, so you know if a ray from the center of the rectangle intersects right, top, left or bottom of the rectangle.
If the angle is: -atan(d/w) < alfa < atan(d/w) the ray intersects the right side of the rectangle. Then since you know that the x-displacement from the center of the rectangle to the right side is d/2, the displacement dy divided by d/2 is tan(alfa), so
dy = d/2 * tan(alfa)
You would handle this similarily with the other three angle intervals.
Ok, here goes. You have a rect with width w and depth d. In the middle you have the center point, cp. I assume you want to calculate P, for different values of the angle alfa.
I divided the rectangle in four different areas, or angle intervals (1 to 4). The interval I mentioned above is the first one to the right. I hope this makes sense to you.
First you need to calculate the angle intervals, these are determined completely by w and d. Depending on what value alfa has, calculate P accordingly, i.e. if the "ray" from CP to P intersects the upper, lower, right or left sides of the rectangle.
Cheers
This was made for and verified to work on the Pebble smartwatch, but modified to be pseudocode:
struct GPoint {
int x;
int y;
}
// Return point on rectangle edge. Rectangle is centered on (0,0) and has a width of w and height of h
GPoint getPointOnRect(int angle, int w, int h) {
var sine = sin(angle), cosine = cos(angle); // Calculate once and store, to make quicker and cleaner
var dy = sin>0 ? h/2 : h/-2; // Distance to top or bottom edge (from center)
var dx = cos>0 ? w/2 : w/-2; // Distance to left or right edge (from center)
if(abs(dx*sine) < abs(dy*cosine)) { // if (distance to vertical line) < (distance to horizontal line)
dy = (dx * sine) / cosine; // calculate distance to vertical line
} else { // else: (distance to top or bottom edge) < (distance to left or right edge)
dx = (dy * cosine) / sine; // move to top or bottom line
}
return GPoint(dx, dy); // Return point on rectangle edge
}
Use:
rectangle_width = 100;
rectangle_height = 150;
rectangle_center_x = 300;
rectangle_center_y = 300;
draw_rect(rectangle_center_x - (rectangle_width/2), rectangle_center_y - (rectangle_center_h/2), rectangle_width, rectangle_height);
GPoint point = getPointOnRect(angle, rectangle_width, rectangle_height);
point.x += rectangle_center_x;
point.y += rectangle_center_y;
draw_line(rectangle_center_x, rectangle_center_y, point.x, point.y);
One simple way to do this using an angle as a parameter is to simply clip the X and Y values using the bounds of the rectangle. In other words, calculate position as though the icon will rotate around a circular or elliptical path, then apply this:
(Assuming axis-aligned rectangle centered at (0,0), with X-axis length of XAxis and Y-axis length of YAxis):
if (X > XAxis/2)
X = XAxis/2;
if (X < 0 - XAxis/2)
X = 0 - XAxis/2;
if (Y > YAxis/2)
Y = YAxis/2;
if (Y < 0 - YAxis/2)
Y = 0 - YAxis/2;
The problem with this approach is that the angle will not be entirely accurate and the speed along the perimeter of the rectangle will not be constant. Modelling an ellipse that osculates the rectangle at its corners can minimize the effect, but if you are looking for a smooth, constant-speed "orbit," this method will not be adequate.
If think you mean rotate like the earth rotates around the sun (not the self-rotation... so your question is about how to slide along the edges of a rectangle?)
If so, you can give this a try:
# pseudo coode
for i = 0 to 499
if i < 100: x++
else if i < 250: y--
else if i < 350: x--
else y++
drawTheIcon(x, y)
Update: (please see comment below)
to use an angle, one line will be
y / x = tan(th) # th is the angle
the other lines are simple since they are just horizontal or vertical. so for example, it is x = 50 and you can put that into the line above to get the y. do that for the intersection of the horizontal line and vertical line (for example, angle is 60 degree and it shoot "NorthEast"... now you have two points. Then the point that is closest to the origin is the one that hits the rectangle first).
Use a 2D transformation matrix. Many languages (e.g. Java) support this natively (look up AffineTransformation); otherwise, write out a routine to do rotation yourself, once, debug it well, and use it forever. I must have five of them written in different languages.
Once you can do the rotation simply, find the location on the rectangle by doing line-line intersection. Find the center of the orbited icon by intersecting two lines:
A ray from your center of rotation at the angle you desire
One of the four sides, bounded by what angle you want (the four quadrants).
Draw yourself a sketch on a piece of paper with a rectangle and a centre of rotation. First translate the rectangle to centre at the origin of your coordinate system (remember the translation parameters, you'll need to reverse the translation later). Rotate the rectangle so that its sides are parallel to the coordinate axes (same reason).
Now you have a triangle with known angle at the origin, the opposite side is of known length (half of the length of one side of the rectangle), and you can now:
-- solve the triangle
-- undo the rotation
-- undo the translation