mercredi 1 décembre 2021

physic's car engine demo version 0.3 programmed on my smartphone!


 





خورزميات محاكات حركة السيارة
الجزء الثاني : القسم التطبيقي
هذه الفيديو  هي عبارة عن هيكل لسيارة تبرز  اهمية المعدلات التفاضلي  لحساب مسار الدواليب االمرسومة بالخطوط الحمراء كما تلاحضون و التحكم على التسارع و اتجهاه المقود عن كريق الضغط على الزر
ملاحضة : هذا البرنامج مكتوب بلغة الجافا على هاتفي النقال و تم تطوير في اوقات الفراغ في المقهى.
void motion(float dt) {
  
     v+=a*dt;
     v*=0.995;
     
     phiA+=v/RA*dt;
     phiB+= v/(RB*abs(cos(wtheta)))*dt;
     omega = v*tan(wtheta)/D;
     phi+= omega*dt;
   
      AB.x=abx*cos(phi)-aby*sin(phi); 
      AB.y=abx*sin(phi)+aby*cos(phi);
    
     
      float stepa= v/D*dt;
      float stepb= omega*dt;
     
      AR.x+=stepa*AB.x;
      AR.y+=stepa*AB.y;
     
      AL.x+=stepa*AB.x;
      AL.y+=stepa*AB.y;
      
      BR.x+= stepa*AB.x-stepb*AB.y;
      BR.y+= stepa*AB.y+stepb*AB.x;
      
      BL.x+= stepa*AB.x-stepb*AB.y;
      BL.y+= stepa*AB.y+stepb*AB.x;
     
     rot(AL,(AL.x+AR.x)/2,(AL.y+AR.y)/2,omega*dt);
     rot(AR,(AL.x+AR.x)/2,(AL.y+AR.y)/2,omega*dt);
     rot(BL,(BL.x+BR.x)/2,(BL.y+BR.y)/2,omega*dt);
     rot(BR,(BL.x+BR.x)/2,(BL.y+BR.y)/2,omega*dt);
     
      G.x=(AL.x+AR.x+BL.x+BR.x)/4;
      G.y=(AL.y+AR.y+BL.y+BR.y)/4;
     
      al.add(new PVector(AL.x,AL.y,0));
      ar.add(new PVector(AR.x,AR.y,0));
      br.add(new PVector(BR.x,BR.y,0));
      bl.add(new PVector(BL.x,BL.y,0));
   
   float fx= v*v/D*tan(wtheta);
   float fz= 10;
   alpha = 0.05*atan(fx/fz);
   }

dimanche 14 novembre 2021

خوارزميات محاكات مسار حركة السيارة

 

الجزء الاول  القسم النظري

ملاحضة : هذه المقالة موجة لاصحاب الاختصاص في البرمجة المحاكات و الالعاب و لديهم مستوى عالي في الرياضيات 

A الدولاب الخلفي

B الدولاب الامامي

|AB|=L  مسافة بين دواليب الامامية و الخلفية

 Va  سرعة دواليب الخلفية

Vb= V سرعة دواليب الامامية

θ  زاوية دوان الدواليب المامية و اتجاه سرعة السيارة

الهدف من هذه المسألة هو حساب مسار الدواليب الاربعة للسيارة مع تغير سرعة و اتجاه السيارة و من ثم ايجاد الخوارزميات المناسب للتحكم في سياقة السيارة مع المتغيرات الاساسية السرعة و زاوية دوران دواليب الامامية

كما نلاحض في الصورة ان المسافة بين الدولاب الامامي و الخلفي يبق دائما ثابتة و السرعة تساوي   V| = |Vb| cos(θ)| => 

 |Vb|= |V|/cos(θ)  

و بتالي شعاع Vb مركب من شعاعين اثنية على مسقاط المماس و الخط القائم 

Vb = Vb cos(θ) Tab +  Vb sin(θ) Nab

Tab = AB/|AB|

Nab شعاع قائم بنسبة ل AB

OA=(xa,ya) OB=(xb,yb)

AB=(xab,yab)=OB-OA=(xb-xa,yb-ya)

xab=xb-xa

yab=yb-ya

Tab= AB/|AB|  =  AB/L= (xab/L,yab/L)

Nab _|_  Tab  =>  Nab . Tab = 0

Nab=(-yab,xab)

Vb = Vb cos(θ) Tab +  Vb sin(θ) Nab

=>

Vb = V/cos(θ) * cos(θ) Tab +  V/cos(θ)* sin(θ) Nab

Va = V Tab

Vb = V Tab +  V tan(θ) Nab

dAB/dt= dOB/dt- dOA/dt= Vb-Va= V tan(θ) Nab

dAB/dt=V  tan(θ) Nab


dTab/dt=V tan(θ)/L Nab
Zab(t) = Zab(0) exp( i ∫ V(t) tan(θ(t))/L dt)
A(t)= ∫ V(t) Tab dt
dB(t)/dt =∫ V(t) Tab dt +∫ V(t) tan(θ(t)) Nab dt
K = tan(θ) /L

هذه هي معادلة الشعاعية التفاظلية لحركة النسبية للدواليب  A و B

dxab(t)/dt  = -V tan(θ)/L yab(t)

dyab(t)/dt  = V tan(θ)/L xab(t)

ω=V tan(θ)/L  سرعة دوران السيارة

dxab(t)/dt  = - ω yab(t)  (1)

dyab(t)/dt  = ω xab(t)    (2)

نقوم الان باضافة الاعداد المركبة لتبسيط المعادلة

Zab = xab + i yab

(1)+ i (2) =>

 dxab(t)/dt  + i dyab(t)/dt= - ω yab(t) +i ω xab(t) 

 d(xab(t) + i yab(t))/dt= i ω ( i yab(t) + xab(t) )

dZab/dt = iω Zab

ln Zab = ∫ iω dt + Constant

Zab(t) = Zab(0) exp( i  ∫ ω(t) dt)

Zab(t) = Zab(0) exp( i  ∫ V(t) tan(θ(t))/L dt) 

و بما ان السرعة الدواليب الخلفية و زاوية الدوران الدواليب الامامية متغيرة سيتولى الحاسوب حل هذه المعادلة التفاظلية بطريقة euler

 الجميع من يقود السيارة يعلم ان اذا قمنا بتثبيت السرعة و المقود ستقوم السيارة بالدوران على نفسها و ترسم شكل دائري او  حركة مستقيم اذا كان المقود مستقيم

لنقم بحساب نصف قطر  الدائرة الخارجية و الداخلية لمسار  سيارة في حالة θ # 0

θ(t) = θ ثابة

V(t) = V ثابة

Zab(t) = Zab(0) exp( i  ∫ V tan(θ)/L dt) 

Zab(t) = Zab(0) exp( i V tan(θ)/L t) 

xab(0)=L    yab(0)=0

Zab(0) =xab(0)+ i yab(0) = L

 Zab(t) = L exp( i V tan(θ)/L t) 

xab(t)= L cos( V tan(θ)/L t) 

yab(t)= L sin( V tan(θ)/L t) 

xb(t)= xab(t)+ xa(t)

yb(t)= yab(t)+ ya(t)

dOA/dt = V Tab

dxa(t)/dt= V/L xab(t)   dya(t)/dt= V/L yab(t)

dxa(t)/dt= V cos( V tan(θ)/L t) 

dya(t)/dt= V sin( V tan(θ)/L t) 

xa(t)=  ∫ V cos( V tan(θ)/L t) dt

ya(t)=  ∫ V sin( V tan(θ)/L t)  dt

xa(t)=  L cot(θ) sin( V tan(θ)/L t) +C1

ya(t)=  -L cot(θ) cos( V tan(θ)/L t) +C2

xa(0)= 0   ya(0)= 0

xa(t)=  L cot(θ) sin( V tan(θ)/L t) 

ya(t)=  L cot(θ) (1-cos( V tan(θ)/L t) )

xa(t)² + (ya(t)- L cot(θ))²=   L² cot(θ)²

Ra =  L cot(θ)

xa^2 + (ya-R)^2=  R^2

نستنتج ان حركة الدولاب A  الخلفي هو على شكل معادلة الدائرة  نصف قطرها   |L |cot(θ)

Ra =  L |cot(θ)|

xb(t)= xab(t)+ xa(t)

yb(t)= yab(t)+ ya(t)

 xb(t)= L cos( V tan(θ)/L t) + L cot(θ) sin( V tan(θ)/L t) 

yb(t)=L sin( V tan(θ)/L t)  + L cot(θ) (1-cos( V tan(θ)/L t) )

xb(t)= L/sin(θ) sin( V tan(θ)/L t +θ) 

yb(t)=-L/sin(θ) cos( V tan(θ)/L t +θ) +L cot(θ)

xb(t)²+ (yb(t)- L cot(θ))²=   L²/sin(θ)²

Rb =  L/|sin(θ)|

 Ra = Rb |cos(θ)|

