برنامج لمحاكاة حركة النواس البسيط

يتكون النواس البسيط  من جسم صلب صغير الأبعاد (يمكن اعتباره نقطة مادية) معلق بطرف خيط غير قابل للامتداد وله كتلة مهملة، شد طرفه الآخر إلى حامل ثابت كما في الشكل:




لمحاكاة حركة النواس باستعمال لغة البرمجة دلفي  نعتبر  كرية صغيرة كتلتها مهملة معلقة  بخيط طوله L مثبت في سقف ثابت ونترك الكرية حتى تستقر في وضعية معينة صانعة زاوية منعدمة مع الشاقول  ومستقرة على بعد L  من المبدأ، فتكون حينها خاضعة للجاذبية الأرضيةg=9.8  وتوتر الخيط T
نحرك الكرية حركة خفيفة فتصنع مع الشاقول زاويةθ0 ثم نتركها تتحرك بحرية فتكون معادلة تغير الزاوية  كالتالي :


بالنسبة للاهتزازات الصغيرة يمكن أن نحصل على حل من الشكل التالي :
θ = θ0 cos ( ω0 t).
حيث:

ω0=√(g/L) Sin(θ)=x/L ; Cos(θ)=y/L ;
بعد الكرية على السقف يكون مساو للقيم التالية :
x=L*sin(θ) ;
y=L*cos(θ) ;

لجعل أبعاد الشاشة مناسبة للأبعاد الفيزيائية نقوم بالتحويلات التالية :
نعتبر المحور الشاقولي يمر من النقطة (0، 0، 0) للشاشة  ويبعد السقف عن المركز بالمسافة b
حيث : 
نضع : 
h :=dummy1.height/2 ;
b :=L*h/200 ;

فتكون إحداثيات الكرة كالتالي 
P.x := h * x/200;
P.y := -h * (l - y)/200;
P.z:=0;
Sphere1.Position.Point := P;


الفيديو التالي يعرض العناصر المستعملة في هذا التطبيف

وهذا نص الكود  :
unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms3D, FMX.Types3D, FMX.Forms, FMX.Graphics,
  FMX.Dialogs, System.Math.Vectors, FMX.MaterialSources, FMX.Objects3D,
  FMX.Controls3D, FMX.Layers3D, FMX.Ani, FMX.Controls.Presentation,
  FMX.StdCtrls, FMX.Edit, FMX.EditBox, FMX.SpinBox, FMX.ScrollBox, FMX.Memo;

type
  TForm1 = class(TForm3D)
    Dummy1: TDummy;
    RoundCube1: TRoundCube;
    Light1: TLight;
    LightMaterialSource1: TLightMaterialSource;
    Sphere1: TSphere;
    TextureMaterialSource1: TTextureMaterialSource;
    FloatAnimation1: TFloatAnimation;
    Layer3D1: TLayer3D;
    Label1: TLabel;
    SpinBox1: TSpinBox;
    Label2: TLabel;
    LightMaterialSource2: TLightMaterialSource;
    Edit1: TEdit;
    Label3: TLabel;
    Plane1: TPlane;
    procedure Form3DCreate(Sender: TObject);
    procedure FloatAnimation1Process(Sender: TObject);
    procedure Dummy1Render(Sender: TObject; Context: TContext3D);
    procedure SpinBox1Change(Sender: TObject);
    procedure Sphere1Click(Sender: TObject);
    procedure Edit1Enter(Sender: TObject);
    procedure Edit1Exit(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;
  t: single;
  w0, w, h, g, l, theta0, m: single;

implementation

{$R *.fmx}

procedure TForm1.Dummy1Render(Sender: TObject; Context: TContext3D);
var
  theta, x, y, b: single;
  P, ps, ps1: TPoint3d;
begin
  theta := theta0 * cos(w0 * t);
  trystrtofloat(Edit1.Text, l);

  // =======================
  x := l * sin(theta);
  y := l * cos(theta);
  if m < (l - y) then
    m := l - y;

  // 200*l/h
  b := h * l / 200;

  P.x := h * x/200;
  P.y := -h * (l - y)/200;
  Sphere1.Position.Point := P;
  ps := Dummy1.AbsoluteToLocal3D(RoundCube1.AbsolutePosition);
  ps1 := Dummy1.AbsoluteToLocal3D(Sphere1.AbsolutePosition);

  Context.DrawLine(ps, ps1, 1, TAlphacolors.yellow);
  Context.DrawLine(ps, point3d(ps.x, Dummy1.Height, ps.Z), 1,
    TAlphacolors.White);

  Label1.Text := format('X:%f,Y:%f  ' + #13 + ' Z:%f Theta :%f ' + #13 +
    'hmax:%f', [x, y, P.Z, 180 * theta / Pi, m]);

end;

procedure TForm1.Edit1Enter(Sender: TObject);
begin
  FloatAnimation1.StopAtCurrent;
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  t := 0;
  m := 0;
  FloatAnimation1.Start;
end;

procedure TForm1.FloatAnimation1Process(Sender: TObject);
begin
  t := t + 0.05
end;

procedure TForm1.Form3DCreate(Sender: TObject);
begin
  t := 0;
  m := 0;

  g := 9.8;
  h := Dummy1.Height / 2;
  w := Dummy1.Width / 2;
  l := h / 2;
  theta0 := Pi / 4;
  SpinBox1.Value := theta0 * 180 / Pi;
  Edit1.Text := format('%f', [100 * l / h]);
  w0 := sqrt(g / l);
  t := 0;
end;

procedure TForm1.Sphere1Click(Sender: TObject);
begin
  t := 0;
  m := 0;
  FloatAnimation1.Start;
end;

procedure TForm1.SpinBox1Change(Sender: TObject);
begin
  theta0 := Pi * SpinBox1.Value / 180;
end;

end.// =======================

المشاركات الشائعة