アプリ版:「スタンプのみでお礼する」機能のリリースについて

次のようにボールの位置(x,y)を物理の公式通りにして
Pythonでシミュレーションプログラムを書き、
canvas上にプロットした場合、

①10pixel =何m
10pixel/s=何 m/s

1 m= 何pixel
1 m/s= 何 pixel/s
でしょうか?


②v0 = float(input('初速度を入力してください'))のこの場合の初速度v0の単位は(m/s)でしょうかそれとも(km/s)でしょうか?

※時速30km=30km/h=8.3m/sは確かなので、この値は参考になると思います。


ポイントは
x = x + vx0 * dt
v1 = vy
v2 = vy - g * dt
y = y + (v1+ v2) / 2.0 * dt
vy = v2

WIDTH, HEIGHT = 800, 600

g = 9.8

v0 = float(input('初速度を入力してください'))

vx0 = v0 * math.cos(theta)
vy0 = v0 * math.sin(theta)

のところだと思います。


def move():
global x
global y
global vy
global t
global x1
global y1

if 0 <= x and x <= WIDTH and 0 <= y and y <= HEIGHT:
x = x + vx0 * dt
v1 = vy
v2 = vy - g * dt
y = y + (v1+ v2) / 2.0 * dt
vy = v2
t = t + dt

WIDTH, HEIGHT = 800, 600
MARGIN = 10

t0 = 0.0
dt = 0.1
g = 9.8

v0 = float(input('初速度を入力してください'))
degrees = float(input('角度を入力してください'))

theta = degrees * math.pi / 180
vx0 = v0 * math.cos(theta)
vy0 = v0 * math.sin(theta)
x0 = 10
y0 = 2 * HEIGHT / 4
x1 = 250
y1 = HEIGHT / 2
x = x0
y = y0
vy = vy0
t = t0

