Python の SymPy Plotting Backends を使って,パラメータを変えて複数の曲線を一気にグラフにする例。グラフを描く際のオプションの設定についても2通りの例をまとめた。
例:斜方投射
簡単のために(初速度 $v_0 \rightarrow 1$, 重力加速度 $g \rightarrow 1$ などとして)適宜無次元化した解は,以下のように時間 $t$ と投射角度 $\theta$ の関数となる。
\begin{eqnarray}
x(t, \theta) &=& t \cos\theta \\
y(t, \theta) &=& t \sin\theta -\frac{1}{2} t^2
\end{eqnarray}
$t=0$ で地上 $y=0$ から投射された物体がふたたび地上に落ちるまでの滞空時間 $t_d$ は
$$t_d(\theta) = 2 \sin\theta$$
必要なモジュールの import
必要なモジュールを import します。
from sympy.abc import *
from sympy import *
# SymPy Plotting Backends (SPB)
from spb import *
# グラフを SVG で Notebook にインライン表示
%config InlineBackend.figure_formats = ['svg']
関数の定義
# 角度 th は度で
def x(t, th):
theta = th * pi/180
return t*cos(theta)
def y(t, th):
theta = th * pi/180
return t*sin(theta) - t**2/2
def td(th):
theta = th * pi/180
return 2*sin(theta)
軌道のグラフ
SPB で媒介変数表示のグラフを描くには,
plot_parametric(x(t), y(t), (t, tmin, tmax))
デフォルトで use_cm = True
になっているので,カラーマップが不要なら False
に。
とりあえず 1 本の軌道を描く
$\theta = 45^{\circ}$ での斜方投射の軌道をグラフにしてみる。
まずは,とりあえずのグラフ:
# θ = 45° のグラフ
th = 45
plot_parametric(
x(t, th), y(t, th), (t, 0, td(th)), use_cm=False);
オプション設定例
以下のようなオプションを設定して,もう少し体裁を整えます。
- $\theta$ の値を凡例に
- 座標軸のラベルとグラフのタイトル
- 横軸縦軸の表示範囲
- 縦軸横軸のアスペクト比
- (座標軸の目盛の間隔… )
ここでは,plot_parametric()
の中でオプションを設定しています。
# θ = 45° のグラフ
th = 45
plot_parametric(
x(t, th), y(t, th), (t, 0, td(th)), 'θ = %2d°' % th,
legend = True,
use_cm = False,
xlabel = "X", ylabel = "Y", title = "斜方投射",
xlim = (0, 1.1), ylim = (0, 0.5),
aspect = "equal");
2 本の軌道を描く
$\theta = 30^{\circ}$ と $\theta = 45^{\circ}$ の2本のグラフを描く例。
plot_parametric(
(x(t, 45), y(t, 45), (t, 0, td(45)), 'θ = %2d°' % 45),
(x(t, 30), y(t, 30), (t, 0, td(30)), 'θ = %2d°' % 30),
legend = True,
use_cm = False,
xlabel = "X", ylabel = "Y", title = "斜方投射",
xlim = (0, 1.1), ylim = (0, 0.5),
aspect = "equal");
2 本の軌道を描く別の例
$\theta = 30^{\circ}$ と $\theta = 45^{\circ}$ の2本のグラフを描くもう一つの方法。
p1
,p2
として別々に描いたグラフを
p = p1 + p2
p.show()
として重ねて表示させます。
th = 45
p1 = plot_parametric(
(x(t, th), y(t, th), (t, 0, td(th)), 'θ = %2d°' % th),
xlabel = "X", ylabel = "Y", title = "斜方投射",
xlim = (0, 1.1), ylim = (0, 0.5),
use_cm = False, aspect = "equal", show = False)
th = 30
p2 = plot_parametric(
(x(t, th), y(t, th), (t, 0, td(th)), 'θ = %2d°' % th),
use_cm = False, show = False)
p = p1 + p2
p.show()
オプション設定の別の例
ここでは,ax
を設定して,より細かなオプション設定を行ってみます。いったん ax
を設定してしまえば,バックエンドの Matplotlib と同じ方法でオプション設定ができます。
SymPy Plotting Backends の関数である plot_parametric()
の引数として設定できないオプションも,ax.___
で細かな設定が可能です。
th = 45
p1 = plot_parametric(
(x(t, th), y(t, th), (t, 0, td(th)), 'θ = %2d°' % th),
use_cm = False, show = False)
th = 30
p2 = plot_parametric(
(x(t, th), y(t, th), (t, 0, td(th)), 'θ = %2d°' % th),
use_cm = False, show = False)
p = p1 + p2
fig, ax = p.fig, p.ax
# グラフのサイズが微妙に小さくなるのを防ぐ
fig.tight_layout()
# いったん ax を定義すればより細かなオプション設定が可能
ax.set_aspect('equal')
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 0.5)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_title("斜方投射")
# グリッドを dotted で
ax.grid(linestyle = 'dotted')
# x の目盛を 0.1 刻みに
ax.set_xticks([0.1*i for i in range(11)])
# y の目盛を 0.1 刻みに
ax.set_yticks([0.1*i for i in range(6)])
ax.legend();
複数の軌道を一度に描く
$\theta$ の値を $30^{\circ}$ から $60^{\circ}$ まで $5^{\circ}$ 刻みで変えて,複数の曲線を一度に描く例。
thl = [th for th in range(60,29,-5)]
plots = [plot_parametric(
x(t, th), y(t, th), (t, 0, td(th)), 'θ = %2d°' % th,
use_cm = False, show = False)
for th in thl]
p = sum(plots)
fig, ax = p.fig, p.ax
# グラフのサイズが微妙に小さくなるのを防ぐ
fig.tight_layout()
ax.set_aspect('equal')
ax.set_xlim(0, 1.1)
ax.set_ylim(0, 0.5)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_title("斜方投射")
# グリッドを dotted で
ax.grid(linestyle = 'dotted')
# x の目盛を 0.1 刻みに
ax.set_xticks([0.1*i for i in range(11)])
# y の目盛を 0.1 刻みに
ax.set_yticks([0.1*i for i in range(6)])
ax.legend();