How can I rotate a rectangle and position using MiniMagick? - ruby

I'm trying to create an overlay using mini_magick (Ruby wrapper for imagemagick) similar to the example below:
I know how to draw a rectangle, and I know how to rotate, but I can't wrap my head around the coordinate system once the rotation has been applied.
So I wrote the following:
x = original_icon.width / 2
y = 0 # or should it be -10 so it's off the canvas?
width = 100
height = 20
result = original_icon.combine_options do |c|
c.fill('#FF0000')
c.draw "rotate -45 rectangle #{x},#{y},#{width},#{height}"
end
However, things get odd fast after the rotate -45. It seems positioning has completely gone out the window.
Is there another way to achieve this?

Related

Turn a 2D Image into a rotating 3D image on Matlab

I would like to know how to rotate a 2D image along its Z-axis using Matlab R2016b and to obtain an image after performing this procedure.
For example, let's take this 2D image:
Now, I rotate it of 45° roughly:
And now, of 90°:
Do you know if it is possible to perform the same operation in Matlab R2016b, please ?
Thank you very much for your help
Images Source: https://www.youtube.com/watch?v=m89mVexWQZ4
Yes it's possible. The easiest thing to do would be to map the image on the y = 0 plane in 3D, then rotate the camera to the desired azimuth or the angle with respect to the y axis. Once you do that, you can use the getframe / cdata idiom to actually capture the actual image data in a variable itself. The reason why you do this with respect to the y plane is because the method that I will be using to present the image is through the surf command that plots surface plots in 3D, but the y axis here is the axis that goes into and out of the screen. The x axis is the horizontal and the z axis would be the vertical when displaying data.
First read in your image using something like imread, then you need to define the 4 corners of the image that map to the 3D plane and then rotate the camera. You can use the view function to help you rotate the camera by adjusting the azimuthal angle (first parameter) and leaving the elevation angle as 0.
Something like this could work. I'll be using the peppers image that is part of the image processing toolbox:
im = imread('peppers.png'); % Read in the image
ang = 45; % Rotate clockwise by 45 degrees
% Define 4 corners of the image
X = [-0.5 0.5; -0.5 0.5];
Y = [0 0; 0 0];
Z = [0.5 0.5; -0.5 -0.5];
% Place the image on the y = 0 plane
% Turn off the axis and rotate the camera
figure;
surf(X, Y, Z, 'CData', im, 'FaceColor', 'texturemap');
axis('off');
view(ang, 0);
% Get the image data after rotation
h = getframe;
rot_im = h.cdata;
rot_im contains the rotated image. To appreciate the rotation of the image, we can loop through angles from 0 to 360 in real time. At each angle, we can use view to dynamically rotate the camera and use drawnow to update the figure. I've also updated the title of the figure to show you what the angle is at each update. The code for that is below as well as the output saved as an animated GIF:
for ang = 0 : 360
view(ang, 0);
pause(0.01);
drawnow;
title(sprintf('Angle: %d degrees', ang));
end

Rotating rectangles so they maintain their relative position to the canvas

I have a background pixmap, basically a canvas, which I draw a bunch of
rectangles on and I need to rotate the pixmap and rectangles.
However rotating the background pixmap and the rectangles needs to be done
seperately, that is the rotation of the background pixmap gets handled via an
external library routine and I need to rotate and redraw the rectangles
on top manually.
So far I am actually able to rotate the rectangles by applying a
transformation matrix I got from Wikipedia
to each vertex. What I don't know is how to translate them that each rectangle retains its position relative to the canvas.
Here is a quick drawing for illustration of what I want to achieve:
I need to do this with C and Xlib, but I'm not necessarily looking for code but would appreciate some general hints/algorithms.
To get the translated position for the child object, you need to rotate the relative position vector for the child object, and then add it to the origin:
Pseudocode would be:
public static Vector2 OffsetByRotation(Vector2 childPos, Vector2 parentPos, float angle)
{
var relativeVector = childPos - parentPos;
relativeVector = Rotate(relativeVector, angle);
return parentPos + relativeVector;
}
Note that your example image not only rotates the parent object, but also translates it: your left image is rotated around (0, 300), but this point is then translated to (0, 0).
The requested transformation is
X' = 300 - Y
Y' = X

How to stick object inside fov

I'm trying to figure out how to position an object inside the edge of the camera's fov if it goes outside of it.
I've looked at this: Three.js - Width of view
But if I plug in the values, it returns 5.12 if the screen width is 512, and 3.12 for height if the screen height is 320.
I have the camera positioned -150 on the z axis, and the objects are located at 0 on the z axis.
I was hoping it would tell me how much x and y distance there is visible in the fov where z axis is 0 if camera is looking along the z axis. That way I could position objects if they go outside the limits.
Anyone know how to get this data?
Okay, I found the answer. Had to use some trigonometry.
h = tan(fov/2)*dist
dist is the distance to the object from the camera. h is half of the screen space in y axis.
to get x axis multiply by (screenwidth/screenheight)

Love2d Rotating an image

