Comment faire pivoter un sommet autour d'un certain point?

Imaginez que vous avez deux points dans l'espace 2d et vous devez faire pivoter L'un de ces points de x degrés avec l'autre point agissant comme un centre.

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

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

Jusqu'à présent, je viens de trouver la distance entre les deux points... toutes les idées où dois-je aller à partir de cela?

entrez la description de l'image ici

50
demandé sur p0rter 2012-08-28 18:16:05

6 réponses

L'approche la plus simple consiste à composer trois transformations:

  1. une traduction qui amène le point 1 à l'origine
  2. Rotation autour de l'origine par l'angle requis
  3. une traduction qui ramène le point 1 à sa position initiale

Lorsque vous travaillez tout cela, vous vous retrouvez avec la transformation suivante:

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

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

Notez que cela suppose que l'angle x est négatif pour la rotation dans le sens des aiguilles d'une montre (la norme dite ou orientation à droite pour le système de coordonnées). Si ce n'est pas le cas, alors vous devrez inverser le signe sur les Termes impliquant sin(x).

58
répondu Ted Hopp 2017-08-27 12:45:04

Vous avez besoin d'une matrice de rotation 2-d http://en.wikipedia.org/wiki/Rotation_matrix

Votre nouveau point sera

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

Parce que vous tournez dans le sens horaire plutôt que dans le sens antihoraire

17
répondu mathematician1975 2012-08-28 14:33:07

En supposant que vous utilisez L'API Java Graphics2D, essayez ce code -

    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;

Où pivot est le point autour duquel vous tournez.

8
répondu Slavcho 2012-08-28 14:24:44
  1. Traduire "1" à 0,0

  2. Rotation

    X = sin (angle) * r; y = cos (angle) * r;

  3. Le Traduire en arrière

2
répondu Tutankhamen 2012-08-28 14:31:10

Voici un moyen de faire pivoter n'importe quel point sur n'importe quel autre point en 2D. notez qu'en 3D cela peut être utilisé comme rotation autour de l'axe z, la coordonnée z d'un point étant ingérée car elle ne change pas. La Rotation autour de l'axe x et de l'axe y en 3D peut également être facilement implémentée.

Le code est en JavaScript. Les lignes commentées au début sont un jeu de test pour la fonction. Ils servent également d'exemple d'utilisation.

//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
répondu Jan Kokes 2015-11-07 18:12:10

Voici une version qui se soucie de la direction de rotation. La droite (dans le sens horaire) est négative et la gauche (dans le sens antihoraire) est positive. Vous pouvez envoyer un point ou un vecteur 2d et définir ses primitives dans cette méthode (dernière ligne) pour éviter l'allocation de mémoire pour les performances. Vous devrez peut-être remplacer vector2 et mathutils aux bibliothèques que vous utilisez ou à la classe de point intégrée de java et vous pouvez utiliser math.toradians () au lieu 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);
}

Notez que cette façon a plus de performances que la façon dont vous avez essayé votre post. Parce que vous utilisez sqrt qui est très coûteux et de cette façon la conversion de degrés en radians gérés avec une table de recherche, Si vous vous demandez. Et donc il a des performances très élevées.

0
répondu ömer.bozkurt 2017-05-31 08:48:41