Ra/Rb= |cos(θ)|

و نستنتج ايضا  ان حركة الدولاب B المامي هو يخضع لمعادلة الدائرة  نصف قطرها  |(L/|sin(θ

تابع الجزء الثاني

تطبيق المعدلات النظرية في البرنامج و تجسيدها على شكل خوزميات...

jeudi 28 octobre 2021

hydrogen electron orbitals in 3d space

 
 
 

بيان ثلاثي الابعاد لمدارات الالكترون في ذرة الهيدروجين وفقًا لتوزيع شرودنجر لاحتمال كثافة الوجود في مكان ما ! تم
إنشاؤه بواسطة برنامجي shader GPU


Visualizing the hydrogen electron orbitals in 3d space according the Schrodinger distribution of the probability of presence ! generated by shader GPU code ....

ih dψ(r,t)/dt=(-h²/2m ( d²ψ(r,t)/dx²+d²ψ(r,t)/dy²+d²ψ(r,t)/dz²)-Ze²/r ψ(r,t))
ρ(r,θ,φ) = |ψ(r,t)|²


vendredi 24 septembre 2021

pinfoot aso, Basic!


 

REM pinfoot aso, Basic!
Wakelock 3
dim xc[10]
dim yc[10]
dim Rc[10],r[10],g[10],b[10],a[10]
dim xa[10],ya[10],xb[10],yb[10]
choc =1
dim s[3]
gravity =0.3
radius =50
GR.OPEN 255, 0, 0,0
GR.SCREEN sy, sx
GR.ORIENTATION 1
!sx=720:sy=1560
ARRAY.LOAD Pattern[],100,10
sensors.open 1
GR.BITMAP.LOAD ptr_ball, "ball.png"
gR.BITMAP.LOAD ptr_wood, "bg.png"
gR.BITMAP.LOAD ptr_alg, "algeria.png"
gR.BITMAP.LOAD ptr_aso, "aso.png"
AUDIO.LOAD whee, "flip-on3.mp3"
AUDIO.LOAD boing, "boing.mp3"
AUDIO.LOAD wall,"wall0.mp3"
AUDIO.LOAD goal,"goal.mp3"
AUDIO.LOAD music,"ball.wav"
dim ball[1],WOOD[1],ALG[1],ASO[1]
begin:
score = 0
alpha =255
x=rnd()*sx
y=450
vx=15
vy=18
KX=KY=0
k =1
dt=0
vmin =15
n=3
xc[1]=sx/2:yc[1]= 300:Rc[1]=60
r[1]=255:g[1]=0:b[1]=0:a[1]=255
xc[2]=sx/2-200:yc[2]= 600:Rc[2]=40
r[2]=0:g[2]=255:b[2]=0:a[2]=255
xc[3]=sx/2+200:yc[3]= 600:Rc[3]=40
r[3]=0:g[3]=0:b[3]=255:a[3]=255
xc[4]=sx/2:yc[4]= 900:Rc[4]=60
r[4]=255:g[4]=0:b[4]=255:a[4]=255
xb= sx/2:yb=sy-200
lx=100:ly=25
do
!start =time()
!sensors.read 1, s[1],s[2],s[3][]
!gr.rotate.start s[1],sx/2,0
!gr.rotate.end
xc[1]=sx/2+200*sin(time()/1000)
yc[2]=sy/2+200*sin(2*time()/1000)
yc[3]=sy/2-200*sin(2*time()/1000)
x+= vx
y+= vy
if x<radius then
AUDIO.STOP
AUDIO.PLAY wall
vx=-k*vx
!if abs(vx)> vmin then vibrate Pattern[],-1
x=radius
endif
if x>sx-radius then
AUDIO.STOP
AUDIO.PLAY wall
!if abs(vx)>vmin then vibrate Pattern[],-1
vx=-k*vx
x= sx-radius
endif
if y<radius then
AUDIO.STOP
AUDIO.PLAY wall
!if abs(vy)>vmin then vibrate Pattern[],-1
vy=-k*vy
y=radius
endif
!if y>sy-radius then
!if abs(vy)>vmin then vibrate Pattern[],-1
!vy=-k*vy
!y= sy-radius
!endif
gr.touch touched, xt, yt
if touched & abs(xt-xb)<=lx & abs(yt-yb)<=ly+50 then
xb= xt:yb=yt
endif
gosub collision
!xb+=-8*s[1]
if xb+lx>sx then xb=sx-lx
if xb-lx<0 then xb=lx
if (x>=xb-lx-20) & (x<=xb+lx+20) & (abs(y+radius-yb+ly)<=40) & (vy>=0) then
vy=-vy+0.1*(yt-ytp)
vx+=0.1*(xt-xtp)
y= yb-ly-radius
!vibrate Pattern[],-1
endif
if y>=sy then
gr.cls
GR.TEXT.SIZE 100
GR.TEXT.DRAW nc,100,600,"YOU LOSE"
gr.render
AUDIO.STOP
AUDIO.PLAY goal
pause 2000
goto begin
endif
if touched=0 then
KX=KY=0
endif
xtp=xt:ytp=yt
!dt=(time()-start)/1000
xtp=xt:ytp=yt
gosub render
!gr.render
until 0
exit:
end
collision:
for i=1 to n
tx = x-xc[i]
ty = y-yc[i]
t = (tx*tx+ty*ty)^0.5
tx=tx/t
ty=ty/t
nx=-ty
ny=tx
vt = vx*tx+vy*ty
vn = vx*nx+vy*ny
if (t<=radius+Rc[i]) & (vt<0) & (a[i]>30) then
gr.color 255,255,255,255
gr.circle nc,xc[i],yc[i],Rc[i]
gr.render
AUDIO.STOP
AUDIO.PLAY whee
vx = 1.0*(-vt*tx+vn*nx)
vy= 1.0*(-vt*ty+vn*ny)
score+=10
if (a[i]>30) then a[i]=a[i]-5.
w =(a[1]<=30) & (a[2]<=30) & (a[3]<=30)
if w then
AUDIO.STOP
AUDIO.PLAY music
gr.cls
gr.color 255,255,255,255
GR.TEXT.SIZE 100
GR.TEXT.DRAW nc,100,600,"YOU WIN"
gr.render
pause 1000*6
goto begin
endif
!vibrate Pattern[],-1
endif
next i
return
render:
gr.color 255,0,0,0
gr.cls
gr.bitmap.draw WOOD[1],PTR_wood,0,0
gr.bitmap.draw ball[1],ptr_ball,x-radius,y-radius
gr.color a[1],r[1],g[1],b[1]
gr.bitmap.draw ALG[1],ptr_alg,xc[1]-Rc[1],yc[1]-Rc[1]
gr.color a[2],r[2],g[2],b[2]
gr.bitmap.draw ASO[1],ptr_aso,xc[2]-Rc[2],yc[2]-Rc[2]
gr.color a[3],r[3],g[3],b[3]
gr.bitmap.draw ASO[1],ptr_aso,xc[3]-Rc[3],yc[3]-Rc[3]
gr.color 255,255,255,0,1
gr.rect nc, xb-lx, yb-ly, xb+lx, yb+ly
!for i=1 to n
!gr.color a[i],r[i],g[i],b[i]
!gr.circle nc,xc[i],yc[i],Rc[i]
!next i
gr.color 255,255,255,1
GR.TEXT.SIZE 50
GR.TEXT.DRAW nc,10,50,"SCORE="
GR.TEXT.DRAW nc,200,50,str$(score)
gr.render
return
line:
for k=1 to nl
tx = xa[k]-xb[k]
ty= ya[k]-yb[k]
t = sqrt(tx*tx+ty*ty)
tx=tx/t:ty=ty/t
nx = -ty: ny= tx
return

 

vendredi 21 mai 2021

maze




 
void generateWall() {
// remove the clones walls
for (int i = 0; i < g_sizex-1; i++)
for (int j = 0; j < g_sizey-1; j++) {
if(cell[i][j].wall[2] && cell[i][j+1].wall[3]) cell[i][j+1].wall[3]=false;
if(cell[i][j].wall[1] && cell[i+1][j].wall[0]) cell[i+1][j].wall[0]=false;
}
// store the walls into the Arraylist
for (int i = 0; i < g_sizex; i++)
for (int j = 0; j < g_sizey; j++) {
if(cell[i][j].wall[0]) wl.add(new wall(j*c_sizex-width/2, i*c_sizey-height/2, j*c_sizex-width/2, (i+1)* c_sizey-height/2));
if(cell[i][j].wall[1]) wl.add(new wall(j*c_sizex-width/2, (i+1)*c_sizey-height/2, (j+1)*c_sizex-width/2, (i+1)*c_sizey-height/2));
if(cell[i][j].wall[2]) wl.add(new wall((j+1)*c_sizex-width/2, (i+1)*c_sizey-height/2, (j+1)*c_sizex-width/2, i*c_sizey-height/2));
if(cell[i][j].wall[3]) wl.add(new wall((j+1)*c_sizex-width/2, i*c_sizey-height/2, j*c_sizex-width/2, i*c_sizey-height/2));
}
}

mercredi 31 mars 2021

pinball physic's engine developped with processing language



pinball
 قمت في اوقات الفراغ ببرمجته في المقهى على جهازي الهاتف النقال محرك فيزيائي ثم بعد ذلك تم نقل البرنامج على
منصة 
windows
 

During my free time I developed on my smartphone a pinball physic's engine  using processing apde application and  ported on windows platform to enhance the graphics

class flipper {

float R,r,D,phi0;
float phi,omega;
float deltaphi=PI/3;
float choc=1.2;
float Vpinball = 13;
vec2 v,vt;
vec2 o,m;
vec2 a1,b1,a2,b2;
wall w1,w2 ;
circle c1,c2;


flipper(vec2 io,float iR,float ir,float iD,float iphi0) {

o = new vec2(io.x,io.y);
R =iR; r = ir; D = iD; phi0 = iphi0;
m = new vec2(D,0);

// rotate the bar
m = add(o,m);
m = rot(m,o,phi0);

// compute the two walls
float L = sqrt(D*D-pow(R-r,2));
a1 = new vec2();
b1 = new vec2();
a1.x = R*(R-r)/D+o.x; a1.y = R*L/D+o.y;
b1.x = r*(R-r)/D+D+o.x; b1.y = r*L/D+o.y;
a1 = rot(a1,o,phi0); b1 = rot(b1,o,phi0);
w1 = new wall(a1.x,a1.y,b1.x,b1.y);

a2 = new vec2();
b2 = new vec2();
a2.x = R*(R-r)/D+o.x; a2.y = -R*L/D+o.y;
b2.x = r*(R-r)/D+D+o.x; b2.y = -r*L/D+o.y;
a2 = rot(a2,o,phi0); b2 = rot(b2,o,phi0);
w2 = new wall(a2.x,a2.y,b2.x,b2.y);

c1 = new circle(o.x,o.y,R);c1.choc =0.5;
c2 = new circle(m.x,m.y,r);c2.choc =0.5;


v =new vec2(0,0);
vt =new vec2(0,0);
omega = 5;
}

void draw() {

stroke(0,255,0);
fill(255,0,0,100);
beginShape();
vertex(w1.a.x,w1.a.y);
vertex(w1.b.x,w1.b.y);
vertex(w2.b.x,w2.b.y);
vertex(w2.a.x,w2.a.y);

endShape(CLOSE);

noFill();
w1.wg=2; w2.wg = 2;
w1.setcolor(255,0,0);
w2.setcolor(255,0,0);

w1.draw();w2.draw();

//stroke(255,0,0);
strokeWeight(1);
fill(255,0,0);
ellipse(o.x,o.y,2*R,2*R);
ellipse(m.x,m.y,2*r,2*r);
fill(255); stroke(255); strokeWeight(2);
ellipse(o.x,o.y,R,R);
ellipse(m.x,m.y,r,r);


}

void update(float t) {
a1 = rot(a1,o,omega*t);
b1 = rot(b1,o,omega*t);
w1.a.x =a1.x;w1.a.y =a1.y;w1.b.x =b1.x;w1.b.y=b1.y;
w1.omega = omega;
a2 = rot(a2,o,omega*t);
b2 = rot(b2,o,omega*t);
w2.a.x =a2.x;w2.a.y =a2.y;w2.b.x =b2.x;w2.b.y=b2.y;
w2.omega = omega;
m = rot(m,o,omega*t);
c2.p.x = m.x;c2.p.y=m.y;
phi+=omega*t;
}

void control_right( char c) {
if ((mousePressed && mouseButton == LEFT) || (keyPressed && key==c)) {

if (!sound_pinball.isPlaying()) sound_pinball.play();

if (phi>=phi0+deltaphi) omega=0; else omega=Vpinball;
} else {
if (phi<=phi0) omega=0; else omega=-Vpinball;
}}

void control_left( char c) {
if ((mousePressed && mouseButton == LEFT) || (keyPressed && key==c)) {
sound_pinball.stop();
if (!sound_pinball.isPlaying()) sound_pinball.play();


if (phi<=(phi0-deltaphi)) omega=0; else omega=-Vpinball;
} else {
if (phi>=phi0) omega=0; else omega=Vpinball;
}
}


boolean collision() {

return w1.collision(b) ||w2.collision(b) || c1.collision(b) || c2.collision(b);
}
}