Seite 1 von 1

Gravitationsfeld/-feldlinien, -simulation 2D

Verfasst: 22.03.2007 17:39
von Olaf
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).

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

Verfasst: 22.03.2007 18:34
von Macros
Hübsches Programm :allright:

2 meiner Meinung nach ganz hübsche Bahnen:
600/388
600/378

und die Längste, die ich gefunden habe:
600/376

dann gibt es da noch 391/391

wer findet ne längere :lol:

Verfasst: 22.03.2007 18:43
von ts-soft
[offtopic]
Mit EnableExplicit läuft der Code nicht :(
Warum deklariert den keiner auch die lokalen Variablen,
Code, Tipps und Tricks sollten vorbildlich sein!

Nur mal nebenbei bemerkt.
[/offtopic]

Hoffentlich mache ich mich jetzt nicht schon wieder unbeliebt :mrgreen:

Verfasst: 22.03.2007 22:00
von THEEX
Hmmm, nette Idee, aber müßte der Körper nicht irgendwo an einem Magneten hängen bleiben, anstatt irgendwo dann aus dem Bildschirm zu fliegen?

Verfasst: 22.03.2007 22:21
von Olaf
@CSprengel: Nee...es soll ja garkein Magnetpendel sein. Das hab ich ja nur so nebenbei erwähnt wegen der festen Massen.
Es soll lediglich die Gravitationskräfte simulieren. Aber 'n Magnetpendel könnte ich auch mal programmieren.

Verfasst: 23.03.2007 12:20
von Kukulkan
Hallo,

Ich finde das faszinierend. :allright:

Nur mal so ein Gedanke: Könnte man das nicht auch für die Kryptografie verwenden? Ich meine, man könnte die Position (XA, YA, XB, YB) und Stärke (NA, NB) von zwei Gravitationsfeldern definieren, die Start-Position (XP, YP) und Masse (MP) eines Punktes und dann anhand dessen auf die Position nach zB X Schritten zählen. Die Abweichung in einem der Faktoren sollte das Ergebnis doch (zum Teil) unvorhersehbar verändern, oder? Also man nehme XA,YA,XB,YB,NA,NB,XP,YP, MP und X. Das Ergebnis ist dann XP und YP nach der Zeit X. Als Schlüssel können nun zB die Positionen der Massen funktionieren, oder?

Volker

Verfasst: 23.03.2007 12:26
von Olaf
@Volker Schmid:
Ja, an sowas hab ich auch schon gedacht. Müsste funktionieren. Kannst ja mal rumprobieren. :wink:

Verfasst: 23.03.2007 15:14
von bluejoke
Hallo!

Da ich über Verschlüsselungstechnik eine Arbeit schreiben soll interessiert mich das genauer: Wollt ihr da eine Symmetrische oder Asymmetrische Verschlüsselung probieren?

Simon

Verfasst: 23.03.2007 15:28
von Tafkadasom2k5
Wenn ich das richtig verstehe, ist sie dann doch symmetrisch, weil man (sofern ich das verstehe) die gleichen Parameter, sowie den richtigen Algorhytmus für diese Schwerkraft-Simulation braucht, um den Klartext zu erzeugen, oder?

Gr33tz
Tafkadasom2k5

Verfasst: 23.03.2007 16:11
von Olaf
@Tafkadasom2k5: richtig verstanden :lol:
Ja, in dem Fall wäre es ne symmetrische Verschlüsselung.
@bluejoke: Falls es dich interessiert, hab ich noch ne asymmetrische Verschlüsselung entwickelt:
Über ne Maske werden die Bits in nem Byte vertauscht.
Hierbei ist der Entschlüsselungskey aber 'n anderer als der Verschlüsselungskey.
Wenns dich interessiert, kann ich dir den Code auch mal geben bzw. mal posten. :wink: