3D Ball Collision in Python with Visual Module.

I only compute the collision between bed and blue one. They’re bola[1] and bola[2] respectively

from visual import *
from random import uniform,random
from visual.controls import *

def change():
global jalan
if b.value:
jalan = True
for ball in(bola):
ball.vx = uniform(-7,7)
ball.vy = uniform(-7,7)
ball.vz = uniform(-7,7)
else:
jalan = False

c = controls(title='Tempat Tombol',x=800, y=0, width=300, height=300, range=50)
b = toggle( pos=(0,0), width=20, height=20, text='Click me', action=lambda: change() )
display(center=(0,0,0),background=(1,1,1), #autoscale=False,
width=600, height=600, forward=(-0.4,-0.3,-1)) #arah kamera
g = -1.
dt = .1
e = 1.
b.value = True
jalan = True
l = 17.
dl = .01
n = 11

distant_light(direction=(1,1,1), color=color.red)
lantai = box(color=color.white, pos=(0,0,0),length=l,height=dl, width=l, opacity=.3)
dindingKiri = box(color=color.white, pos=(-l/2,l/2,0),length=dl,height=l, width=l, opacity=.3)
dindingKanan= box(color=color.white, pos=(l/2,l/2,0),length=dl,height=l, width=l, opacity=.3)
dBelakang = box(color=color.white, pos=(0,l/2,-l/2),length=l,height=l, width=dl, opacity=.3)
atap = box(color=color.white, pos=(0,l,0),length=l,height=dl, width=l, opacity=.3)
bola = []
for i in arange(n):
ball = sphere (pos=(uniform(1,7),0,uniform(-7,7)), radius=.3, color=color.green)
ball.v = vector(uniform(-7,7),uniform(-7,7),uniform(-7,7))
bola.append(ball)


bola[1].radius = 2.5
bola[2].radius = 2.5

bola[1].color = color.red
bola[2].color = color.blue
def proses():
for ball in (bola):
a = g
ball.v[1] += a*dt
ball.pos+= ball.v*dt
tumbukan()
tumbukanBola()

def tumbukan():
for ball in(bola):
if ball.y<0:
ball.y = 0.01
ball.v[1] *=-1.*e
elif ball.y>l:
ball.y = l-.01
ball.v[1] *= -1
if ball.x<-l/2:
ball.x=-l/2+.01
ball.v[0] *= -1*e
if ball.x>l/2:
ball.x=l/2-.01
ball.v[0] *= -1*e
if ball.z<-l/2:
ball.z=-l/2+.01
ball.v[2] *= -1*e
if ball.z>l/2:
ball.z=l/2-.01
ball.v[2] *= -1*e

def tumbukanBola():
#pass
jarak = mag(bola[2].pos-bola[1].pos)
if jarak<(bola[1].radius+bola[2].radius):
arah = norm(bola[2].pos-bola[1].pos)
v1 = dot(bola[1].v,arah)
v2 = dot(bola[2].v,arah)
dv = v2-v1
bola[1].v += dv*arah
bola[2].v -= dv*arah



while 1:
rate (51)
if jalan:
proses()







.

Alright, Now Do It in Python, with style, :)

Python version of this flash action script of electron under Lorentz force, 🙂

from visual import *
from random import uniform

display(center=(0,0,0),background=(1,1,1), autoscale=False,
width=600, height=600,
#forward=(-0.4,-0.3,-1)
)

distant_light(direction=(1,1,1), color=color.red)


l = 11
dt = 1./8.
medan = box(color=color.white,
pos=(l/2,0,0),length=l,height=l,
width=l, opacity=.3)

ball = sphere (pos=(-7,0,0), radius=.3, color=(uniform(0,1),uniform(0,1),uniform(0,1)))

def awal():
global q,m,B,v
q = 1.
m = 1.
B = vector(0.,0.,1.)
v = vector(3.,0.,0.)


def proses():
global v,B
if ball.x > 0:
B = vector(0.,0.,1.)
else:
B = vector(0.,0.,0.)
print B
F = q*(cross(v,B))
a = F/m
v += a*dt

ball.pos += v*dt
print ball.x

awal()
while 1:
rate (37)
proses()



.

Menyapa Senjata Lama.

Sudah lama tidak otak-atik Macromedia Flash.

Yup, masih yang Macromedia, bukan Adobe, 🙂 .

Membuat animasi bola bermuatan (atau elektron) yang bergerak lurus dengan kecepatan konstan tiba-tiba mencapai daerah dengan  medan magnet. Sesuai hukum Lorentz maka bola/elektron akan bergerak melengkung.

Action script hanya ditulis pada action di frame pertama layer background.

px0 = bola._x;
py0 = bola._y;
awal();
_root.onEnterFrame = function() {
if (jalan == true) {
proses();
}
//trace(jalan)
};
function awal() {
jalan = false;
bola._x = px0;
bola._y = py0;
q = 1;
B = 1;
tB.text = B;
//massa
m = 1;
tm.text = m;
//kecepatan
vx = 50;
vy = -10;
tvx.text = vx;
tvy.text = vy;
//percepatan
ax = 0;
ay = 0;
//posisi
px = 0;
py = 0;
dt = 1/8;
}
function bacaInput() {
vx = Number(tvx.text);
vy = Number(tvy.text);
m = Number(tm.text);
B = Number(tB.text);
}
function updateNilai() {
tB.text = B;
tm.text = m;
tvx.text = vx;
tvy.text = vy;
}
function proses() {
v = Math.sqrt(vx*vx+vy*vy);
if (bola._x>200) {
F = B*q*v;
} else {
F = 0;
}
a = F/m;
//arah vektor normal v
nvx = vx/v;
nvy = vy/v;
/*arah vektor percepatan
karena vektor yang tegak lurus a=(ax,ay) adalah at=(-ay,ax)
*/
nax = -nvy;
nay = nvx;
ax = a*nax;
ay = a*nay;
//hitung kecepatan baru
vx += ax*dt;
vy += ay*dt;
px += vx*dt;
py -= vy*dt;
trace(F);
//update posisi bola
bola._x = px0+px;
bola._y = py0+py;
updateNilai();
}
//tombol-tombol
//tombol tbJalan
tbJalan.onRelease = function() {
bacaInput();
jalan = true;
};
tbStop.onRelease = function() {
jalan = false;
};
tbReset.onRelease = function() {
awal();
};


.

Iterasi di Python

Jika kita punya sebuah list bernama bola yang didefinisikan sebagai:

bola = []

kemudian kita membuat obyek bernama ball

ball = sphere (pos=(uniform(1,7),0,uniform(-7,7)), radius=.3, color (uniform(0,1),uniform(0,1),uniform(0,1)))
ball.vx  = uniform(-7,7)
ball.vy  = uniform(-7,7)
ball.vz  = uniform(-7,7)
 
Obyek ini kita masukkan ke dalam bola dengan perintah

bola.append(ball)

Kita dapat melakukannya berkali-kali sehingga pada list bola terdapat beberapa obyek bernama ball

Jika kita ingin mengakses obyek tersebut, kita dapat menggunakan perintah semacam

bola[0].vx = 1

jika kita ingin mengakses vx di semua obyek bola, kita dapat menggunakan iterasi

for i in arange (n):
  bola[i].vx = 1

Namun di python ada cara lain yang juga mudah

for ball in (bola):
  ball.vx = 1

Berikut contoh kode yang menggunakan iterasi seperti itu

from visual import *
from random import uniform,random
from visual.controls import *

def change():
global jalan,vx,vy,vz
if b.value:
jalan = True
for ball in(bola):
ball.vx = uniform(-7,7)
ball.vy = uniform(-7,7)
ball.vz = uniform(-7,7)
else:
jalan = False

c = controls(title='Tempat Tombol',x=800, y=0, width=300, height=300, range=50)
b = toggle( pos=(0,0), width=20, height=20, text='Click me', action=lambda: change() )
display(center=(0,0,0),background=(1,1,1), #autoscale=False,
width=600, height=600, forward=(-0.4,-0.3,-1)) #arah kamera
g = -1.
dt = .1
e = 1.
b.value = True
jalan = True
l = 17.
dl = .01
n = 11

distant_light(direction=(1,1,1), color=color.red)
lantai = box(color=color.white, pos=(0,0,0),length=l,height=dl, width=l, opacity=.3)
dindingKiri = box(color=color.white, pos=(-l/2,l/2,0),length=dl,height=l, width=l, opacity=.3)
dindingKanan= box(color=color.white, pos=(l/2,l/2,0),length=dl,height=l, width=l, opacity=.3)
dBelakang = box(color=color.white, pos=(0,l/2,-l/2),length=l,height=l, width=dl, opacity=.3)
atap = box(color=color.white, pos=(0,l,0),length=l,height=dl, width=l, opacity=.3)
bola = []
for i in arange(n):
ball = sphere (pos=(uniform(1,7),0,uniform(-7,7)), radius=.3, color=(uniform(0,1),uniform(0,1),uniform(0,1)))
ball.vx = uniform(-7,7)
ball.vy = uniform(-7,7)
ball.vz = uniform(-7,7)
bola.append(ball)

def proses():
global vx,vy,vz
for ball in (bola):
a = g
ball.vy += a*dt
ball.pos+= vector(ball.vx*dt,ball.vy*dt,ball.vz*dt)
tumbukan()

def tumbukan():
global vx,vy,vz
for ball in(bola):
if ball.y<0:
ball.y = 0.01
ball.vy *=-1.*e
elif ball.y>l:
ball.y = l-.01
ball.vy *= -1
if ball.x<-l/2:
ball.x=-l/2+.01
ball.vx *= -1*e
if ball.x>l/2:
ball.x=l/2-.01
ball.vx *= -1*e
if ball.z<-l/2:
ball.z=-l/2+.01
ball.vz *= -1*e
if ball.z>l/2:
ball.z=l/2-.01
ball.vz *= -1*e

while 1:
rate (100)
if jalan:
proses()


.

Stack.

 It’s basically an unused cymbal thrown on top of another broken one at the cymbal stand, 😛

 #edisiError

Lorenz Attractor in Python with Visual Module.

 So much faster than matplotlib 3d projection

from visual import *
from random import uniform
display(center=(0,0,0), #pusat display
background=(1,1,1),
#autoscale=False, #agar display tidak otomatis mengikuti obyek
width=600,
height=600,
forward=(-0.4,-0.3,-1)) #arah kamera
x = 1.
y = 1.
z = 1.

dt = 1./64.
s = 10.
b = 8./3.
r = 28
w = 0.
dw = 0.01

n = 0
while 1:
rate(1)
while n<3000:
n += 1

xdot = s * (y-x)
ydot = x*r -x*z -y
zdot = x*y -b*z

x = x+xdot*dt
y = y+ydot*dt
z = z+zdot*dt

w +=dw
if w>1 or w<0:
dw = -dw

sphere(pos=(x,y,z),radius=.7,color=(0.,w,0))







Timbal balik

 Alfa suka roti bakar “tesoberry” buatan ibuknya atau buatanku (yang hampir pasti selalu gosong, 🙂 ).

 Kadang dia ingin rasa lain.

 Beberapa hari sekali minta roti bakar keju dan “yang coklat untuk adek”. Beta memang suka  coklat.

 Jadilah, jika di pagi hari dia pesan sewaktu saya akan berangkat ngampus (saat dia kuantar ke rumah budhe), maka pulang harus bawa roti bakar bandung rasa coklat dan keju terpisah buat mereka.

 Awalnya saya langganan beli  roti bakar di pertigaan yang lumayan dekat dengan rumah.  Langganan, yeah, karena di situ selalu sepi, jarang sekali ngantri.

 Ternyata juga jarang sekali penjualnya ada meski dagangannya ada, entah kenapa.

 Ehm, sepi, ternyata itu. Tetap saja kadang saya rela menunggu lima belas menit untuk orangnya datang. Pulang ke rumah dengan tangan kosong bukan pilihan yang bagus, meski Alfa Beta terkadang juga tidak protes.

 Mengajari mereka menepati janji dengan contoh nyata, 🙂

 Suatu malam, pulang ngampus, dapat “order” untuk bawa roti-bakar. Ndilalah tukang roti bakar di pertigaan situ tak ada, berikut jualannya. Tutup.

 Terpaksa balik ke arah kampus. Targetnya ke perempatan Galunggung. Dulu sepertinya ada.

 Eh, ternyata selepas perempatan Dieng ternyata ada. Coba ah.

 Kebetulan, hanya ada satu pembeli, mbak cantik yang sedang duduk di sadel bebek matic putih, pesanannya hampir selesai, relatif sepi.

 Sehabis turun dari si ducati langsung disapa

 “Rasa apa mas?”

 “Coklat keju, mas”

 “Dicampur atau pisah?”

 “Pisah”

 “Tunggu sebentar ya”

 “nggih”

 Pesanan sebelumku telah jadi, terbungkus kertas minyak coklat, dan sudah masuk kantong plastik hitam. Entah rasa apa.

 “sudah mbak”

 Si mbak cantik, mengeluarkan uang seratus ribu.

 Tanpa diduga, mas penjual roti minta ijin ke warung tenda sebelah  untuk tukar recehan.

 Wow, kejadian langka. Harusnya, eh, biasanya, penjual akan sedikit protes atau setidaknya tanya “apakah ada uang kecil?’.

 Kesan pertama.

 …

 Roti panggangku sudah separuh jalan. Tinggal dihias cokelat dan keju.

 Si mas memberi taburan cokelat meses dengan royal, sampai-sampai ketika roti ditutup jadi langsung berubah wujud, obesitas.

 Hal yang sama juga terjadi pada parutan keju. Hampir setengah batang dihbaiskan hanya untuk rotiku.

 Panik, meroh]goh dompet, kulihat daftar harga. Sama, tujuhbelas ribu. What the…

 “Ini mas, ” tiba-tiba  kantong plastik berisi roti yang terbungkus kertas minyak cokelat disodorkan ke tanganku.

 Kubayar dengan tiga lembar lima ribuan dan selembar dua ribu, yang diterima dengan senang hati, ada bahan untuk uang kembalian.

 Dan malam itu, di rumah, kami berempat seperti pesta roti mewah, 🙂

 …

 Hari-hari berikutnya selalu pesan ke tempat itu.

 Selalu bayar dengan uang pas.

 Selalu di jam yang hampir sama.

 Selalu dengan jaket gunung kuning menyala.

 Selalu bayar dengan uang pas.

 …

 Suatu malam, pembeli sedang banyak-banyaknya. OK, tak apa, nunggu sambil main-main handphone.

 Satu demi satu pembeli terlayani hingga tinggal dua orang. Sepasang cowok-cewek yang naik motor touring dan aku. Rotinya sudah selesai. Ada satu roti yang juga siap dibungkus

 Ups, lupa pesan.

“Eh mas, coklat keju”

 “Sudah tahu kok, ni tinggal mbungkus “

 Eh.

 Si mas penjual sudah hafal. Mungkin.

Beberapa hari setelah itu. Datang ke sana, sengaja diam untuk mengetes.

 Dan…, coklat-keju. Otomatis. Valid, si mas penjual roti telah hafal, hehehe.

 Bakal ke situ terus.

 Sepertinya dihafal oleh seseorang memang bukan apa-apa, tak ada artinya, bagi beberapa orang.

 Tetapi itu juga merupakan kemewahan, meskipun kecil.

 Dan itu juga merupakan nilai lebih, meskipun kecil.

 Juga merupakan nilai tambah, nilai jual, meningkatkan daya saing, meskipun kecil.

 Itu yang membuat saya ke situ terus.

Forced to get Force using Center of Mass

 I know. Using solely center of mass as main contributor in force calculation is bad idea in nearly homogenous n-body system.

 Well, I’m curious about that. So, just bite it.

 And, yeah, bad idea.

 The system is fine, generally.

 Each body move as usual, at a glimpse.

 But if we go detail about that. There’s strange behavior here and there.

 On previous code with brute force calculation, we could saw, binary system consist of two body orbiting each other. But, with this center-of-mass-code, we see no one. A body that have very close neighbor don’t make a twin system. It continues orbiting center of mass.

 As we have system with -body with same mass, it should be natural if two close-body will have greater gravity force than with any other body. It should have “priority”; orbiting each other.

 Ok, this “forced”-center-mass-code is weird, but it’ll useful in other system. 🙂

from visual import *
from random import uniform,random

l = 17.
dl = .01
display(center=(0,0,0),background=(1,1,1),autoscale=False, width=600, height=600,forward=(-0.7,-0.7,-1))
distant_light(direction=(1,1,1), color=color.red)
#local_light(pos=(0,0,0), color=(0,0,1))
#sphere(pos=(0,0,0), color=(0,0,0), material=materials.emissive, opacity=0.9)

box(color=color.white, pos=(0,l/2,0),length=l,height=dl, width=l, opacity=0.3)
box(color=color.white, pos=(0,-l/2,0),length=l,height=dl, width=l, opacity=0.3)
box(color=color.white, pos=(l/2,0,0),length=dl,height=l, width=l, opacity=0.3)
box(color=color.white, pos=(-l/2,0,0),length=dl,height=l, width=l, opacity=0.3)
box(color=color.white, pos=(0,0,l/2),length=l,height=l, width=dl, opacity=0.3)

bola = []
n = 11
dv = .1 #kecepatan setelah menabrak dinding
G = 31.
for i in range(n):
ball = sphere (pos=(uniform(-7,7),uniform(-7,7),uniform(-7,7)), radius=.2, color=(random(),random(),random()))
ball.v = vector(uniform(-1,1),uniform(-1,1),uniform(-1,1))

bola.append(ball)


dt = 1./32.
bola[0].pos=(1,1,1)


def hitungGaya(i,rcm):
r = bola[i].pos-rcm
jarak = mag(r)
arah = -norm(r)
gaya = G*1./(pow(jarak,2)+.1)*arah*n
return gaya
def hitungPusatMassa():
xcm = 0.
ycm = 0.
zcm = 0.
for i in arange(n):
xcm += bola[i].x
ycm += bola[i].y
zcm += bola[i].z
xcm /= n
ycm /= n
zcm /= n
return vector(xcm,ycm,zcm)

def proses():
global bola
rcm = hitungPusatMassa()
for i in arange(n):
gaya = hitungGaya(i,rcm)
r = bola[i].pos
#tambah gaya dari pusat
'''
jarak = mag(bola[i].pos)
arah = -norm(bola[i].pos)
gaya += 10*G*1./(pow(jarak,2)+.05)*arah
'''
a = gaya
v = bola[i].v
v += a*dt
r += v*dt
#cek pantul ke tembok
if bola[i].x > l/2.:
bola[i].x = l/2.
v.x *= -dv
elif bola[i].x < -l/2.:
bola[i].x = -l/2.
v.x *= -dv
elif bola[i].y > l/2.:
bola[i].y = l/2.
v.y *= -dv
if bola[i].y < -l/2.:
bola[i].y = -l/2.
v.y *= -dv
if bola[i].z > l/2.:
bola[i].z = l/2.
v.z *= -dv
if bola[i].z < -l/2.:
bola[i].z = -l/2.
v.z *= -dv

bola[i].pos = r

while 1:
rate (10)
proses()


.

