2011-11-26 12 views
35

Come posso creare una trasformazione affine Core Graphics per la rotazione attorno a un punto x, y di angolo a, utilizzando solo una singola chiamata a CGAffineTransformMake() più le funzioni trigonometriche.ht come sin(), cos(), ecc. e nessun altro CG chiama.Una trasformazione affine in un passaggio per la rotazione attorno a un punto?

Altre risposte qui sembrano riguardare l'utilizzo di più trasformazioni impilate o trasformazioni multi-step per spostare, ruotare e spostare, utilizzando più chiamate Core Graphics. Quelle risposte non soddisfano i miei requisiti specifici.

+2

Perché avete bisogno di una singola chiamata a 'CGAffineTransformMake()'? Le chiamate in pila producono esattamente gli stessi risultati, tranne che lo fanno in un modo leggibile e comprensibile.Se vuoi davvero farlo in una singola chiamata, finirai per replicare la stessa matematica usata nelle chiamate impilate, per non avvantaggiarti. –

+3

Quali requisiti potrebbe essere? È possibile combinare queste trasformazioni "impilate" in un CGAffineTransform utilizzando CGAffineTransformConcat. Il risultato sarà lo stesso delle formule per i singoli componenti e i calcoli coinvolti saranno gli stessi internamente, o eventualmente più ottimizzati nel caso di CGAffineTransformConcat. – morningstar

+0

Desidero che le equazioni di matrice vengano utilizzate su un oggetto di modello corrispondente ma non grafico in uno spazio 2D geometrico diverso (non necessariamente Euclideo). – hotpaw2

risposta

101

Una rotazione di un angolo intorno al punto (x, y) corrisponde alla trasformazione 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)); 

potrebbe essere necessario collegare in -a invece di una seconda se si desidera che la rotazione sia in senso orario o antiorario. Inoltre, potrebbe essere necessario inserire -y anziché y a seconda che il sistema di coordinate sia capovolto o meno.

Inoltre, è possibile eseguire esattamente la stessa cosa in tre righe di codice utilizzando:

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

Se si dovesse applicando questo per una vista, si potrebbe anche usare semplicemente una rotazione trasformare tramite CGAffineTransformMakeRotation (a), a condizione di impostare la proprietà anchorPoint del livello della vista per riflettere il punto che si desidera ruotare. Tuttavia, sembra che tu non sia interessato ad applicarlo a una vista.

Infine, se lo si applica a uno spazio 2D non Euclideo, è possibile che non si desideri affatto una trasformazione affine. Le trasformazioni affini sono isometrie dello spazio euclideo, nel senso che conservano la distanza euclidea standard, nonché gli angoli. Se il tuo spazio non è euclideo, allora la trasformazione che desideri potrebbe non essere effettivamente affine, o se è affine, la matrice per la rotazione potrebbe non essere semplice come quello che ho scritto sopra con peccato e cos. Ad esempio, se ti trovi in ​​uno spazio iperbolico, potresti dover utilizzare le funzioni trigonometriche iperboliche sinh e cosh, insieme a diversi segni + e - nella formula.

P.S. Volevo anche ricordare a chiunque abbia letto fino a questo punto che "affine" è pronunciato con un breve "a" come in "ask", non un lungo "a" come in "able". Ho persino sentito i dipendenti di Apple mal pronunciarlo nei loro discorsi sul WWDC.

+1

Che cos'è esattamente 'a'? – jjxtra

+1

'a' è l'angolo in radianti sembra – Curtis

+2

Se hai intenzione di dare suggerimenti sulla pronuncia, allora dovresti anche specificare se è -fine come in "fine" o -fine come in "feen". Ma forse sono l'unico a sbagliare quella parte. : -/ –

1

Dai un'occhiata a questo link: Rotating an iPhone View Around a Point. Potrebbe aiutarti. Verso la fine dell'articolo, c'è una sezione intitolata "Cambia il punto di ancoraggio". Questo è probabilmente più adatto alle tue esigenze, sebbene ci sia un certo risarcimento che deve essere fatto per non compensare la vista.

2

Per quelli come me, che stanno lottando alla ricerca di una soluzione completa per ruotare un'immagine e adattarla correttamente, per riempire il frame contenente, dopo un paio d'ore questa è la soluzione più completa e perfetta che io ho ottenuto.

Il trucco qui è di tradurre il punto di riferimento, prima di qualsiasi trasformazione coinvolta (sia in scala che in rotazione). Dopodiché, devi concatenare le due trasformazioni per ottenere una trasformazione affine completa.

Ho imballato l'intera soluzione in una sottoclasse CIFilter che è possibile gist here.

seguito la parte rilevante di codice:

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