Impossible avec CGAffineTransform. Une transformation affine peut toujours être décomposée en translations, rotations, cisaillement et mise à l'échelle. Ils cartographient tous des parallélogrammes en parallélogrammes, ce que votre transformatrice ne fait pas.
Pour votre transformation, cela peut se faire en deux étapes. Un pour convertir le carré en trapèze.
p1-----p2 p1-----p2
| | --> | \
p3-----p4 p3--------p4'
Un autre à la direction verticale. Une règle de transformation est naïve
y - c
x' = (x - p1.x) * ———————— + p1.x
p1.y - c
y' = y
où c est la coordonnée y du point d'intersection des lignes de jonction P1 et P3 et P2 et P4.
Notez maintenant le facteur x * y dans la transformation. Cela indique qu'une telle transformation est et non linéaire. Par conséquent, CATransform3D ne peut pas effectuer cela comme une transformation 2D non plus.
Cependant, le vecteur
[x, y, z, w=1]
seront converties au vecteur 3D réelle
(x/w, y/w, z/w)
avant la projection si CA suit les règles habituelles graphiques de calcul 3D, de sorte que vous pouvez « tricher » en utilisant le transformer
[ P . . Q ] [ x ] [ x' ]
[ . R . S ] [ y ] = [ y' ]
[ . . 1 . ] [ z ] [ z' ]
[ . T . U ] [ 1 ] [ w' ]
avec P approprié, Q, R, S, T, U qui mappe les 4 points aux endroits prévus. (6 coordonnées uniques et 6 variables doivent avoir exactement 1 solution dans la plupart des cas.)
Lorsque vous avez trouvé ces 6 constantes, vous pouvez créer un CATransform3D. Notez la définition de la structure est
struct CATransform3D
{
CGFloat m11, m12, m13, m14;
CGFloat m21, m22, m23, m24;
CGFloat m31, m32, m33, m34;
CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;
vous pouvez donc modifier directement les éléments de la matrice, au lieu de compter sur les fonctions de CATransform3DMake. (Vous devrez peut-être effectuer une transposition en raison de la convention d'utilisation de vecteurs de ligne ou de colonne.)
Pour obtenir la transformée de convertir un rectangle ((X, Y), (W, H)) à un quadrilatère ((X1A, Y1A), (X2A, Y2A); (X3A, Y3a) (X4a, Y4a)), utilisez cette fonction (vous devrez peut-être une transposition):
function compute_transform_matrix(X, Y, W, H, x1a, y1a, x2a, y2a, x3a, y3a, x4a, y4a) {
var y21 = y2a - y1a,
y32 = y3a - y2a,
y43 = y4a - y3a,
y14 = y1a - y4a,
y31 = y3a - y1a,
y42 = y4a - y2a;
var a = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42);
var b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43);
var c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43);
var d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a);
var e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42);
var f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a)));
var g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43);
var h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42);
var i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a));
return [[a,b,0,c],[d,e,0,f],[0,0,1,0],[g,h,0,i]];
}
Voici une autre façon d'y parvenir: http://stackoverflow.com/questions/9470493/transforming-a-rectangle-image-into- a-quadrilateral-using-a-catransform3d Faites-moi savoir si cela vous aide. – MonsieurDart
Pour 2016: grâce à tous les éléments de base ici: voici une solution rapide Swift http://stackoverflow.com/a/39981054/294884 – Fattie