質問者からの補足コメント

  • ディスプレイの設定は、解像度1900x1200で、
    画面の拡大縮小はせず100%の場合と考えて教えて頂きたいです。

      補足日時:2023/05/31 10:31
  • ご回答有難うございます。シミュレーション初心者なので重ねて質問させてください。

    ・重力加速度を g= 9.8 m/s^2 →長さはm
    変数x,yをそのままcanvasの座標に使っているので1pixel =1mとなっているのですね?

      補足日時:2023/05/31 12:32
  • ・m,sを使って計算するプログラムを作るとして。
    初速度どんな単位で入力させたにしても、そこからm/sに変換して実行すればいい

    →v0 = float(input('初速度を入力してください'))
    自分でこのように書いたのですが単位を考えていませんでした
    はたして、
    v0 = float(input('初速度(km/h)を入力してください'))
    v0 = float(input('初速度(m/s)を入力してください'))
    のどちらが、現状にふさわしい速度の単位かわかりません。

    km/h単位で入力させたにしても、そこからm/sに変換して実行すればいいということですが、
    変換せずに行うにはm/sで初速度を入力すれば良いでしょうか?

    km/hからm/sに変換するのはkm/hの値に1000/3600をかければ良いのですね?

      補足日時:2023/05/31 12:32
  • ・計算上の座標x,yと、canvas上の座標 xc,yc とを関連付ければということですが、
    関連付けするとは具体的にどのようなコードを書くことでしょうか?

      補足日時:2023/05/31 12:33
  • ・重力加速度を g= 9.8 m/s^2だから長さはm単位
    変数x,yをそのままcanvasの座標に使っているのなら、1pixel =1m
    v0 = float(input('初速度(m/s)を入力してください'))

    これを決めるのが私なら速度はm/sにして10pixelを1mにしたいのですが、
    どの部分でどうコードを書きかえればよいかわかりません、教えて頂けますでしょうか?

    No.2の回答に寄せられた補足コメントです。 補足日時:2023/05/31 17:41
  • ・>1pixel=10m, キャンバスのcx=20を x=0mにしたい、という場合なら
    >cx = 10 * x + 20 拡大縮小率を掛けて平行移動分足します。
    >おそらく、canvasの縦は上が0と数学の座標と逆になっているので、合わせるなら
    >cy = -10 * y + 300
    >等とマイナスを掛ける必要があります。

    縦軸 canvas.create_line(0, i * 10,800, i * 10, fill = '#000000' if i==30 else '#d2d2d2')
    横軸 canvas.create_line(i * 10, 0, i * 10,600, fill = '#000000' if i==1 else '#d2d2d2')
    この目盛り線のx,y座標にcx,cyを代わりに代入してやれば良いということでしょうか?

    No.1の回答に寄せられた補足コメントです。 補足日時:2023/05/31 17:41
  • こういう物理シミュレーションの場合、入出力と計算を分けるとはどういうことでしょうか?
    入出力がどこの部分で、計算がどこの部分でしょうか?

    おそらく計算はここの部分かとおもいますが。
    x = x + vx0 * dt
    v1 = vy
    v2 = vy - g * dt
    y = y + (v1+ v2) / 2.0 * dt
    vy = v2
    t = t + dt

      補足日時:2023/06/02 06:54
  • Canvas座標系での座標変換は、具体的なCanvasの設定に依存する。座標系の原点(0, 0)はCanvasの左上隅に位置し、x軸は右向き、y軸は下向きとなる。
    以下の関係式を使用して、2次元座標系(x, y)をCanvas座標系(X, Y)に変換できる。
    X = x + X_offset
    Y = canvas_height - y - Y_offset
    ここで、X_offsetはCanvas内のx軸のオフセット(水平方向のシフト)を表し、Y_offsetはCanvas内のy軸のオフセット(垂直方向のシフト)を表す。また、canvas_heightはCanvasの高さ。

    具体的なCanvasの設定に合わせて、X_offsetとY_offsetの値を調整する。これにより、2次元座標系(x, y)がCanvas座標系(X, Y)に正しく変換される。
    ということですね。

      補足日時:2023/06/06 16:53
  • Canvasのサイズが(800, 600)で、
    1 pixelが10mを表すようにしたい場合

    def pixel_to_meter(x, y):
    X = 10 * x + 400
    Y = -10 * y + 300
    return X, Y
    この関数は、引数として与えられたxとyの値を使って、ピクセル座標をメートル座標に変換する。
    具体的には、x軸方向の変換では、xを10倍して400を足す。
    y軸方向の変換では、yを10倍して-1をかけ、その後300を足す。

    これにより、(x, y)のピクセル座標が、(X, Y)のメートル座標に変換される。
    つまりこういうことなのですね?

      補足日時:2023/06/06 17:03
  • あ、最後間違ってますね、
    Canvasのサイズが(800, 600)で、
    1 pixelが10mを表すようにしたい場合

    def pixel_to_meter(x, y):
    X = 10 * x + 400
    Y = -10 * y + 300
    return X, Y
    この関数は、引数として与えられたxとyの値を使って、ピクセル座標をメートル座標に変換する。

    これにより、(x, y)のメートル2次元座標が、(X, Y)のCanvas座標に変換される。
    つまりこういうことなのですね?
    勉強になりました有難うございます。

      補足日時:2023/06/07 07:53

A 回答 (4件)

> 補足日時:2023/06/06 17:03



メートルとピクセルが逆では?
    • good
    • 0

○メートルを使った座標とcanvas上の座標のどちらを使う場面なのか、きっちり区別するようにしましょう。



canvasに対して指定するのはcanvas上の座標です。
 canvas.create_line(0, i * 10,800, i * 10, fill = '#000000' if i==30 else '#d2d2d2')
は canvas左上を(0,0)で右下が(正,正)となるpixcel座標で y= (i * 10) pixel の位置に線を引きます。
左下が(0,0)で右上が(正,正)となるメートル座標で y= (i * 10) メートルに引きたいのなら、メートル座標→canvas座標の変換が必要です。
800 も canvas座標のx=800pixelの意味で 800mではありません。

