2012-08-28 14 views
48

Imagine que tiene dos puntos en el espacio 2d y necesita girar uno de estos puntos en X grados con el otro punto actuando como un centro.¿Cómo rotar un vértice alrededor de un cierto punto?

float distX = Math.abs(centerX -point2X); 
float distY = Math.abs(centerY -point2Y); 

float dist = FloatMath.sqrt(distX*distX + distY*distY); 

Hasta ahora solo llegué a encontrar la distancia entre los dos puntos ... ¿Alguna idea de a dónde debería ir desde eso?

enter image description here

+0

Tome un vistazo a esto .. que podría ayudar a despejar las cosas: http://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions – Sednus

Respuesta

54

El método más sencillo es componer tres transformaciones:

  1. una traducción que aporta el punto 1 al origen
  2. rotación alrededor del origen por el ángulo requerido
  3. una traducción que devuelve el punto 1 a su posición original

Cuando se trabaja todo esto a cabo, se termina con la siguiente transformación:

newX = centerX + (point2x-centerX)*Math.cos(x) - (point2y-centerY)*Math.sin(x); 

newY = centerY + (point2x-centerX)*Math.sin(x) + (point2y-centerY)*Math.cos(x); 

Tenga en cuenta que esto hace que el supuesto de que el ángulo x es negativo para el giro a la derecha (el llamado standard or right-hand orientation para el sistema de coordenadas). Si ese no es el caso, entonces deberá revertir el signo en los términos relacionados con sin(x).

+2

Suena como una respuesta OpenGL –

+7

@CoreyOgburn - Es una respuesta básica geometría plana. Aprendí esto mucho antes de que hubiera un OpenGL :) –

+0

Seguramente debe tener en cuenta el ángulo de las agujas del reloj ??? – mathematician1975

1
  1. Traducir "1" a 0,0

  2. Girar

    x = sen (ángulo) * r; y = cos (ángulo) * r;

  3. Traducir de nuevo

+2

no es preciso. El OP quiere rotar alrededor de un punto específico. Como @Ted Hopp indicó que debe haber una traducción al origen, aplica la rotación y luego vuelve a traducir a la ubicación original. (Sin las traducciones, la rotación será alrededor del 0,0 de la pantalla) – giorashc

+2

Para ser justos, el OP publicó una imagen gigante que indica el punto 1 en el origen. –

+1

Como ya sabes, para girar algo alrededor de un punto específico, puedes simplemente traducir este punto a "cero", rotarlo y luego traducirlo de nuevo ... – Tutankhamen

16

Usted necesita una matriz de rotación 2-d http://en.wikipedia.org/wiki/Rotation_matrix

Su nuevo punto será

newX = centerX + (cosX * (point2X-centerX) + sinX * (point2Y -centerY)) 
newY = centerY + (-sinX * (point2X-centerX) + cosX * (point2Y -centerY)) 

porque está girando hacia la derecha en lugar de hacia la izquierda

+0

¡Gracias, parece que funciona muy bien! :) –

8

Suponiendo que se usa el Java G raphics2D API, pruebe este código -

Point2D result = new Point2D.Double(); 
    AffineTransform rotation = new AffineTransform(); 
    double angleInRadians = (angle * Math.PI/180); 
    rotation.rotate(angleInRadians, pivot.getX(), pivot.getY()); 
    rotation.transform(point, result); 
    return result; 

donde pivote es el punto por el que está girando.

+2

También hay 'Math.toRadians()' en Java ;-) – Betlista

0

Aquí hay una manera de rotar cualquier punto sobre cualquier otro punto en 2D. Tenga en cuenta que en 3D esto se puede utilizar como rotación sobre el eje z, coordenada z de un punto que se está utilizando, ya que no cambia. La rotación sobre el eje xy el eje y en 3D también se puede implementar fácilmente.

El código está en JavaScript. Las líneas comentadas al principio son un conjunto de prueba para la función. También sirven como un ejemplo de uso.

//A = new Array(0,0) 
//S = new Array(-1,0) 
//fi = 90 
//alert("rotujBod: " + rotatePoint(A, S, fi)) 

function rotatePoint(A, S, fi) { 
/** IN points A - rotated point, S - centre, fi - angle of rotation (rad) 
* points in format [Ax, Ay, Az], angle fi (float) 
*  OUT point B 
*/ 
    r = Math.sqrt((A[0] - S[0])*(A[0] - S[0]) + (A[1] - S[1])*(A[1] - S[1])) 
    originOfRotation = new Array(S[0] + r, S[1]) 
    if (A[1] < S[1]) { 
     A2 = new Array(A[0], -1*A[1]) 
     originalAngle = -1*sizeOfAngle(originOfRotation, S, A2) 
    } else { 
    originalAngle = sizeOfAngle(originOfRotation, S, A) 
    } 
    x = S[0] + r*Math.cos(fi + originalAngle) 
    y = S[1] + r*Math.sin(fi + originalAngle) 
    B = new Array(x, y) 
    return(B) 
} 

function sizeOfAngle(A, S, B) { 
    ux = A[0] - S[0] 
    uy = A[1] - S[1] 
    vx = B[0] - S[0] 
    vy = B[1] - S[1] 
    if((Math.sqrt(ux*ux + uy*uy)*Math.sqrt(vx*vx + vy*vy)) == 0) {return 0} 
    return Math.acos((ux*vx + uy*vy)/(Math.sqrt(ux*ux + uy*uy)*Math.sqrt(vx*vx + vy*vy))) 
} 
0

Aquí una versión que se preocupa por la dirección de rotación.La derecha (en sentido horario) es negativa y la izquierda (en sentido contrario a las agujas del reloj) es positiva. Puede enviar un punto o un vector 2d y establecer sus primitivos en este método (última línea) para evitar la asignación de memoria para el rendimiento. Es posible que necesite reemplazar vector2 y mathutils en las bibliotecas que usa o en la clase de punto incorporada de java y puede usar math.toradians() en lugar de mathutils.

/** 
* rotates the point around a center and returns the new point 
* @param cx x coordinate of the center 
* @param cy y coordinate of the center 
* @param angle in degrees (sign determines the direction + is counter-clockwise - is clockwise) 
* @param px x coordinate of point to rotate 
* @param py y coordinate of point to rotate 
* */ 

public static Vector2 rotate_point(float cx,float cy,float angle,float px,float py){ 
    float absangl=Math.abs(angle); 
    float s = MathUtils.sin(absangl * MathUtils.degreesToRadians); 
    float c = MathUtils.cos(absangl * MathUtils.degreesToRadians); 

    // translate point back to origin: 
    px -= cx; 
    py -= cy; 

    // rotate point 
    float xnew; 
    float ynew; 
    if (angle > 0) { 
     xnew = px * c - py * s; 
     ynew = px * s + py * c; 
    } 
    else { 
     xnew = px * c + py * s; 
     ynew = -px * s + py * c; 
    } 

    // translate point back: 
    px = xnew + cx; 
    py = ynew + cy; 
    return new Vector2(px, py); 
} 

Tenga en cuenta que esta forma tiene más rendimiento que la forma en que lo intentó en su publicación. Debido a que utiliza sqrt que es muy costoso y de esta manera la conversión de grados a radianes gestionados con una tabla de búsqueda, si se lo espera. Y entonces tiene un rendimiento muy alto.

Cuestiones relacionadas