Menjinakkan Gravitasi.

 Cari cara agar mereka jadi enak untuk dilihat.

 Di kode sebelumnya, bola sudah dicegah agar tidak melarikan diri dengan menambahkan kotak, mereka akan memantul jika menabrak kotak.

 Beres, sekarang tambahkan interaksi antar bola, interaksi sederhana, gravitasi.

 Ok, pake metode brutal, untuk tiap-tiap bola, hitung satu-satu interaksi gravitasi dengan seluruh bola, kemudian jumlahkan.


(ide, cari pusat masa seluruh bola, perlakukan interaksi gaya seperti kode sebelumnya)

 (saat nulis tadi, sambil mikir, ternyata itu ide buruk, tapi boleh juga, lihat saja nanti, bagus atau tidak)

 (tapi tidak sekarang, tidak masuk kode yang sekarang)

 (kode di posting ini tetap pake metode brutal)

 Hasilnya adalah, …, ok, mereka tetap memantul saat menabrak tembok, tetapi di dalam kotak mereka bergerak dengan sangat cepat, bola liar.

 (yep, metode brutal menghasilkan hasil brutal, tetapi tidak selalu…)

 Ide licik, tambahkan koefisien restitusi di dinding, tumbukan dengan dinding tidak lenting sempurna, kecepatannya tinggal 10% setelah memantul

 Dengan demikian mereka lebih jinak di dalam kotak, 🙂

from visual import *
from random import uniform,random

l = 17.
dl = .01
display(center=(0,0,0),background=(1,1,1),autoscale=False, width=600, height=600,forward=(-0.7,-0.7,-1))
distant_light(direction=(1,1,1), color=color.red)
#local_light(pos=(0,0,0), color=(0,0,1))
#sphere(pos=(0,0,0), color=(0,0,0), material=materials.emissive, opacity=0.9)

box(color=color.white, pos=(0,l/2,0),length=l,height=dl, width=l, opacity=0.3)
box(color=color.white, pos=(0,-l/2,0),length=l,height=dl, width=l, opacity=0.3)
box(color=color.white, pos=(l/2,0,0),length=dl,height=l, width=l, opacity=0.3)
box(color=color.white, pos=(-l/2,0,0),length=dl,height=l, width=l, opacity=0.3)
box(color=color.white, pos=(0,0,l/2),length=l,height=l, width=dl, opacity=0.3)

bola = []
n = 11
dv = .1 #kecepatan setelah menabrak dinding
G = 31.
for i in range(n):
ball = sphere (pos=(uniform(-7,7),uniform(-7,7),uniform(-7,7)), radius=.3, color=(random(),random(),random()))
ball.v = vector(uniform(-1,1),uniform(-1,1),uniform(-1,1))

bola.append(ball)


dt = 1./32.
bola[0].pos=(1,1,1)


def hitungGaya(i):
gaya = vector(0,0,0)
for j in arange(n):
if i!=j:
r = bola[i].pos-bola[j].pos
jarak = mag(r)
arah = -norm(r)
gaya += G*1./(pow(jarak,2)+.1)*arah
return gaya
def proses():
global bola
for i in arange(n):
gaya = hitungGaya(i)
#tambah gaya dari pusat
r = bola[i].pos
jarak = mag(bola[i].pos)
arah = -norm(bola[i].pos)
gaya += 10*G*1./(pow(jarak,2)+.05)*arah

a = gaya
v = bola[i].v
v += a*dt
r += v*dt
#cek pantul ke tembok
if bola[i].x > l/2.:
bola[i].x = l/2.
v.x *= -dv
elif bola[i].x < -l/2.:
bola[i].x = -l/2.
v.x *= -dv
elif bola[i].y > l/2.:
bola[i].y = l/2.
v.y *= -dv
if bola[i].y < -l/2.:
bola[i].y = -l/2.
v.y *= -dv
if bola[i].z > l/2.:
bola[i].z = l/2.
v.z *= -dv
if bola[i].z < -l/2.:
bola[i].z = -l/2.
v.z *= -dv

bola[i].pos = r

while 1:
rate (10)
proses()


.