この前のサンプルhelloCTMを動かすと

CGContextRotateCTM

による回転は、ある一定の位置から何度回転するというものではなく、現状にどんどん加算するタイプだってのがわかると思う。
 今回は、この変形をもうちょっとわかりやすく確認するために文字列じゃなく三角形を使ってみる。三角形を描くには、例によってサンプルソースのQuartzDemoやCGContextRefのReferenceを調べることで

CGContextStrokePath

てのを使えばいいことがわかる。リファレンス読む(iPhoneアプリ開発、その(33)を参照)と「CGContextに設定されている現在の形状パスを描画し、現在の形状パスはクリアする。」とある。で、サンプルソースではこのCGContextStrokePathの前に

CGContextMoveToPoint
CGContextAddLineToPoint

で形状パスを定義してるっぽい。これも同じようにリファレンスからCGContextMoveToPointは新しい形状パスの開始位置になり、CGContextAddLineToPointによって次の点を指定することで、2点間を結ぶ直線で形状パスを定義することになるらしいことがわかる。以下のサンプル
------------
サンプルプロジェクト:helloCTM-2.zip
では

static void drawTriangle(CGContextRef context)
{
CGContextMoveToPoint(context, 0.0, 0.0);
CGContextAddLineToPoint(context, 100.0, 0.0);
CGContextAddLineToPoint(context, 100.0, 100.0);
CGContextClosePath(context);
CGContextStrokePath(context);
}

としてるので、CGContextClosePathを省略するとどうなるかとか、CGContextMoveToPointを省略するとどうなるかとか確認してみるといいです。

テン・シー・シー-fig.1

 直線とわざわざ断っているのは、曲線も描けるからで、これにはAdobe Illustratorでおなじみの2つのコントロールポイントを持つベジェ曲線が定義できるようになってます。

CGContextAddQuadCurveToPoint
CGContextAddCurveToPoint

とかなんだけど、これはまたいずれ。
 今回は単純な三角形をCTMで変形させる実験をします。真っ黒の線もちょっと寂しいのでちょっと色づけしてる。

[[UIColor colorWithHue:0.0 saturation:1.0 brightness:1.0 alpha:0.5] set];

 こいつは、色相、彩度、照度でこれから描画する線の色を指定してて、最後の0.5はアルファ濃度。今回は重なりが透けるように50%に指定。色相、彩度、照度がわからない人は↓のサイトを読むといい。

HSB配色の基礎

 ま、とりあえず、平行移動3回だとどうなるか?

for (int i = 0; i < 3; i++) {
drawTriangle(context);
CGContextTranslateCTM(context, 50.0,50.0);
}

テン・シー・シー-fig.2
こんな感じ。15度ずつの回転移動3回だとどうなるか?

for (int i = 0; i < 3; i++) {
drawTriangle(context);
CGContextRotateCTM(context, 15.0 / 360.0 * (M_PI * 2.0));
}

テン・シー・シー-fig.3
てな感じですわ。

 じゃ~、移動して回転と、回転して移動だとどうなるんでしょか?
 「iPhoneアプリ開発、その(64)」で、CGContextTranslateCTM→ CGContextRotateCTMの順に書くと回転→移動の指定になるって書いたけど、実はこれが大間違いだった。変形のたびに原点とX,Y軸も変形するんだよ。
 なので

【移動して回転】

for (int i = 0; i < 3; i++) {
drawTriangle(context);
CGContextTranslateCTM(context, 50.0,50.0);
CGContextRotateCTM(context, 15.0 / 360.0 * (M_PI * 2.0));
}

テン・シー・シー

これは、以下のようなステップで変形してたわけですわ。
最初の変形
テン・シー・シー-fig.4 b
次の変形
テン・シー・シー-fig.4 c

【回転して移動】

for (int i = 0; i < 3; i++) {
drawTriangle(context);
CGContextRotateCTM(context, 15.0 / 360.0 * (M_PI * 2.0));
CGContextTranslateCTM(context, 50.0,50.0);
}

テン・シー・シー-fig.5

の方は
最初の変形
テン・シー・シー-fig.5 b
次の変形
テン・シー・シー-fig.5 c
というわけ。

 ぜんぜん、書いた順にちゃんと変形されてんじゃん。納得。この前のも最初のスケーリングで3対1の変形した座標系での回転や平行移動を考えないと駄目だったわけやね。アフィン変換恐るべし。
 ま、いろいろ試してみてください。

------------
サンプルプロジェクト:helloCTM-3.zip