C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: GDI+で文字の縮小拡大+回転


(過去ログ 10 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■2102 / inTopicNo.1)  GDI+で文字の縮小拡大+回転
  
□投稿者/ セイン (10回)-(2007/03/19(Mon) 10:26:11)

分類:[C/C++] 

いつもお世話になっています。
C++ .NET で開発しております。

GDI+で文字の縮小拡大+回転をしようとしましたが、
両方共同時にしようとすると、正しく表示されません。
求める動作は、横幅の広い文字や細い文字を表示することです。
下記サイトの一番下の表示方法を参考にしました。

http://park17.wakwak.com/~dragoon/gdiplus7.htm



float XScale = 0.5; //Xスケール(0.5はスリム文字 1.5は幅広文字)
float YScale = 1.0; //Yスケール
Matrix mx;

for( int i=0; i<=180; i+=45 )
{
mx.Scale(XScale, YScale);//スケール適応
mx.RotateAt( (REAL)i, origin );
graphics.SetTransform( &mx );
SolidBrush brush( Color(255-i, 0,0,0) );
graphics.DrawString( pStr, -1, &myFont, origin, &format, &brush );
}


上記を動かすと、90度に回転した図は、Y方向にスリム文字になってしまっています。(45度では斜体のような表示)


別手段として、↓の方法も考えましたが、origin2の座標の補正の計算式が思い浮かびません。
下記は0度90度180度のときの補正位置をベタで書いてみています。
この方法で行く場合は、計算式どのようになるのでしょうか?

float XScale = 0.5; //Xスケール(0.5はスリム文字 1.5は幅広文字)
float YScale = 1.0; //Yスケール
Matrix mx;

for( int i=0; i<=180; i+=45 )
{
PointF origin2(origin);

//計算
if( i == 0 ) {
origin2.X = origin.X / 0.5f;
origin2.Y = origin.Y / 1.0f;
}
if( i == 90 ) {
origin2.X = origin.X;
origin2.Y = origin.Y + (origin.Y*0.5f);
}
if( i == 180 ) {
origin2.X = origin.X / 1.5f;
origin2.Y = origin.Y / 1.0f;
}

mx.RotateAt( (REAL)i, origin2);

graphics.SetTransform( &mx );
graphics.ScaleTransform(XScale, YScale);
}


上記2種類以外にも、こんな方法を使えば、回転+縮小拡大の文字が扱えるよという方法ございましたら
ご教授願います。
よろしくお願いいたします。
引用返信 編集キー/
■2108 / inTopicNo.2)  Re[1]: GDI+で文字の縮小拡大+回転
□投稿者/ オノデラ (9回)-(2007/03/19(Mon) 12:32:30)
ぱっと見ただけで試していないのですが、単にループごとに mx を初期化していないだけではないでしょうか?
引用返信 編集キー/
■2109 / inTopicNo.3)  Re[2]: GDI+で文字の縮小拡大+回転
□投稿者/ セイン (12回)-(2007/03/19(Mon) 13:02:00)
No2108 (オノデラ さん) に返信
> ぱっと見ただけで試していないのですが、単にループごとに mx を初期化していないだけではないでしょうか?

ループの中で
float XScale
float YScale
Matrix mx

宣言してみましたが、同じでした。
求める動作になりません。
引き続きお願いいたします。
引用返信 編集キー/
■2128 / inTopicNo.4)  Re[3]: GDI+で文字の縮小拡大+回転
□投稿者/ オノデラ (10回)-(2007/03/19(Mon) 23:22:04)
オノデラ さんの Web サイト
2007/03/19(Mon) 23:29:14 編集(投稿者)

 すいません。テストできる環境にいなかったので返信が遅れました。

 リンク先にも書いてあるとおり、Matrix は「行列」を使った計算になります。

 例えばスカラー式「A・B」は「B・A」と等しいですが(A・B=B・A)、行列式の「A×B」は「B×A」と等しくなりません(A×B≠B×A)。(高校数学ですね(^_^))

 で、何が言いたいかというと、「Matrix.Scale」や「Matrix.RotateAt」メソッドは上記の行列式を内部で行っています。「拡大してから回転」するのと「回転してから拡大」するのでは最終的な表示結果が異なってきます。

 セインさんが行いたいのは「拡大してから回転」になるので、セインさんの書いた処理で正しいように見えますが、実は「Matrix.Scale」などのメソッドはデフォルトでは「前掛け」の計算になってしまいます。

 どういうことかというと、Matrix.Scale、Matrix.RotateAt の順番で処理しても「結果=回転×拡大」となってしまうのです。

 これを解決するには、単純に処理の順番を反対にする方法もありますし、Matrix.Scale メソッドとMatrix.RotateAt の第3引数に「MatrixOrder」を指定して掛ける順番を指定できるので、そこを「MatrixOrder::Append」として指定してください。

//-----------------------------------------------------//
float XScale = 0.5; //Xスケール(0.5はスリム文字 1.5は幅広文字)
float YScale = 1.0; //Yスケール

for( int i=0; i<=180; i+=45 )
{
Matrix mx;
mx.Scale(XScale, YScale, MatrixOrder::Append );//スケール適応
mx.RotateAt( (REAL)i, origin, MatrixOrder::Append );
graphics.SetTransform( &mx );
SolidBrush brush( Color(255-i, 0,0,0) );
graphics.DrawString( pStr, -1, &myFont, origin, &format, &brush );
} // これであってるかな?
//-----------------------------------------------------//

※余談ですが、Graphics::DrawString の point 引数を使用すると、「結果=移動×拡大×回転」になることに注意してください。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -