Manually rotating points around center

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Manually rotating points around center

Post by Jasoco »

Say I have a bunch of points in a shape, or even one single point or two or whatever.

Now I have a center point. How do I rotate each point? (Obviously I just need to know how to rotate based on an offset.)
eFnpL.png
eFnpL.png (13.09 KiB) Viewed 885 times
I already know how to place a point at an angle based on a fixed distance and a center point.

Code: Select all

x = center_x + (math.sin((angle) * pi / 180) * (distance))
y = center_y + (math.cos((angle) * pi / 180) * (distance))
I just don't know how to take points that already exist and move them around a center.

If I can avoid having to use Box2D even just for calculations that would be nice.
User avatar
Chief
Party member
Posts: 101
Joined: Fri Mar 12, 2010 7:57 am
Location: Norway, 67° north

Re: Manually rotating points around center

Post by Chief »

if you have the center on cx and cy, original position of a point on x and y and the angle to rotate rad:

nx and ny are the new points.

Code: Select all

nx = x*math.cos( rad ) - y*math.sin( rad ) + cx
ny = x*math.sin( rad ) + y*math.cos( rad ) + cy
Im 96,77% sure that will work!


Edit:
God damn'in I was close. This function will rotate the points with center 0,0 and then shift it with cx and cy. Im tired!
Last edited by Chief on Tue May 24, 2011 10:07 pm, edited 1 time in total.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Manually rotating points around center

Post by Jasoco »

How can I make a function from that where it will return the new X and Y from passing the Center X and Y and the original Offset X and Y. Where original offset is the offset from the center?
User avatar
Chief
Party member
Posts: 101
Joined: Fri Mar 12, 2010 7:57 am
Location: Norway, 67° north

Re: Manually rotating points around center

Post by Chief »

Code: Select all

function Magic( x, y, cx, cy, ox, oy, rad )
    local nx = (x - cx)*math.cos( rad ) - (y - cy)*math.sin( rad ) + ox
    local ny = (x - cx)*math.sin( rad ) + (y - cy)*math.cos( rad ) + oy

    return nx, ny;
end
I believe this would work?
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Manually rotating points around center

Post by kikito »

If this is only a visual effect, probably you can "cheat" and just use love.graphics.translate and love.graphics.rotate. If you need those calculations for other things besides graphical stuff (i.e. collision detection) then you have to use trigonometry.
When I write def I mean function.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Manually rotating points around center

Post by Jasoco »

I don't want to use the translate and rotate calls really. I want to move points as I will also be using this in my 3D engine at some point and those calls wouldn't really translate (No pun intended) to that program easily if at all.

I need to move the points, that are already set by offsets, around the center.

Like if I had a center point of 100, 100 and one of the polygon points is at -10, -10 from that center point. If I rotate that point around the center, that's the math I'm looking for.

The function above wasn't accounting for the offset for some reason. I mean shouldn't the Offset X and Y be the same as the regular X and Y?
User avatar
slime
Solid Snayke
Posts: 3166
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Manually rotating points around center

Post by slime »

User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Manually rotating points around center

Post by Jasoco »

That first link got me to create this:

Code: Select all

function rotate_point( cx, cy, ox, oy, angle )
  local rot_pnt = { x, y }
  rot_pnt.x = ox * math.cos(math.rad(-angle)) - oy * math.sin(math.rad(-angle))
  rot_pnt.y = ox * math.sin(math.rad(-angle)) + oy * math.cos(math.rad(-angle))
  return rot_pnt.x + cx, rot_pnt.y + cy
end
Which seems to work pretty good. I had to negative the angle though and change the rad to angle since I am more familiar with using 0 - 359 instead of PI * 2 for my angles.

Code: Select all

new_x, new_y = rotate_point(center_x, center_y, offset_x, offset_y, angle)
This will be a useful addition to my collection of useful math-related functions.

Now to create a rotate 3D point function. lol
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Manually rotating points around center

Post by Jasoco »

Oh, hey. This seems to work...

Create a 3D Object: (Points only right now, triangles later)

Code: Select all

