web-dev-qa-db-fra.com

Une transformation affine en une étape pour la rotation autour d'un point?

Comment puis-je créer une transformation affine Core Graphics pour la rotation autour d'un point x, y de l'angle a, en utilisant un seul appel à CGAffineTransformMake () plus des fonctions trigonométiques math.h telles que sin (), cos (), etc. aucun autre appel de CG.

D’autres réponses semblent concerner l’utilisation de plusieurs transformations empilées ou de transformations en plusieurs étapes pour déplacer, faire pivoter et se déplacer, en utilisant plusieurs appels Core Graphics. Ces réponses ne répondent pas à mes exigences spécifiques.

40
hotpaw2

Une rotation de l'angle a autour du point (x, y) correspond à la transformation affine:

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));

Vous devrez peut-être connecter -a au lieu de selon selon que vous voulez que la rotation soit dans le sens des aiguilles d'une montre ou dans le sens contraire des aiguilles d'une montre. En outre, vous devrez peut-être connecter -y au lieu de y, selon que votre système de coordonnées est à l'envers ou non.

En outre, vous pouvez accomplir exactement la même chose dans trois lignes de code en utilisant:

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

Si vous appliquez cela à une vue, vous pouvez également simplement utiliser une transformation de rotation via CGAffineTransformMakeRotation (a), à condition de définir la propriété anchorPoint de la couche de la vue pour refléter le point autour duquel vous souhaitez faire pivoter la rotation. Cependant, il semble que vous ne souhaitiez pas appliquer cela à une vue.

Enfin, si vous appliquez cela à un espace 2D non euclidien, vous ne souhaiterez peut-être pas une transformation affine. Les transformations affines sont des isométries de l'espace euclidien, ce qui signifie qu'elles préservent la distance euclidienne standard, ainsi que les angles. Si votre espace n'est pas euclidien, alors la transformation que vous souhaitez peut ne pas être réellement affine, ou si elle est affine, la matrice de la rotation pourrait ne pas être aussi simple que ce que j'ai écrit ci-dessus avec sin et cos. Par exemple, si vous vous trouviez dans un espace hyperbolique, vous devrez peut-être utiliser les fonctions trigonométriques hyperboliques sinh et cosh, ainsi que différents signes + et - dans la formule.

P.S. Je voulais aussi rappeler à ceux qui lisent jusque-là que "affine" se prononce avec un court "a" comme dans "demander", pas un long "a" comme dans "capable". J'ai même entendu des employés d'Apple mal interpréter cela lors de leurs discussions avec la WWDC.

112
landweber

Pour ceux qui, comme moi, ont du mal à trouver une solution complète pour faire pivoter une image et la redimensionner correctement, afin de remplir le cadre qui le contient, au bout de quelques heures, c’est la solution la plus complète et la plus parfaite que j’ai obtenue.

Le truc ici est de traduire le point de référence avant toute transformation (échelle et rotation). Après cela, vous devez concaténer les deux transformations pour obtenir une transformation affine complète. 

J'ai emballé toute la solution dans une sous-classe de CIFilter que vous pouvez Gist ici .

En suivant la partie de code pertinente:

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

pour 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

Consultez ce lien: Rotation d'un iPhone Visualiser autour d'un point . Cela peut vous aider. Vers le bas de l'article, il y a une section intitulée "Changer le point d'ancrage". C’est probablement ce qui convient le mieux à vos besoins, bien qu’une compensation soit nécessaire pour ne pas décaler la vue.

0
aopsfan