Excel
VBA

VBAで楕円の円弧を描画

More than 1 year has passed since last update.

ExcelのVBAで作図する際に、楕円の円弧のパラメーターをどう設定すればいいのかよく忘れてしまうので、ここにまとめておく。

正しく設定できれば、3Dっぽい図も自信を持って描ける。

sphere.png

ポイント

  • Excelの座標は左手系
    • x軸は右向きが正、y軸は下向きが正
    • その結果、角度は時計回りが正
  • オブジェクト作成時に指定する座標値は、楕円弧の右上1/4についての値
    • 作成後は弧の範囲によって変化
  • 楕円弧の両端を表す角度は、楕円中心から見た角度
    • 初期値(右上1/4)は、-90° から 0° までの時計回り
    • 図形を伸縮したときに、異なる変形をしたような違和感

基本的な描き方

Shapes.AddShape メソッドを使い、種類には msoShapeArc を指定すると、楕円弧の右上1/4を描ける。座標値には開始点(左上)の位置と幅・高さを指定する。
描き終わったら Shape.Adjustments プロパティの値を書き換え、弧の開始と終了の角度を指定する。これはGUIで黄色いハンドルを操作するのと同じ。

Sub DrawEllipticArc(left, top, width, height)
    Set shp = ActiveSheet.Shapes.AddShape(msoShapeArc, left, top, width, height)

    ' 以下は楕円弧の描画範囲を変更する。デフォルトは-90°~0°
    With shp.Adjustments
        .Item(1) = -90
        .Item(2) = 0
    End With
End Sub

ellipse_1.png

Excelの座標はディスプレイと同様で、左上が(0,0)で、x軸は右向きが正、y軸は下向きが正になっている。角度はx軸正方向を基準にしてy軸正方向に回ると増えていく。そのため弧の右上1/4というのは-90°~0°ということになる。

AddShape に指定した座標値はあくまで弧の右上1/4を描く段階のもので、作成した図形の座標値は弧の描画範囲によって変化する。試した感じだと、GUIが囲む領域(楕円全体)とは一致せず、弧と中心をちょうど含む矩形領域としての値に見える。

指定値を変更して描画

個人的には開始点の位置よりも楕円の中心を指定できると嬉しい。また、幅や高さにマイナスを指定するとエラーとなるが、図形を反転させてくれれば都合がいいこともある。これらに対応させると以下のコードになる。

' (x0,y0)を中心とした半径rx,ryの楕円弧を描く
Sub DrawEllipticArc(x0, y0, rx, ry)
    ra = Abs(rx)
    rb = Abs(ry)
    Set shp = ActiveSheet.Shapes.AddShape(msoShapeArc, x0, y0 - rb, ra, rb)
    If rx < 0 Then shp.Flip msoFlipHorizontal
    If ry < 0 Then shp.Flip msoFlipVertical

    ' 以下は楕円弧の描画範囲を変更する。デフォルトは-90°~0°
    With shp.Adjustments
        .Item(1) = -90
        .Item(2) = 0
    End With
End Sub

ellipse_2.png

(参考)楕円/弦/パイなどの場合

楕円形を描く一般的な図形では、AddShape に指定する座標値が楕円全体に対する値である。そのため幅や高さは楕円の半径の2倍となる。

' (x0,y0)を中心とした半径rx,ryのパイを描く
Sub DrawPie(x0, y0, rx, ry)
    ra = Abs(rx)
    rb = Abs(ry)
    Set shp = ActiveSheet.Shapes.AddShape(msoShapePie, x0 - ra, y0 - rb, ra * 2, rb * 2)
    If rx < 0 Then shp.Flip msoFlipHorizontal
    If ry < 0 Then shp.Flip msoFlipVertical

    ' 以下はパイの描画範囲を変更する。デフォルトは0°~270°(=-90°)
    With shp.Adjustments
        .Item(1) = 0
        .Item(2) = 270
    End With
End Sub

pie_1.png

これらの図形は楕円弧と異なり、描画範囲の角度をどう変更したとしても楕円全体でみた座標値が使われ続けるらしい。

楕円弧を伸縮

図形は幅や高さを変更することにより伸縮できる。しかし楕円弧などに対しては、この操作は恐らく直感に合わない変形を起こしてしまう。

例えば、真円の-60°~+30°部分を描いた図形を縦に潰してみる。下の絵で左側の変形が起きることを期待すると思うが、実際は右側のようになる。

scaling_arc.png

Excelの場合、楕円弧上での角度は楕円の中心から見た角度を表す。右側(現実)の伸縮の様子をよく見てみると、楕円の中心から見た角度は変わっていないことが分かる(弧を「塗り潰し」しておくと分かりやすい)。逆に左側(理想)の伸縮をするにはこの角度を計算し直さなければならない。

' 楕円弧arcを横にsx倍・縦にsy倍の倍率で伸縮する
Sub ScaleArc(arc, sx, sy)
    arc.ScaleWidth  sx, msoFalse, msoScaleFromMiddle
    arc.ScaleHeight sy, msoFalse, msoScaleFromMiddle
    With arc.Adjustments
        .Item(1) = ConvertArcAngle(.Item(1), sx, sy)
        .Item(2) = ConvertArcAngle(.Item(2), sx, sy)
    End With
End Sub

Function ConvertArcAngle(psi, sx, sy)
    psi1 = WorksheetFunction.Radians(psi)
    psi2 = WorksheetFunction.Atan2(sx * Cos(psi1), sy * Sin(psi1))
    ConvertArcAngle = WorksheetFunction.Degrees(psi2)
End Function