Gravitationsfeld/-feldlinien, -simulation 2D
Verfasst: 22.03.2007 17:39
Mal ne kleine Simulation zur Bewegung eines Körpers im 2dimensionalen Raum, der von 4 Massen (kann im
Quellcode beliebig verändert werden) angezogen wird. In diesem Fall sind die Massen jedoch fest und nicht selbst
beweglich (vgl. Magnetpendel).
Quellcode beliebig verändert werden) angezogen wird. In diesem Fall sind die Massen jedoch fest und nicht selbst
beweglich (vgl. Magnetpendel).
Code: Alles auswählen
Enumeration
#Window
#ImageGadget
#XText
#XSpin
#YText
#YSpin
#Start
#Pause
#Stop
#Erase
#ActX
#ActY
#Kraftfeld
#Hintergrund
#HintergrundThread
#Display
EndEnumeration
Structure df
fx.d
fy.d
EndStructure
Structure mass
x.d
y.d
m.d
EndStructure
Global Gravitation_Const.d=1,StdMass.d=1
Global NewList Masses.mass()
m.d=1000000
Dist.d=200
Global w.l,h.l,KoordX.l,KoordY.l
w=600
h=600
KoordX=457
KoordY=254
CreateImage(#Hintergrund,w*2,h)
CreateImage(#HintergrundThread,w*2,h)
CreateImage(#Kraftfeld,w,h)
CreateImage(#Display,w*2,h)
Raster=40
radius=2*Raster/40
First=1
If First<>0
AddElement(Masses())
Masses()\x=300+Cos(60*#PI/180)*Dist
Masses()\y=300+Sin(60*#PI/180)*Dist
Masses()\m=m
EndIf
Second=1
If Second<>0
AddElement(Masses())
Masses()\x=300+Cos(180*#PI/180)*Dist
Masses()\y=300+Sin(180*#PI/180)*Dist
Masses()\m=m
EndIf
Third=1
If Third<>0
AddElement(Masses())
Masses()\x=300+Cos(300*#PI/180)*Dist
Masses()\y=300+Sin(300*#PI/180)*Dist
Masses()\m=m
EndIf
Fourth=1
If Fourth<>0
AddElement(Masses())
Masses()\x=300
Masses()\y=300
Masses()\m=m
EndIf
Procedure.d Absolute(*Vector.df)
Distance.d=Sqr(*Vector\fx**Vector\fx+*Vector\fy**Vector\fy)
ProcedureReturn Distance
EndProcedure
Procedure.l GetColor(Absolute.d)
;ColorSeed.c=Int(Sqr(Absolute)/680*255)
ColorSeed=Int(Absolute)
Color.l=RGB(255-ColorSeed,255-ColorSeed,255)
ProcedureReturn Color
EndProcedure
Procedure.d GetAngle(Sin.d,Cos.d)
Angle.d=ATan(Sin/Cos)
If Sin<0 And Cos<0
Angle+#PI
ElseIf Cos<0 And Sin>=0
Angle+#PI
ElseIf Sin<0 And Cos>=0
Angle+2*#PI
EndIf
If Angle>2*#PI
Angle-2*#PI
EndIf
ProcedureReturn Angle
EndProcedure
Procedure GetGravitation(x.d,y.d,*Vector.df)
ResetList(Masses())
*Vector\fx=0
*Vector\fy=0
While NextElement(Masses())
deltax.d=(x-Masses()\x)
deltay.d=(y-Masses()\y)
r.d=Sqr(deltax*deltax+deltay*deltay)
F.d=-Gravitation_Const*StdMass*Masses()\m/(r*r)
*Vector\fx+F*deltax/r
*Vector\fy+F*deltay/r
Wend
EndProcedure
Procedure DrawTestMass(x,y)
If x<=w
Circle(x,y,4,RGB(200,200,200))
Circle(x,y,3,RGB(000,128,128))
EndIf
EndProcedure
Procedure Simulation()
CopyImage(#Hintergrund,#HintergrundThread)
x.d=KoordX
y.d=KoordY
TimeStep=8
Repeat
GetGravitation(x,y,Kraft.df)
ax.d=Kraft\fx/StdMass
ay.d=Kraft\fy/StdMass
vx.d=vx+ax*TimeStep/1000
vy.d=vy+ay*TimeStep/1000
x =x +vx*TimeStep/1000
y =y +vy*TimeStep/1000
StartDrawing(ImageOutput(#HintergrundThread))
;Circle(Int(x) ,Int(y),1,RGB(000,128,128))
Circle(Int(x+w),Int(y),1,RGB(000,128,128))
StopDrawing()
StartDrawing(ImageOutput(#Display))
DrawImage(ImageID(#HintergrundThread),0,0)
DrawTestMass(Int(x) ,Int(y))
;DrawTestMass(Int(x+w),Int(y))
StopDrawing()
SetGadgetState(#ImageGadget,ImageID(#Display))
SetGadgetText(#ActX,"Aktuell X: "+Str(x))
SetGadgetText(#ActY,"Aktuell Y: "+Str(y))
Delay(TimeStep/2)
Until x>w Or y>h Or x<0 Or y<0
DisableGadget(#Start,0)
DisableGadget(#Pause,1)
DisableGadget(#Stop ,1)
DisableGadget(#XSpin,0)
DisableGadget(#YSpin,0)
DisableGadget(#Erase,0)
Repeat
Delay(10)
ForEver
EndProcedure
Procedure Erase()
StartDrawing(ImageOutput(#Display))
DrawImage(ImageID(#Hintergrund),0,0)
DrawTestMass(KoordX,KoordY)
StopDrawing()
SetGadgetState(#ImageGadget,ImageID(#Display))
SetGadgetText(#ActX,"Aktuell X: "+Str(KoordX))
SetGadgetText(#ActY,"Aktuell Y: "+Str(KoordY))
EndProcedure
OpenWindow(#Window,0,0,w*2,h+40,"Gravitationsfeld, -linien und -simulation",#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
StartDrawing(ImageOutput(#Kraftfeld))
For x=0 To w
For y=0 To h
GetGravitation(x,y,Vector.df)
Abs.d=Absolute(Vector)
Plot(x,y,Int(Abs))
Next y
Next x
StopDrawing()
StartDrawing(ImageOutput(#Hintergrund))
DrawImage(ImageID(#Kraftfeld),0,0)
For x=0 To w
For y=0 To h
If x%Raster=0 And y%Raster=0 And x<w And y<h And x<>0 And y<>0
GetGravitation(x,y,Vector.df)
Angle.d=GetAngle(Vector\fy,Vector\fx)
dx.l=Int(Cos(Angle)*10*Raster/40)
dy.l=Int(Sin(Angle)*10*Raster/40)
dA.d=#PI/6+#PI
dxp1.l=Int(Cos(Angle+dA)*7*Raster/40)
dyp1.l=Int(Sin(Angle+dA)*7*Raster/40)
dxp2.l=Int(Cos(Angle-dA)*7*Raster/40)
dyp2.l=Int(Sin(Angle-dA)*7*Raster/40)
Circle(x,y,radius,16777215)
Line(x-dx,y-dy,dx*2,dy*2,16777215)
Line(x+dx,y+dy,dxp1,dyp1,16777215)
Line(x+dx,y+dy,dxp2,dyp2,16777215)
Circle(x+w,y,radius,16777215)
Line(x-dx+w,y-dy,dx*2,dy*2,16777215)
Line(x+dx+w,y+dy,dxp1,dyp1,16777215)
Line(x+dx+w,y+dy,dxp2,dyp2,16777215)
EndIf
Next y
Next x
StopDrawing()
StartDrawing(ImageOutput(#Display))
DrawImage(ImageID(#Hintergrund),0,0)
DrawTestMass(KoordX,KoordY)
StopDrawing()
CreateGadgetList(WindowID(#Window))
ImageGadget(#ImageGadget,0,0,w*2,h,ImageID(#Display))
TextGadget(#XText, 10,h+10 ,40,20,"Start-X:")
StringGadget(#XSpin, 50,h+10-3,60,20,Str(KoordX),#PB_String_Numeric|#PB_Text_Right)
TextGadget(#YText,120,h+10 ,40,20,"Start-Y:")
StringGadget(#YSpin,160,h+10-3,60,20,Str(KoordY),#PB_String_Numeric|#PB_Text_Right)
ButtonGadget(#Start,280,h+10-3,50,20,"Start")
ButtonGadget(#Pause,340,h+10-3,50,20,"Pause")
DisableGadget(#Pause,1)
ButtonGadget(#Stop, 400,h+10-3,50,20,"Stop")
DisableGadget(#Stop ,1)
ButtonGadget(#Erase,460,h+10-3,50,20,"Löschen")
DisableGadget(#Erase,1)
TextGadget(#ActX,520,h+10,70,20,"Aktuell X: "+Str(KoordX))
TextGadget(#ActY,600,h+10,70,20,"Aktuell Y: "+Str(KoordY))
Repeat
event=WaitWindowEvent()
Select event
Case #PB_Event_Gadget
Select EventGadget()
Case #XSpin
KoordX=Val(GetGadgetText(#XSpin))
If KoordX>w
KoordX=w
SetGadgetText(#XSpin,Str(KoordX))
ElseIf KoordX<0
KoordX=0
SetGadgetText(#XSpin,Str(KoordX))
EndIf
StartDrawing(ImageOutput(#Display))
DrawImage(ImageID(#Hintergrund),0,0)
DrawTestMass(KoordX,KoordY)
StopDrawing()
SetGadgetState(#ImageGadget,ImageID(#Display))
Case #YSpin
KoordY=Val(GetGadgetText(#YSpin))
If KoordY>h
KoordY=h
SetGadgetText(#YSpin,Str(KoordY))
ElseIf KoordY<0
KoordY=0
SetGadgetText(#YSpin,Str(KoordY))
EndIf
StartDrawing(ImageOutput(#Display))
DrawImage(ImageID(#Hintergrund),0,0)
DrawTestMass(KoordX,KoordY)
StopDrawing()
SetGadgetState(#ImageGadget,ImageID(#Display))
Case #Start
If IsThread(Simulation)
KillThread(Simulation)
EndIf
Simulation=CreateThread(@Simulation(),0)
DisableGadget(#Start,1)
DisableGadget(#Pause,0)
DisableGadget(#Stop ,0)
DisableGadget(#XSpin,1)
DisableGadget(#YSpin,1)
DisableGadget(#Erase,1)
Case #Pause
If IsThread(Simulation)
If ThreadPaused=0
ThreadPaused=1
PauseThread(Simulation)
ElseIf ThreadPaused=1
ThreadPaused=0
ResumeThread(Simulation)
EndIf
EndIf
Case #Stop
If IsThread(Simulation)
KillThread(Simulation)
EndIf
DisableGadget(#Start,0)
DisableGadget(#Pause,1)
DisableGadget(#Stop ,1)
DisableGadget(#XSpin,0)
DisableGadget(#YSpin,0)
DisableGadget(#Erase,0)
Case #Erase
DisableGadget(#Erase,1)
Erase()
EndSelect
EndSelect
Until event=#PB_Event_CloseWindow