Page 1 of 2

Manually rotating points around center

Posted: Tue May 24, 2011 9:56 pm
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 882 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.

Re: Manually rotating points around center

Posted: Tue May 24, 2011 10:04 pm
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!

Re: Manually rotating points around center

Posted: Tue May 24, 2011 10:06 pm
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?

Re: Manually rotating points around center

Posted: Tue May 24, 2011 10:10 pm
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?

Re: Manually rotating points around center

Posted: Tue May 24, 2011 11:15 pm
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.

Re: Manually rotating points around center

Posted: Tue May 24, 2011 11:33 pm
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?

Re: Manually rotating points around center

Posted: Tue May 24, 2011 11:38 pm
by slime

Re: Manually rotating points around center

Posted: Tue May 24, 2011 11:51 pm
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

Re: Manually rotating points around center

Posted: Wed May 25, 2011 12:58 am
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.

Re: Manually rotating points around center

Posted: Wed May 25, 2011 9:11 am
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.