¿Cómo rotar un vértice alrededor de un punto determinado?

Imagina que tienes dos puntos en el espacio 2d y necesitas rotar uno de estos puntos X grados con el otro punto actuando como centro.

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 adónde debo ir desde eso?

enter image description here

preguntado el 28 de agosto de 12 a las 15:08

Echa un vistazo a esto... podría ayudar a aclarar las cosas: en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions -

6 Respuestas

El enfoque más sencillo es componer tres transformaciones:

  1. Una traslación que lleva el punto 1 al origen
  2. Rotación alrededor del origen por el ángulo requerido
  3. Una traslación que devuelve el punto 1 a su posición original.

Cuando resuelves todo esto, terminas con la siguiente transformación (donde x es el ángulo de rotación deseado en radianes):

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 supone que el ángulo x es negativa para la rotación en el sentido de las agujas del reloj (la llamada orientación estándar o derecha para el sistema de coordenadas). Si ese no es el caso, entonces deberá invertir el signo en los términos que involucran sin(x).

Respondido el 21 de junio de 20 a las 21:06

@mathematician1975: el ángulo debe ser positivo para la rotación en el sentido contrario a las agujas del reloj, negativo para el sentido de las agujas del reloj. Eso es prácticamente un estándar universal a menos que haya una declaración explícita de lo contrario (que no la hubo). Sin embargo, actualicé la respuesta para aclarar. Gracias. - ted salto

OK bastante justo. Solo pensé que, como el OP tal vez no haya hecho nada antes, es posible que no lo sepa y no estaría de más especificar la convención. - matemático 1975

El papel cuadriculado convencional se coordina con (+x=right, +y=up) son "diestros" con (+angles=counter-clockwise). Pero la pantalla convencional se coordina con (+x=right, +y=down) son "zurdos" con (+angles=clockwise). - tormenta venidera

@comingstorm - Buen punto. Supongo que lo correcto es decir que un ángulo de rotación positivo mueve el eje +x hacia el eje +y. - ted salto

Quería crear una función similar a la que se muestra en la página siguiente. Mi solución fue aplicar transform: rotate(120deg) a una imagen circular con fondo transparente. la imagen tiene height y width: 100% de su progenitor, rotate(120deg) rotará toda la imagen alrededor de su centro - Fabricio Bertoglio

Necesitas una matriz de rotación bidimensional 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ás girando en el sentido de las agujas del reloj en lugar de en el sentido contrario a las agujas del reloj

Respondido 28 ago 12, 15:08

Suponiendo que está utilizando la API Java Graphics2D, 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 alrededor del cual giras.

Respondido 28 ago 12, 15:08

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

  1. Traducir "1" a 0,0

  2. Girar

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

  3. Traducirlo de nuevo

Respondido 28 ago 12, 15:08

no es correcto. El OP quiere rotar alrededor de un punto específico. Como dijo @Ted Hopp, debe haber una traducción al origen, aplicar la rotación y luego traducir a la ubicación original nuevamente. (Sin las traslaciones la rotación será alrededor del 0,0 de la pantalla) - giorashc

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

Como sabes, para rotar algo alrededor de un punto específico, puedes simplemente traducir este punto a "cero", rotarlo y luego volver a traducirlo... - Tutankamón

@MarcBollinger: la imagen muestra el punto 1 en el centro de rotación. (Sí, hay ejes, pero ¿desde cuándo el origen tiene la etiqueta "1"? Eso, más la palabrería, debería ser al menos una pista). - ted salto

Aquí una versión que cuida la dirección de rotación. La derecha (en el sentido de las agujas del reloj) es negativa y la izquierda (en el sentido contrario a las agujas del reloj) es positiva. Puede enviar un punto o un vector 2d y establecer sus primitivas en este método (última línea) para evitar la asignación de memoria para el rendimiento. Es posible que deba reemplazar vector2 y mathutils en las bibliotecas que usa o en la clase de puntos integrada 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 usa sqrt que es muy costoso y de esta manera la conversión de grados a radianes se administra con una tabla de búsqueda, si se pregunta. Y por lo que tiene un rendimiento muy alto.

contestado el 31 de mayo de 17 a las 09:05

Aquí hay una forma de rotar cualquier punto sobre cualquier otro punto en 2D. Tenga en cuenta que en 3D esto se puede usar como rotación sobre el eje z, la coordenada z de un punto se ignora ya que no cambia. La rotación sobre el eje x y 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 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)))
}

respondido 07 nov., 15:18

¿Tienes la versión 3D de esta función? - Desolador

Le echaré un vistazo. Lo tengo, pero tendré que buscarlo. Era una especie de recursión monstruosa, un poco como la aproximación de Newton, evitando el uso de la matriz. Creo que lo publiqué en algún lugar de Stack Overflow, pero desde entonces no puedo encontrarlo. Debería estar en mi antigua copia de seguridad. - Jan Kokes

No es necesario, hombre, ya he implementado la solución aquí: stackoverflow.com/questions/59242195/… - Desolador

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.