単振動のシミュレーション

解決


sayaka2011  2011-02-17 19:00:42  No: 40035

以下は2πを40等分して単振動の様子をシミュレーションさせる関数ですが、これだと当然ながら40個の円が一度に単振動して全体としては最初から正弦曲線を描いてしまいます。最初40個の円はY軸上に配置して、一番最初(x = 0)の円が単振動をはじめたら、それにつづいて次の円が位相の分だけ遅れて単振動をするというようにしたいのですが、どうしたらいいでしょうか?
  
  private
    FOx, FOy: Integer; //原点
    FTm, Fq: Extended; //振動数と時間

//実座標⇒表示座標
function TForm1.RealToDispX(x: Extended): Integer;
begin
  Result := Round(FOx + x * PerX);
end;

function TForm1.RealToDispY(y: Extended): Integer;
begin
  Result := Round(FOy - y * PerY);
end;

//単振動-横波
procedure TForm1.FDrawShm(TargetCanvas: TCanvas);
var
  Ex,Ey,Phi : Extended;
  i: Integer;
begin
  with TargetCanvas do
  begin
    Pen.Width := SubWidth;
    Pen.Color := clGreen;
    Phi := 0; //とりあえず 0≦ x ≦2π
    Ex := 0;
    for i := 0 to 40 do
    begin
      Ey := 3*sin(2*Pi*Fq*FTm+Phi);
      MoveTo( RealToDispX(Ex),RealToDispY(Ey) );
      if i Mod 5 = 0 then Brush.Color := clRed
      else                Brush.Color := clBlack;
      Ellipse( RealToDispX(Ex)-20, RealToDispY(Ey)-20,     //位置を示す円
               RealToDispX(Ex)+20, RealToDispY(Ey)+20 );
      Ex  := Ex + 1;
      Phi := Phi + Pi/20;
    end;
  end;
  FTm := FTm + 0.002;
end;


Kenny  2011-02-17 23:39:26  No: 40036

基本こんな形でどうですか。使うコンポはForm,PaintBox,Timer,Buttonです。
Buttonを押したら最初にy軸並びの○を描いて、それからタイマースタート。
タイマーが動き出したら、タイマーイベントで○を再描画しています。
画面のちらつきとか、スタート/ストップで一旦画面消去するとか、色々やることは
有りますので、そこは頑張ってみてください。

unit Unit1;

interface

uses
 Forms, ExtCtrls, Controls, Classes, StdCtrls, Graphics;
Type
  TForm1 = class(TForm)
    Button1: TButton;
    PaintBox1: TPaintBox;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    FOx, FOy   : Integer;  //原点
    Ex,Ey,Phi  : Extended;
    PerX, PerY : integer;  //表示倍率
    iCount     : integer;
    function RealToDispX(x1: Extended): Integer;
    function RealToDispY(y1: Extended): Integer;
    procedure FDrawShm(x: integer; Phi: Extended);
  public
    { Public 宣言 }
  end;
var
  Form1: TForm1;           

implementation

{$R *.dfm}

function TForm1.RealToDispX(x1: Extended): Integer;
begin
  Result := Round(FOx + x1 * PerX);
end;

function TForm1.RealToDispY(y1: Extended): Integer;
begin
  Result := Round(FOy - y1 * PerY);
end;

procedure TForm1.FDrawShm(x:integer; Phi: Extended);
var y :extended;
begin
  y := sin(Phi-Pi/20);
  with PaintBox1.Canvas do begin
    Brush.Color:=clBtnFace;                            //背景で上書きして
    Pen.Color := clBtnFace;                            //消去の代わり
    MoveTo( RealToDispX(x),RealToDispY(y) );
    Ellipse( RealToDispX(x)-10, RealToDispY(y)-10,
             RealToDispX(x)+10, RealToDispY(y)+10 );
    y := sin(Phi);
    Pen.Color := clGreen;
    if x Mod 5 = 0 then Brush.Color := clRed
    else                Brush.Color := clBlack;
    MoveTo( RealToDispX(x),RealToDispY(y) );
    Ellipse( RealToDispX(x)-10, RealToDispY(y)-10,
             RealToDispX(x)+10, RealToDispY(y)+10 );
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  iCount:= 0;         //初期値の設定
  FOx   := 100;
  FOy   := 200;
  PerX  := 20;
  Pery  := 100;
  Phi   := 0;
  Ex    := 0;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  i: Integer;
begin
  Phi := Phi + Pi/20;
  for i:=0 to iCount do
    FDrawShm(i, Phi-i*(Pi/20));
  if iCount<40 then
    inc(iCount)
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  with PaintBox1.Canvas do begin
    Pen.Color := clGreen;
    for i := 0 to 40 do begin
      Ey := sin(Phi);
      MoveTo( RealToDispX(Ex),RealToDispY(Ey) );
      if i Mod 5 = 0 then Brush.Color := clRed
      else                Brush.Color := clBlack;
        Ellipse( RealToDispX(Ex)-10, RealToDispY(Ey)-10,
               RealToDispX(Ex)+10, RealToDispY(Ey)+10 );
      Ex  := Ex + 1;
    end;
  end;
  Phi := 0;
  Timer1.Enabled:=true;
end;

end.


Kenny  2011-02-18 00:24:44  No: 40037

あ、貼り付けたタイマーコンポはデフォルトでEnabledがtrueになっているので、
インスペクタで初期値=falseにしておいてください。


sayaka2011  2011-02-18 00:41:43  No: 40038

すみません。書き方が悪かったみたいです。単振動のシミュ自体は出来ているのです。もちろんチラツキ対策も裏画面を利用する方法で対応しています。
  http://ichigo-up.com/cgi/up/qqq/nm31346.zip
  上のファイルを見てもらえたらわかるのですが、たとえば横波の場合40個の円が最初から正弦曲線を描いた状態で単振動がスタートします。それを最初は

*  *  *  *  *  *  *  *  *  *  *  *

のようにに一直線上に並べた状態でスタートさせたいということなのです。


Kenny  2011-02-18 01:04:14  No: 40039

>*  *  *  *  *  *  *  *  *  *  *  *
>のようにに一直線上に並べた状態でスタートさせたいということなのです。

私が書いたやつはそうなっていますよ。TimerコンポのEnabledがtrueのままになっていませんか?


sayaka2011  2011-02-18 01:17:06  No: 40040

> 私が書いたやつはそうなっていますよ。TimerコンポのEnabledがtrueのま
> まになっていませんか?
  あ、そうですね。ありがとうございます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加