リサジュー図形

 リサジュー図形は、図形のx軸y軸に、それぞれ単振動の値を入力して得られる図形です。

x=Acos(αt),y=Bsin(βt+δ)

 プログラムは、正弦波と三角波になっていますが、他の波形でも、それなりの図形が得られます。
プログラム上のX係数、Y係数は単振動x=Acos(αt),y=Bsin(βt+δ)のαとβの値を表しています、又、cos、sinの関係は単に位相が90度に成っているだけなので、δの値により同じ図形が得られます。
A及びBの値は1に固定です、δの値は、動画として表示している間に少しずつ 0~2π の間で変化します。
αとβの入力(X,Y)は、整数入力になっており、作図される図形は最小公倍数の値として表示されるので、4,6は2,3と同じです。

プログラム

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    LabeledEdit1: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    Button2: TButton;
    Timer1: TTimer;
    RadioGroup1: TRadioGroup;
    RadioGroup2: TRadioGroup;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    procedure ImgeClear;
    procedure xyPlot_Line(xd, yd : double; MF: boolean);
    function input(var bcos, bsin: integer) : boolean;
    function triangle_wave(t, qt, ft: integer): double;
    procedure Lissajous_curve(bcos, bsin, Q: integer);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// イメージクリア
procedure TForm1.ImgeClear;
var
  Rect : TRect;
begin
  Rect.Top := 0;
  Rect.Left := 0;
  Rect.Right := image1.Width;
  Rect.Bottom := image1.Height;
  image1.Canvas.Brush.Color := clWhite;
  image1.Canvas.Brush.Style := bsSolid;
  Image1.Canvas.FillRect(Rect);
end;

// xd, yd  x, y座標
// MF  true Lineto false  moveto
procedure TForm1.xyPlot_Line(xd, yd : double; MF: boolean);
var
  x, y: integer;
  xc, yc: integer;
  ps: double;
begin
  xc := image1.Width div 2;
  yc := image1.Height div 2;
  if xc < yc then ps := xc / 1.5 else ps := yc / 1.5;
  x := round(xd * ps) + xc;
  y := yc - round(yd * ps);
  if MF then image1.Canvas.LineTo(x, y)
        else image1.Canvas.MoveTo(x, y);
end;

// 三角波発生
// t 位置
// qt  ピーク位置
// ft  一周期長さ
// result  -1~+1
function TForm1.triangle_wave(t, qt, ft: integer): double;
var
  n : integer;
begin
  result := 0;
  t := t mod ft;
  n := t div qt;
  case n of
    0 : result := t / qt;
    1 : result := (qt + qt - t) / qt;
    2 : result := - (t - qt - qt) / qt;
    3 : result := - (qt + qt + qt + qt - t) / qt
  end;
end;

const
  Period = 720;            // 周期

var
  bcos, bsin, Q: integer;  // bcos x軸波形数  bsin y軸波形数
                           // Q 周期に対する位相

// bcos, bsin  角度倍数(作図時サイクル数)
// Q  sin側位相角
procedure TForm1.Lissajous_curve(bcos, bsin, Q: integer);
var
  i, qt : integer;
  x, y, t, dt, sq :double;
begin
  ImgeClear;
  qt := Period div 4;
  dt := pi / Period * 2;
  sq := pi / 180 * Q;      // 位相角 rad
  x := 0;
  y := 0;
  // 始点移動
  case radiogroup1.ItemIndex of
    0: x := cos(0);
    1: x := triangle_wave(0, qt, Period);
  end;
  case radiogroup2.ItemIndex of
    0: y := sin(sq);
    1: y := triangle_wave(Q, qt, Period);
  end;
  xyPlot_Line(x, y, false);
  // 一周期作図
  for i := 1 to Period do begin
    t := dt * i;
    case radiogroup1.ItemIndex of
      0: x := cos(bcos * t);
      1: x := triangle_wave(bcos * i, qt, Period);
    end;
    case radiogroup2.ItemIndex of
      0: y := sin(bsin * t + sq);
      1: y := triangle_wave(bsin * i + Q, qt, Period);
    end;
    xyPlot_Line(x, y, true);
  end;
end;

// タイマーループ
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Lissajous_curve(bcos, bsin, Q);
  inc(Q);
  if Q >= Period then Q := 0;
end;

// 入力処理
function TForm1.input(var bcos, bsin: integer) : boolean;
var
  ch : integer;
begin
  result := false;
  val(labelededit1.Text, bcos, ch);
  if ch <> 0 then begin
    application.MessageBox('cos係数に間違いがあります。','注意',0);
    exit;
  end;
  val(labelededit2.Text, bsin, ch);
  if ch <> 0 then begin
    application.MessageBox('sin係数に間違いがあります。','注意',0);
    exit;
  end;
  result := true;
end;

// 動画 strat
procedure TForm1.Button1Click(Sender: TObject);
begin
  if not input(bcos, bsin) then exit;
  timer1.Enabled := true;
end;

// 動画停止
procedure TForm1.Button2Click(Sender: TObject);
begin
  timer1.Enabled := false;
end;

// 初期設定
procedure TForm1.FormCreate(Sender: TObject);
begin
  timer1.Enabled := false;
  timer1.Interval := 30;
  Q := 0;
  ImgeClear;
  image1.Canvas.Pen.Color := clRed;
  image1.Canvas.Pen.Width := 2;
end;

end.


download Lissajous_figure.zip

  画像処理プログラム 作図 に戻る