2011-11-26 4 views
35

CGAffineTransformMake()とsin()、cos()などのmath.h trig関数の1回の呼び出しだけを使用して、角度aの点x、yを中心に回転するCore Graphicsアフィン変換を行うにはどうすればよいですか?他のCGコールはありません。ポイントを中心に回転するための1ステップアフィン変換?

他の回答は、複数のCore Graphics呼び出しを使用して、複数のスタックトランスフォームまたはマルチステップトランスフォームを使用して移動、回転、移動することです。これらの回答は私の特定の要件を満たしていません。

+2

を?積み重ねられた呼び出しは、読み込み可能で意味がある方法を除いて、まったく同じ結果を生成します。あなたが本当に一回の呼び出しでそれをしたいのであれば、スタックされた呼び出しで使用されたのと同じ数学を複製することになります。 –

+3

どのような要件がありますか? CGAffineTransformConcatを使用して、これらの「積み重ねた」変換を1つのCGAffineTransformに組み合わせることができます。結果は個々のコンポーネントの数式と同じになり、関係する計算は内部的に同じになります。あるいはCGAffineTransformConcatの場合にはさらに最適化されます。 – morningstar

+0

私は行列方程式が、異なる(必ずしもユークリッドではない)幾何学的2D空間で一致するが非グラフィックスモデルオブジェクトに使用されることを望む。 – hotpaw2

答えて

101

点の周りに角度αの回転(x、y)はアフィン変換に対応する:

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

代わりに使用すると、回転するかどうかに応じての-aをプラグインする必要があるかもしれません時計回りまたは反時計回り。また、座標系が上下逆になっているかどうかによって、yの代わりに-yを差し込む必要があります。ビューにこれを適用した場合、あなたはまた、単に(A)CGAffineTransformMakeRotationを経由して変換の回転を使用することができます

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

を、:

また、あなたが使用して3行のコードで正確に同じことを達成することができますビューのレイヤーのanchorPointプロパティを設定して、回転させたいポイントを反映させる必要があります。しかし、これをビューに適用することに興味がないような音です。

最後に、これを非ユークリッドの2D空間に適用する場合、アファイン変換はまったく必要ないかもしれません。アフィン変換は、ユークリッド空間の等尺性であり、標準的なユークリッド距離と角度を保存することを意味します。あなたの空間がユークリッドでないなら、あなたが望む変換は実際にはアファインではないかもしれません。アファインであれば、ローテーションの行列は、私がsinとcosで上に書いたものほど単純ではないかもしれません。たとえば、双曲線の空間にいた場合は、双曲線三角関数sinhとcoshと、式の異なる+と - の記号を使用する必要があります。

P.S.私はまた、「アフィーネ」が「有能」のような長い「a」ではなく「ask」のような短い「a」で発音されることを、これまでに読んだ人に思い出させたい。 Appleの社員がWWDCの会合でそれを誤って発音していると聞いています。

+1

「a」とは何ですか? – jjxtra

+1

'a'はラジアンの角度で表示されます – Curtis

+2

発音のヒントを表示する場合は、 "fine"のように-fineか "feen"のように-fineかを指定する必要があります。しかし、おそらく私はその部分を間違ってしまう唯一の人です。 : -/ –

1

Rotating an iPhone View Around a Pointを参照してください。それはあなたを助けるかもしれません。記事の一番下には、「アンカーポイントを変更する」というセクションがあります。これはおそらくあなたのニーズに最も適していますが、ビューを相殺しないためには何らかの補償が必要です。

2

私のような人にとっては、画像を回転して適切に拡大する完全なソリューションを探しているうちに、枠を埋めるために苦労しています。これは数時間後に私が最も完全で完璧な解決策です得た。

ここでのトリックは、任意の移動情報(スケールと回転の両方)が発生する前に、基準点を平行移動することです。その後、完全なアフィン変換を得るために2つの変換を連結する必要があります。

私はすべてのソリューションをgist hereというCIFilterサブクラスにパックしました。

コードの関連部分に続いて:あなたは `CGAffineTransformMake()`への単一の呼び出しが必要なのはなぜ

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