Rotation & offset position

BlitzMax Forums/BlitzMax Programming/Rotation & offset position

ima747(Posted 2010) [#1]
Example problem:
I have an image (100x100) that I want to draw in the center of a rectangular area (300x200). The image can vary in size/aspect ratio as can the rectangular area. The image could also be text drawn with DrawText(), as such the image handle must remain the default (to be compatable with drawing text in it's place). To draw centered I would normally calculate the offset by the following.
x = rectArea.x + rectArea.width/2 - image.width/2


This works great. However I now need to rotate the drawing area. The offset calculation won't take the rotation into account, so it will be drawn where it previously would have been, just rotated...

Any suggestions on a relatively easy way to calculate the x and y offsets taking rotation into account? If it were all mid handled it wouldn't be a problem, but then I couldn't support text unless I did something like draw the text to the backbuffer, grab it with masking into an image and use that... but that will come out with some jaggies etc and is quite a lot slower since I have to draw/grab/image-draw every text element...


ImaginaryHuman(Posted 2010) [#2]
use AutoMidHandle and just draw the image at the center of the rectangle? If it's text it should work too?


ima747(Posted 2010) [#3]
I'm unaware of any way to get text to mid handle. AutoMidHandle, just sets the imagehandle to it's mid point automatically when it's created (the same process as creating an image and then setting it's handle yourself), but text is not created as an image as such, just given a draw position which is it's upper left corner. While in the end I think it all gets rendered out to surfaces before being draw (rotation works etc.) but since there's no direct access to that surface, auto mid doesn't work.


ima747(Posted 2010) [#4]
There are also other reasons I need to calculate the offset, such as determining if a click is inside a rect that is rotated. The top example is the the cleanest I could think off (fewer extra steps etc.) though I suppose text would have been stricter... new example:

I want to draw text centered, inside a rectangle, scaled and rotated

I calculate the position without rotation as follows

x = rectArea.x * scale + (rectArea.width * scale)/2.0 - (TextWidth(text) * scale)/2.0


How would I factor rotation into the offset for text. Alternatively how can one mid-handle text.


Czar Flavius(Posted 2010) [#5]
Function TextHeight( text$ )
Function TextWidth( text$ )
the height/width, in pixels, of text based on the current image font.


Jesse(Posted 2010) [#6]
I don't know if this is any help to you but this code uses blitzmax integrated scale and rotation to solve it:
SuperStrict
Graphics 800,600
	
Global gfx:TMax2dGraphics = tmax2dgraphics.Current()
Global text:String = "this is centered"	
Global scale:Float = 2.0
Global angle:Float = 0.0
Local transx:Float = (Float(TextWidth(text))/2.0) 'text center width
Local transy:Float = (Float(TextHeight(text))/2.0) 'text center height
SetScale scale,scale
Repeat 
	Cls
	SetRotation angle
	Local x:Float = 300 - (transx * gfx.tform_ix + transy * gfx.tform_iy)
	Local y:Float = 300 - (transx * gfx.tform_jx + transy * gfx.tform_jy)
	DrawText text,x,y
	angle :+ 1.0
	Flip()
Until KeyDown(key_escape)



ima747(Posted 2010) [#7]
Jesse my hero! that's perfect for mid handling text... had no idea the tform was accessable and usable in that way, love it!


Oddball(Posted 2010) [#8]
Ima747 are just trying to rotate the screen and have all image drawn in the correct place? I couldn't quite work it out from your first post. If you are you might want to check out my Odd2D module which does exactly that. It even has a function for getting the correct mouse position after rotation.


ima747(Posted 2010) [#9]
In full what I need to accomplish is to draw a base image un rotated and un-scaled. On top of that draw rectangles that can be individually rotated. They can also be outlined (with drawline) so the lines need to be positioned and rotated as well. And finally draw images and or text centered inside those rotated rectangles that preserve the image/text aspect ratio... and a few other things, but each set of elements has to be matched together.

With jesse's code it is possible to calculate an offset that takes into account the currently active rotation, which means I can do all the various things I need to. His sample specifically gives you text that behaves like a midhandled image to make the rotation easy.


ima747(Posted 2010) [#10]
Here are the offset functions I've spun incase anyone else needs them.

Function OffsetWithRotationX:Float(pivotX:Float, offsetX:Float, offsetY:Float)
	local gfx:TMax2dGraphics = tmax2dgraphics.Current()
	Return pivotX + (offsetX * gfx.tform_ix + offsetY * gfx.tform_iy)
End Function


Function OffsetWithRotationY:Float(pivotY:Float, offsetX:Float, offsetY:Float)
	local gfx:TMax2dGraphics = tmax2dgraphics.Current()
	Return pivotY + (offsetX * gfx.tform_jx + offsetY * gfx.tform_jy)	
End Function


For better performance mod them to take gfx as an input or just make that a global somewhere else, speed isn't an issue for me so I made it more code portable for re-use some other time.

Important note, since these calculate positions with rotation factored in don't use them directly in things like DrawLine(), as the second point in draw line automatically has rotation applied to it so you end up with double rotation... but they're perfect for calculating an offset with rotation such as centering text, etc.

[update]
Corrected typo in function names
important note, this takes your graphics scale setting into account as well so don't forget about that when passing in your desired offsets (they will be scaled, use full size)


Czar Flavius(Posted 2010) [#11]
This thread is being weird for me. My post says

(Posted 20 hours ago) Edit #5

but the post before says

(Posted 54 minutes ago) #4

and the ones prior have more recent times too.


TaskMaster(Posted 2010) [#12]
This happens every month on the 1st. Times get screwy. Something in the calculation Mark uses.