obj3d = {}

obj3d[1] = {
  x = 200,
  y = 100,
  z = 0,
  rot = {
    xy = 0,
    xz = 0,
    yz = 0
  },
  pnt = {
    [1] = {-30, -30, -30},
    [2] = { 30, -30, -30},
    [3] = { 30,  30, -30},
    [4] = {-30,  30, -30},
    [5] = {-30, -30,  30},
    [6] = { 30, -30,  30},
    [7] = { 30,  30,  30},
    [8] = {-30,  30,  30}
  }
}
The rotate 3d point function:

Code: Select all

function rotate_point_3d( cx, cy, cz, ox, oy, oz, angle_xy, angle_xz, angle_yz )
  local rot_pnt = { x, y, z }
  rot_pnt.x = ox * math.cos(math.rad(-angle_xy)) - oy * math.sin(math.rad(-angle_xy))
  rot_pnt.y = ox * math.sin(math.rad(-angle_xy)) + oy * math.cos(math.rad(-angle_xy))

  ox = rot_pnt.x
  rot_pnt.x = ox * math.cos(math.rad(-angle_xz)) - oz * math.sin(math.rad(-angle_xz))
  rot_pnt.z = ox * math.sin(math.rad(-angle_xz)) + oz * math.cos(math.rad(-angle_xz))

  oy = rot_pnt.y
  oz = rot_pnt.z
  rot_pnt.y = oy * math.cos(math.rad(-angle_yz)) - oz * math.sin(math.rad(-angle_yz))
  rot_pnt.z = oy * math.sin(math.rad(-angle_yz)) + oz * math.cos(math.rad(-angle_yz))

  return rot_pnt.x + cx, rot_pnt.y + cy, rot_pnt.z + cz
end
Rotate and draw the points:

Code: Select all

function draw_object_3d(obj)
  local x, y, z = {}, {}, {}
  for i, p in pairs(obj3d[obj].pnt) do
    obj3d[obj].rot.xy = obj3d[obj].rot.xy + dt * 20
    obj3d[obj].rot.xz = obj3d[obj].rot.xz + dt * 20
    x[i], y[i], z[i] = rotate_point_3d(
      obj3d[obj].x, obj3d[obj].y, obj3d[obj].z,
      p[1], p[2], p[3],
      obj3d[obj].rot.xy, obj3d[obj].rot.xz, obj3d[obj].rot.yz
    )
    love.graphics.circle("fill", x[i], y[i], 2)
  end
end
Of course this does nothing for sorting and handling large amounts. So I have to do some tweaking and thinking.

Edit: Eh. Experiment was a slight failure. Will try again maybe sometime in the future.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Manually rotating points around center

Post by kikito »

Encapsulating your rotating/translating operations inside a Vector and/or Matrix class/structure might simplify and speed your code up ... at the cost of having to understand the involved Algebra first (and sorry, I can't help on that one).

Code: Select all

local v = Vector3D(-30, -30, -30)
v:rotate(math.pi,0,0)
Also, if you start having points depending on other points (i.e. points A,B & C rotate around point D which rotates over point E) then you will probably need to implement a micro scene graph, and traverse it for calculating all the coordinates.

I'm not very familiar with SceneGraphs, but it seems that in that case most of the "transforms" would occur on the nodes, which would be used to "group" the points. This is an imaginary interface:

Code: Select all

local root = SceneGraph:root()

local node1 = root:createChildNode()
node1:addObject(Vector3D(30, 30, 30))
node1:addObject(Vector3D(30, 30, 30))

-- node2 depends on node1
local node2 = node1:createChildNode()
node2:addObject(Vector3D(30,30,30))

-- prints 30,30,30 three times
root:traverse(function(object)
  print(object.x, object.y, object.z)
end)

-- move the nodes around
node1:rotate(math.pi,0,0)
node2:translate(100,100,0)

-- the points have been moved
root:traverse(function(object)
  print(object.x, object.y, object.z)
end)
Again, take my advice with a grain of salt; I'm no expert on these things.
When I write def I mean function.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 11 guests