変換は、変換用関数を用意すると便利です。
例)
def xc(x): return 10 * x + 400
def yc(y): return -10 * y + 300
#(0m,( i * 10)m)から(800m, (i * 10)m)に線を引く
 canvas.create_line(xc(0), yc(i * 10),xc(800), yc(i * 10), fill = '#000000' if i==30 else '#d2d2d2')

○ 入力とは、プログラム外からデータ等を受けとることです。
例) キーボード、マウス、ファイル、ネットワーク等
出力とは、プログラム外へデータ等を渡すことです。
例) 画面、ファイル、ネットワーク等

入出力と計算を分ける というのは、入出力は入出力だけ、計算は計算だけで動かせるようにして、互いの関係を必要最小限にするということです。

例えば
x0 = 10
y0 = 2 * HEIGHT / 4
x1 = 250
y1 = HEIGHT / 2
if 0 <= x and x <= WIDTH and 0 <= y and y <= HEIGHT
これらに出てくる 数値やWIDTH,HEIGHTはcanvasのpixelの値だと思われます。
ところが、これらの値がメートルを基準にした計算部分でそのまま使われています。
これは、計算が入出力に依存している状態です。

今回のプログラムなら

キーボードで必要なパラメータを入力(単位は度、m/s)
↓ラジアンに変換
計算
↓メートル座標をPixel座標に変換
画面出力

とすることで、入力と計算を分けることになります。
これができると

ウインドウにあるTextboxでパラメータを入力(単位は度、km/s)
↓ラジアンに変換
計算
↓メートル座標のまま
CSVファイルに出力

といったプログラムも、計算部分を変えることなく作ることができます。


クラス、モジュール、関数といったものを使って、プログラムの機能的に分離することができます。
というか、分離するのが「よいプログラム」です。
    • good
    • 1

> v0 = float(input('初速度(km/h)を入力してください'))


> v0 = float(input('初速度(m/s)を入力してください'))
> のどちらが、現状にふさわしい速度の単位かわかりません。

それを決めるのは、あなたです。(あるいは、あなたにこのプログラムを作るように指示した人です)

Wikipediaの「砲口初速」(大砲の打ち出し速度)の説明では、毎秒m(m/s) で表記されています。
おそらく、他の資料でもm/s表記が多いのでしょう。
これをそのまま入力したいのなら、 ふさわしいのは m/sです。

野球でピッチャーの球速は km/hで表記されます。
自動車の速度はkm/hで表記されます。
投球の軌跡や、ジャンプ台から飛び出した自動車の軌跡といったものをシミュレートしたいのなら、 ふさわしいのはkm/h入力です。

> 変換せずに行うにはm/sで初速度を入力すれば良いでしょうか?

「変換せずに」したいのならそうです。


>・計算上の座標x,yと、canvas上の座標 xc,yc とを関連付ければということですが、
> 関連付けするとは具体的にどのようなコードを書くことでしょうか?

例えば。
1pixel=10m, キャンバスのcx=20を x=0mにしたい、という場合なら
cx = 10 * x + 20
拡大縮小率を掛けて平行移動分足します。
おそらく、canvasの縦は上が0と数学の座標と逆になっているので、合わせるなら
cy = -10 * y + 300
等とマイナスを掛ける必要があります。
この回答への補足あり
    • good
    • 1

・①②のような内容は、「自動で決まる」ものではなく、プログラムの設計段階で「決める」ものです。


・入出力と、計算とは分けて考えましょう。

重力加速度を g= 9.8 m/s^2 としているということは、長さは メートルを使わないと計算が合わなくなります。
※ 地球ではないどこかの星であれば別の単位かもしれませんが。


変数x,yをそのままcanvasの座標に使っているのなら、1pixel =1mになります。


こういうプログラムの場合は、入出力と計算を分けるのが常套手段です。
m,sを使って計算するプログラムを作るとして。
・初速度どんな単位で入力させたにしても、そこからm/sに変換して実行すればいい
・計算上の座標x,yと、canvas上の座標 xc,yc とを関連付ければ、1pixelを何mにするか、とか、どこに原点を持ってくるか、とか、上下左右反転、とかを物理シミュレーション部分に手を加える必要なく変更できます。
この回答への補足あり
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!