I would like to rotate an image in Love2D.
I have found a documentation on love2d.org: https://love2d.org/wiki/love.graphics.rotate
But I can't seem to get it to work when I try to load an image.
Heres my code:
local angle = 0
function love.load()
g1 = love.graphics.newImage("1.png")
end
function love.draw()
width = 100
height = 100
love.graphics.translate(width/2, height/2)
love.graphics.rotate(angle)
love.graphics.translate(-width/2, -height/2)
love.graphics.draw(g1, width, height)
end
function love.update(dt)
love.timer.sleep(10)
angle = angle + dt * math.pi/2
angle = angle % (2*math.pi)
end
Could anyone show me an simple example of rotating an image in love2d?
https://love2d.org/wiki/love.graphics.draw
You may be better off using the fourth argument, shown as 'r' to rotate images, such as:
love.graphics.draw(image, x, y, math.pi/4)
It's not worth the trouble of using the translate functions for a single draw, and keeping those for when you're batching many draws at once.
Your code worked perfectly for me, aside from a small unrelated issue (love.timer.sleep uses seconds in LÖVE 0.8.0).
We will be able to help you better, and perhaps reproduce your error, if you provide us with more information.
When you say
I can't seem to get it to work when I try to load an image
..what is the result?
Is the image a white box? Does the application crash? Is there nothing on the screen?
All of these imply a image loading issue, rather than a rotation issue. Although, it could be the case that the image is rotating off of the screen.
If you continue to use translate, rotate, and scale (which is usually a good idea), I recommend you take a look at the push and pop functions.
They allow you to 'stack' transformations so you can render sub elements.
Example uses are rendering a GUI (each child pushes its translation and then renders the children) and drawing sprites on a scrolling map (the camera translates the entire map and then does for entity in entities do push() entity:draw() pop() end. Each entity can translate and rotate in local coordinates (0,0 = centre of sprite)).
love.graphics.draw( drawable, x, y, r, sx, sy, ox, oy, kx, ky )
the R is the rotation.. why don't you just set it to a variable and change it as you please? ... I'm new to programming so I may be wrong but this is how I would do it.
Example of rotating at center of image using LOVE 11.3 (Mysterious Mysteries):
function love.draw()
love.graphics.draw(img, 400,300, wheel.r, wheel.sx, wheel.sy, wheel.w / 2, wheel.h / 2)
end
function love.update(dt)
wheel.r = wheel.r + dt
end
function love.load()
wheel = {x = 0, y = 0, w = 0, h = 0, sx = 0.5, sy = 0.5, r = 0, image = "wheel.png"}
img = love.graphics.newImage(wheel.image)
wheel.w = img:getWidth()
wheel.h = img:getHeight()
end
Normaly the axis for rotating is the upper left corner. To center the axis to the middle of an image you have to use the parameters after the r parameter to half of width and half of height of the image.

Rotating an image with the mouse

I am writing a drawing program, Whyteboard -- http://code.google.com/p/whyteboard/
I have implemented image rotating functionality, except that its behaviour is a little odd. I can't figure out the proper logic to make rotating the image in relation to the mouse position
My code is something similar to this:
(these are called from a mouse event handler)
def resize(self, x, y, direction=None):
"""Rotate the image"""
self.angle += 1
if self.angle > 360:
self.angle = 0
self.rotate()
def rotate(self, angle=None):
"""Rotate the image (in radians), turn it back into a bitmap"""
rad = (2 * math.pi * self.angle) / 360
if angle:
rad = (2 * math.pi * angle) / 360
img = self.img.Rotate(rad, (0, 0))
So, basically the angle to rotate the image keeps getting increased when the user moves the mouse. However, this sometimes means you have to "circle" the mouse many times to rotate an image 90 degrees, let alone 360.
But, I need it similar to other programs - how the image is rotated in relation to your mouse's position to the image.
This is the bit I'm having trouble with. I've left the question language-independent, although using Python and wxPython it could be applicable to any language
I'm assuming resize() is called for every mouse movement update. Your problem seems to be the self.angle += 1, which makes you update your angle by 1 degree on each mouse event.
A solution to your problem would be: pick the point on the image where the rotation will be centered (on this case, it's your (0,0) point on self.img.Rotate(), but usually it is the center of the image). The rotation angle should be the angle formed by the line that goes from this point to the mouse cursor minus the angle formed by the line that goes from this point to the mouse position when the user clicked.
To calculate the angle between two points, use math.atan2(y2-y1, x2-x1) which will give you the angle in radians. (you may have to change the order of the subtractions depending on your mouse position axis).
fserb's solution is the way I would go about the rotation too, but something additional to consider is your use of:
img = self.img.Rotate(rad, (0, 0))
If you are performing a bitmap image rotation in response to every mouse drag event, you are going to get a lot of data loss from the combined effect of all the interpolation required for the rotation. For example, rotating by 1 degree 360 times will give you a much blurrier image than the original.
Try having a rotation system something like this:
display_img = self.img.Rotate(rad, pos)
then use the display_img image while you are in rotation mode. When you end rotation mode (onMouseUp maybe), img = display_img.
This type of strategy is good whenever you have a lossy operation with a user preview.
Here's the solution in the end,
def rotate(self, position, origin):
""" position: mouse x/y position, origin: x/y to rotate around"""
origin_angle = self.find_angle(origin, self.center)
mouse_angle = self.find_angle(position, self.center)
angle = mouse_angle - origin_angle
# do the rotation here
def find_angle(self, a, b):
try:
answer = math.atan2((a[0] - b[0]) , (a[1] - b[1]))
except:
answer = 0
return answer

Resources