VB.NET2005 TIPS / グラフィックス系 |
G0303 文字の極座標変換 |
最終更新:2006/11/12 再掲 |
●解説
グラフを極座標で描くように文字列を描く。元のXY座標の点をXY平面で表した極座標の点に写像することになる。
楕円での実例
●原理
○変換式
X軸を角度θ、Y軸を距離rに変換する。結果を再び、X-Yで表すと、
X = g(y) * Cos(f(x))
Y = g(y) * Sin(f(x))
となる。g()はyを、f()はxをθにそれぞれマッピングする関数である。
○変換元
文字は描画はできるが、そのままでは演算対象にならない。一番簡単な方法は、描画される文字を点集合にするものである。これには、GraphicPath
オブジェクトを利用する。
●方法
元の関数(ここでは文字列)をGraphicPathにてPoint配列に変換する。従って、任意の図形が対象となる。
1.
オブジェクトをPoint配列にする。
2.
xの範囲を角度の範囲にマッピングする。今全角度をaとすると、
θi = (xi –
xmin) * (a/(xmax-xmin)) + θoffs
3.
yは結果の円の半径Rを考慮して決める。
ri = R + b * yi など。
4.
極座標の原点(円の中心)をXc、Yc、半径をRとし、全角度をaラジアン、また、簡単のためPoint配列(po())の原点が左下とすれば、
θi = (po(i).X –
xmin) * (a/(xmax-xmin)) + θoffs
Xi = (R + po(i).Y) * cos(θi) + Xc
Yi = (R + po(i).Y) * sin(θi) + Yc
文字列をGraphicPath にするには、以下のようにする。
Dim pa As New GraphicsPath()
'空白のパスオブジェクト
pa.Reset()
'念のため空白にしておく
pa.AddString("内容", フォント指定, フォント属性, フォントサイズ, ポイント配列, 描画フォーマット)
'パスに文字列を描画する
pa.CloseFigure()
'描画終了
pa.Flatten
'描画したものを全て直線化する
re = pa.GetBounds
Dim pps() As PointF = pa.PathPoints
‘完全なPoint配列にする
このpps()が演算対象となる。
文字として描くには、このpps を再びパス化する必要がある。
pa = New GraphicsPath(pps, pa.PathTypes)
PathTypes
は、点の性質を記述したバイト配列である。この記述により文字としての集合が明らかになる。
●実例
○例1:円の全周に乗っかった文字列の例
gはGraphics、Xc、Ycは円の中心点とする。
Dim ds As String = "。
円に沿った文字列です" 'スペースを文字とするため、最後尾を先頭にする。
fmt.Alignment = StringAlignment.Near
fmt.LineAlignment = StringAlignment.Near
Dim R As Single = 120
g.DrawEllipse(Pens.Black, New RectangleF(Xc - R, Yc - R, 2 * R, 2 * R))
Dim pa As New GraphicsPath()
Dim re As RectangleF, fh As Single = f.GetHeight(g)
pa.Reset()
pa.AddString(ds, New FontFamily("MS Pゴシック"), CInt(FontStyle.Regular), fh, New
PointF(0, 0), fmt)
pa.CloseFigure()
pa.Flatten
re = pa.GetBounds
Dim pps() As PointF = pa.PathPoints
‘文字列をパス化し、Point配列にする
Dim i As Integer, ra As Double, K As Double = 2 * PI / re.Width
Dim YY As Single
For i = 0 To pps.GetLength(0) - 1
ra = pps(i).X * K + PI
YY = fh - pps(i).Y ‘実際には、文字は半径方向と逆なので反転する。
pps(i).X = (R + YY) * Cos(ra) + Xc
‘円の内側にぶら下がる場合は、(R
–
pps(i).Y)とする
pps(i).Y = (R + YY) * Sin(ra) + Yc
Next
pa = New GraphicsPath(pps, pa.PathTypes)
‘Point配列を再びパス化する。でないと文字として見えない。
g.FillPath(Brushes.Red, pa)
pa.dispose()
○例2:楕円上に乗っかった文字列
例1のRを変更すれば、楕円となる。
pps(i).X = (R
+ YY) * Cos(ra) + Xc
pps(i).Y = (R / 2 + YY) * Sin(ra) + Yc
|