webentwicklung-frage-antwort-db.com.de

Eine affine Transformation für die Rotation um einen Punkt?

Wie kann ich eine Core Graphics-affine Transformation für die Drehung um einen Punkt x, y des Winkels a vornehmen, indem ich nur einen einzigen Aufruf von CGAffineTransformMake () plus math.h-Funktionen wie sin (), cos () usw. verwendet keine anderen CG-Anrufe.

Bei anderen Antworten handelt es sich anscheinend um die Verwendung mehrerer gestapelter Transformationen oder mehrstufiger Transformationen zum Verschieben, Drehen und Verschieben mit mehreren Core Graphics-Aufrufen. Diese Antworten entsprechen nicht meinen spezifischen Anforderungen.

40
hotpaw2

Eine Drehung des Winkels a um den Punkt (x, y) entspricht der affinen Transformation:

CGAffineTransform transform = CGAffineTransformMake(cos(a),sin(a),-sin(a),cos(a),x-x*cos(a)+y*sin(a),y-x*sin(a)-y*cos(a));

Möglicherweise müssen Sie -a anstelle eines einstecken, abhängig davon, ob die Drehung im oder gegen den Uhrzeigersinn erfolgen soll. Möglicherweise müssen Sie -y anstelle von y anschließen, je nachdem, ob Ihr Koordinatensystem auf dem Kopf steht oder nicht.

In drei Codezeilen können Sie genau dasselbe erreichen, indem Sie Folgendes verwenden:

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, a);
transform = CGAffineTransformTranslate(transform,-x,-y);

Wenn Sie dies auf eine Ansicht anwenden, können Sie auch einfach eine Rotationstransformation über CGAffineTransformMakeRotation (a) verwenden, vorausgesetzt, Sie setzen die AnkerPoint-Eigenschaft der Ansichtsebene so, dass sie den Punkt darstellt, um den Sie drehen möchten. Es klingt jedoch so, als ob Sie nicht daran interessiert sind, dies auf eine Ansicht anzuwenden.

Wenn Sie dies auf einen nicht-euklidischen 2D-Raum anwenden, möchten Sie möglicherweise überhaupt keine affine Transformation. Affine Transformationen sind Isometrien des euklidischen Raums, das heißt, dass sie die standardmäßige euklidische Entfernung sowie Winkel beibehalten. Wenn Ihr Raum nicht euklidisch ist, ist die Transformation, die Sie wünschen, möglicherweise nicht affin oder wenn es affin ist, ist die Matrix für die Rotation möglicherweise nicht so einfach wie die, die ich oben mit sin und cos geschrieben habe. Wenn Sie sich beispielsweise in einem hyperbolischen Raum befanden, müssen Sie möglicherweise die hyperbolischen Triggerfunktionen sinh und cosh sowie verschiedene + und - Zeichen in der Formel verwenden.

P.S. Ich möchte auch jeden, der so weit liest, daran erinnern, dass "affine" mit einem kurzen "a" wie in "ask" ausgesprochen wird, nicht einem langen "a" wie in "fähig". Ich habe sogar gehört, dass Apple-Mitarbeiter es in ihren WWDC-Gesprächen falsch verkünden.

112
landweber

Für diejenigen wie mich, die auf der Suche nach einer vollständigen Lösung kämpfen, um ein Bild zu drehen und richtig zu skalieren, um den Rahmen zu füllen, ist dies nach einigen Stunden die vollständigste und fehlerloseste Lösung, die ich erhalten habe.

Der Trick besteht hier darin, den Bezugspunkt vor der jeweiligen Transformation (sowohl Maßstäbe als auch Rotation) zu übersetzen. Danach müssen Sie die beiden Transformationen verketten, um eine vollständige affine Transformation zu erhalten. 

Ich habe die gesamte Lösung in eine CIFilter-Unterklasse gepackt, die Sie hier herunterladen können .

Folgen Sie dem relevanten Teil des Codes:

CGFloat a = _inputDegree.floatValue;
CGFloat x = _inputImage.extent.size.width/2.0;
CGFloat y = _inputImage.extent.size.height/2.0;

CGFloat scale = [self calculateScaleForAngle:GLKMathRadiansToDegrees(a)];

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, a);
transform = CGAffineTransformTranslate(transform,-x,-y);


CGAffineTransform transform2 = CGAffineTransformMakeTranslation(x, y);
transform2 = CGAffineTransformScale(transform2, scale, scale);
transform2 = CGAffineTransformTranslate(transform2,-x,-y);

CGAffineTransform concate   = CGAffineTransformConcat(transform2, transform);
1
valvoline

für Swift 4

print(x, y) // where x,y is the point to rotate around
let degrees = 45.0
let transform = CGAffineTransform(translationX: x, y: y)
    .rotated(by: degrees * .pi / 180)
    .translatedBy(x: -x, y: -y)
1
Ming Chu

Schauen Sie sich diesen Link an: Drehen einer iPhone-Ansicht um einen Punkt . Es kann dir helfen. Am Ende des Artikels befindet sich ein Abschnitt mit dem Titel "Ankerpunkt ändern". Dies ist wahrscheinlich am besten für Ihre Bedürfnisse geeignet, obwohl einige Kompensationen erforderlich sind, um die Ansicht nicht zu verschieben.

0
aopsfan