Come ruotare un vertice attorno ad un certo punto?

Immagina di avere due punti nello spazio 2d e devi ruotare uno di questi punti di X gradi con l’altro punto che funge da centro.

float distX = Math.abs( centerX -point2X ); float distY = Math.abs( centerY -point2Y ); float dist = FloatMath.sqrt( distX*distX + distY*distY ); 

Finora ho solo trovato la distanza tra i due punti … qualche idea da dove dovrei andare?

inserisci la descrizione dell'immagine qui

L’approccio più semplice consiste nel comporre tre trasformazioni:

  1. Una traduzione che porta il punto 1 all’origine
  2. Rotazione attorno all’origine dall’angolo richiesto
  3. Una traduzione che riporta il punto 1 nella sua posizione originale

Quando lavori tutto questo, finisci con la seguente trasformazione:

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

Si noti che ciò presuppone che l’angolo x sia negativo per la rotazione in senso orario (il cosiddetto orientamento standard o destro per il sistema di coordinate). Se questo non è il caso, allora dovresti invertire il segno sui termini che coinvolgono sin(x) .

Hai bisogno di una matrice di rotazione 2-d http://en.wikipedia.org/wiki/Rotation_matrix

Il tuo nuovo punto sarà

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

perché stai ruotando in senso orario anziché antiorario

Supponendo che tu usi l’API Java Graphics2D, prova questo codice –

  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; 

dove pivot è il punto in cui stai ruotando.

  1. Traduci “1” a 0,0

  2. Ruotare

    x = sin (angolo) * r; y = cos (angolo) * r;

  3. Traduci indietro

Ecco un modo per ruotare qualsiasi punto su qualsiasi altro punto in 2D. Si noti che in 3D questo può essere usato come rotazione attorno all’asse z, coordinata z di un punto che viene ingigantito poiché non cambia. La rotazione sull’asse xe sull’asse y in 3D può essere facilmente implementata.

Il codice è in JavaScript. Le righe commentate all’inizio sono un test set per la funzione. Servono anche come esempio di utilizzo.

 //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))) } 

Ecco una versione che si occupa della direzione di rotazione. Destra (in senso orario) è negativa e sinistra (in senso antiorario) è positiva. È ansible inviare un punto o un vettore 2D e impostare le sue primitive in questo metodo (ultima riga) per evitare l’allocazione della memoria per le prestazioni. Potrebbe essere necessario sostituire vector2 e mathutils con le librerie che si usano o con la class di punti integrata di java e si può usare math.toradians () invece di 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); } 

Nota che in questo modo ha più prestazioni rispetto al modo in cui hai provato nel tuo post. Perché tu usi sqrt che è molto costoso e in questo modo convertire da gradi a radianti gestiti con una tabella di ricerca, se ti chiedi. E quindi ha prestazioni molto elevate.