Calculating smallest rotated rectangle that bounds another and maintains aspect - javascript

I need to be able to calculate the size of rectangle 2
To illustrate my problem here is a diagram:
I know the width and height of rectangle 1
I know the aspect ratio of rectangle 2 along with a minimum height and width which will always be larger than rectangle 1
I know the origin of the rotation which is always the centre of rectangle 1
I know the angle of rotation in radians
rectangle 1 must always be fully inside rectangle 2
Given the above variables I need to calculate the smallest size rectangle 2 can be, while maintaining its aspect ratio and rotation origin.
This excellent function calculates the largest possible rectangle within a rotated outer rectangle.
Calculate largest rectangle in a rotated rectangle
I have tried to use it as a base to achieve the behaviour i require but so far with no luck. I'm linking to it in case it is helpful to anyone with greater Math knowledge than I.
Any help would be greatly appreciated.

In the comments you said it's just a trigonometry problem, so I am writing only the formulas.
In your picture, the right bottom triangle will be part of the larger rectangle that you need.
If the smaller angle is x (it's equal to the angle of rotation), and side of inner rectangle is a, then sides of the triangle will be a * cos(x) and a * sin(x). When we move to next side of inner rectangle, the lower b, we will have b * cos(x), b * sin(x).
The picture will be symmetrical, so one side of the larger rectangle will be a * cos(x) + b * sin(x), another will be a * sin(x) + b * cos(x). These are the sizes you need.
You can check with x = 0 (no rotation), x = pi/2 or pi to see what would be the special cases and sizes in those cases.

Related

How to get pixel position

I feel really dumb asking this, but bear with me. I know about the formula to get the pixel position in a linear array:
pos = (y * width + x) * 4
which works fine. jsFiddle. But before the image/table is linearized, same formula doesn't work. You need to use (let's discard the RGBA for simplicity)
pos = (y-1) * width + x
Why is that? I'm probably missing something really simple.
Update: I knew it was something simple. Silly me.
In javascript pixel coordinates start at 0, the same as any coordinate system. The pixel is referenced by its top left corner, thus the first pixel is at (0,0) , then the next going right (1,0) (2,0) and so on. The pixel below at (0,1) we give coordinates relative to the origin (0,0).
We give sizes as counts. When using width and height they are pixel counts and you start at one when you count. So the 100th pixel is on row 99. Just the same as this is the 21th century but we are in the year 2015.
So no need to subtract 1 from the pixel coordinates.

Drawing a point to point ellipse to allow painting in GUI

I'm implementing some basic annotation draw features, such as arrows. Now I'm a little bit stuck with ellipse.
The methods to draw an ellipse usually address using it's two diameters and eventually a rotation:
However I want to display the ellipse between the point user clicked and the one he's hovering, therefore I need a function that calculates diameters and rotation based on two points:
How would I do that? Can it be achieved with sufficient performance (as it renders during mouse-hovering)?
the steps you shoul follow:
get the angle of the line (from this post: get angle of a line from horizon)
rotate the canvas or at least the part you currently drawing (live demo here: http://www.html5canvastutorials.com/advanced/html5-canvas-transform-rotate-tutorial)
draw an ellipse in canvas (http://www.scienceprimer.com/draw-oval-html5-canvas)
the resulted ellipse will be transformed as described
It can be done in the same way that it is normally done, just using different math to calculate the shape. Without writing the entire code for you, you can start by having an event trigger when the user clicks the mouse button down. The function will copy the users x and y position based on the screen. Then there is a second function which will handle mouse movement. This function will keep track of the x and y coords of the mouse while it is in motion. The final function will be a mouse up event, when a user lifts their finger from the mouse button (assuming this is when the event should be finished). Using the initial and final position of the x and y coordinates, you can calculate the length of the line the user created. That line is the long diameter of the ellipse. Half this number for the large radius. Then use whatever ratio you are using to calculate the smaller radius from the larger one. Then create an ellipse based on these numbers.
For the math: Suppose your first point is x1,y1 and the end point is x2,y2
I'm also assuming that we have a line going from bottom-left to top-right
Distance between two points = sqrt((x2-x1)^2 + (y2-y1)^2) ---> (we will call this d1)
half of this is the length of the large radius ---> (we will call this r1)
Midpoint formula = ((x1+x2)/2 , (y1+y2)/2) ---> axis of rotation (we will call it (m1, m2))
distance from midpoint to end is just the radius
radius is now the hypotenuse of constructed plane, y2-m2 is height of right triangle.
Find the angles between midpoint and one end of larger radius - sin((y2-m2)/r1).
Angle of smaller radius is this angle + pi/4 radians.
calculate length of smaller radius based on ratio.

How can I calculate the size of an outer rectangle when it is rotated and must encompass an inner rectangle totally

I have found many answered questions explaining how to calculate the bounding box of a rotated rectangle, however what I need to do is almost the reverse.
The red rectangle A is described as:
var box = {
x : 0,
y : 0,
w : 100,
h : 200
};
And the dimensions of the blue rectangle B are exactly the same when it is not rotated.
Given that rectangle B is rotated around its center point and that it's angle is provided in radians, how can I calculate the minimum size rectangle B can be when rectangle A must always fit inside it while maintaining its original aspect ratio (as previously mentioned, the same as rectangle A)
If you label the sides of the rectangles and draw in an extra line (green in the diagram), you can see what you need to calculate:
So c = a * cos(θ) + b * sin(θ)
and d=b*c/a

Canvas - Reset pixels around

I want to reset pixels to transparent like this:
Consider white as transparent. How to calculate those pixels.
If reset 50% it would be half image, if 100% it would be entire image hidden. On the picture is 35%.
Circle is just for show. It can be any square image.
For each point on the canvas, calculate the angle to your central point. In basic terms:
angle = Math.atan2(y - cy, x - cx);
Where (cx,cy) are the coordinates of your central point, and (x,y) the coordinates of the current pixel being examined.
If this angle is within the range you want to nuke, clear that pixel.
To make this simpler, add Math.PI*3/2, then do % Math.PI*2, and finally multiply by 100/(Math.PI*2) to get a number in the range 0 (up) counter-clockwise to 100.
Now it's a simple case of seeing if that number is less than your target percentage, and if so clear it.

How to compute rotation/scale pivot coordinates for SVG transformations (I'm using Raphael.js)?

I'm having serious trouble understanding how to compute the coordinates of rotation/scale pivots (e.g. rotation point) for SVG transformations, using Raphael.js. In short, if you apply a transformation such as image.transform("S1.5R45"), the transformations are applied in relation to the default rotation & scale pivot, which I'm not sure how to calculate.
To exemplify, I've put together a fiddle (jsfiddle.net/GVEqf/), where the aim is to have exactly the same output in both the viewports, for a couple of transformations on an image object. In the first viewport, I don't specify the rotation point, but in the second one I do. However, I can't get the same results. What I need is to input the rotation coordinates for the second viewport, so that the output is identical with the first case.
Please help.
When not specified the pivot is the center of the element.
Here you have to take care of the position you have applied to the images and the scaling that will be done. Since in this case your scaling is relative to the top left corner of the image, we can just multiply the center coordinate by it.
// Compute rotation pivot coordinates
var scaling = 1.5;
rx = (x + (img_width / 2)) * scaling;
ry = (y + (img_height / 2)) * scaling;
// Apply transformations
image1.transform("S1.5,1.5,0,0R45");
image2.transform("S1.5,1.5,0,0R45,"+rx+","+ry);
http://jsfiddle.net/TYCJ7/

Categories