Rotate around point

BlitzMax Forums/BlitzMax Programming/Rotate around point

Yahfree(Posted 2009) [#1]
Hey, can someone tell me what I'm doing wrong with the math behind this:



I'm just trying to rotate a point around another point, storing those new x/y values.

The ending goal of which is to attach a image to another image. as sort of a child:

RotateAroundOrigin(x, y, player.x, player.y, player.angle)
SetRotation(player.angle)
DrawImage img, y, x
SetRotation(0)


However, this is not working.

Additionally, does anyone know of a place that can explain the math behind rotation around a point? I always seem to have trouble getting that to work, no matter how many projects I use it in.


GfK(Posted 2009) [#2]
You're overcomplicating it.

Typed straight into the reply box, so untested. It should give you one point orbiting another.
Strict
Local xP:int = 400
Local yP:int = 300
Local d:int = 50
Local a:int
Local newX:float,newY:float

Graphics 800,600

Repeat
  a:+1
  a:Mod 360

  newX = Cos(a) * d + xP
  newY = Sin(a) * d + yP

  Cls
  Plot xP,yP 'centre
  Plot newX,newY ' new coords
  Flip
Forever



Yahfree(Posted 2009) [#3]
That works.. Then what was I doing?

I googled "rotate point around point 2d" to get the equation I used:

"RotatePoint.X = Cos(D2R(Degrees)) * pPoint.X - Sin(D2R(Degrees)) * pPoint.Y
RotatePoint.Y = Sin(D2R(Degrees)) * pPoint.X + Cos(D2R(Degrees)) * pPoint.Y"

Much different?

Anyways, thanks Gfk.


GfK(Posted 2009) [#4]
I dunno what that's all about! Looks like there's a function missing in there as they're converting from degrees to radians. Your code by-passed that which probably explains why the result did not work.


Zakk(Posted 2009) [#5]
Blitz uses degrees though, right?


_JIM(Posted 2009) [#6]
@Zakk, yes.

@Yahfree

Your code doesn't behave like the equation you posted.
According to the equation, your code should be:

newX = Cos(a) * (x-ox) - Sin(a) * (y-oy) + ox
newY = Sin(a) * (x-ox) - Cos(a) * (y-oy) + oy


However this gives weird results.

There is a way to fix your code, but there are some major errors. First of all you don't hold data about the angle of the point. Just the distance. Then the math behind tx an ty is wrong:

Function RotateAroundOrigin(X:Float Var, Y:Float Var, ox:Float, oy:Float, a:Int)
	Local DX:Float = X - ox
	Local DY:Float = Y - oy
	Local angdiff:Float = ATan2(DX, DY)
	Local dist:Float = Sqr(DX * DX + DY * DY)
	Local s:Float = Sin(a + angdiff)
	Local c:Float = Cos(a + angdiff)
	Local tx:Float = (dist * s)
	Local ty:Float = (dist * c)
	x = tx + ox
	y = ty + oy
	Return
End Function

Graphics 800, 600

Global oX:Float = 400
Global oY:Float = 300

Global rX:Float = oX + 60
Global rY:Float = oY + 40
Global a:Float = 1

While Not KeyHit(KEY_ESCAPE)
	RotateAroundOrigin(rX, rY, ox, oy, a)
	Plot rX, rY
	Plot ox, oy
	Flip
Wend
End


This works, but I would recommend using something like this:

Type TTransform2D
	Field Matrix:Double[2, 2]
	Field Rotation:Float = 0
	Field ScaleX:Float = 1
	Field ScaleY:Float = 1
	
	Method Init(sx:Float = 1, sy:Float = 1, rot:Float = 0)
		Self.ScaleX = sx
		Self.ScaleY = sy
		Self.Rotation = rot
		Self.Update()
	EndMethod
	
	Method Scale(sx:Float, sy:Float)
		ScaleX = sx
		ScaleY = sy
		
		Self.Update()
	EndMethod
	
	Method Update()
		Matrix[0, 0] = Cos(Rotation)
		Matrix[1, 0] = - Sin(Rotation)
		Matrix[0, 1] = Sin(Rotation)
		Matrix[1, 1] = Cos(Rotation)
	End Method
	
	Method Rotate(angle:Float)
		Rotation = angle
		
		Self.Update()
	EndMethod
	
	Method Transform(x:Float var, y:Float var)
		Local xx:Float
		Local yy:Float
		
		x = x * ScaleX
		y = y * ScaleY
		
		xx = x * Matrix[0, 0] + y * Matrix[1, 0]
		yy = x * Matrix[0, 1] + y * Matrix[1, 1]
		
		x = xx
		y = yy
	End Method
	
	Method ITransform(x:Float var, y:Float var)
		Local xx:Float
		Local yy:Float
		
		Self.Rotation = -Self.Rotation
		Self.Update()
		
		xx = x * Matrix[0, 0] + y * Matrix[1, 0]
		yy = x * Matrix[0, 1] + y * Matrix[1, 1]
		
		Self.Rotation = -Self.Rotation
		Self.Update()
		
		xx = xx / ScaleX
		yy = yy / ScaleY
		
		x = xx
		y = yy
	End Method
End Type

Function RotateAroundOrigin(X:Float Var, Y:Float Var, ox:Float, oy:Float, a:Int)
	Local t2d:TTransform2D = New TTransform2D
	t2d.Init(1, 1, a)
	X:-ox
	Y:-oy
	t2d.Transform(X, Y)
	X:+ox
	Y:+oy
	Return
End Function

Graphics 800, 600

Global oX:Float = 400
Global oY:Float = 300

Global rX:Float = oX + 60
Global rY:Float = oY + 40
Global a:Float = 1

While Not KeyHit(KEY_ESCAPE)
	RotateAroundOrigin(rX, rY, ox, oy, a)
	Plot rX, rY
	Plot ox, oy
	Flip
Wend
End