Seite 1 von 1

Trick - ProcedureReturn für "kleine" Strukturen

Verfasst: 07.08.2011 17:28
von STARGÅTE
Es scheint ja immer wieder Leute zu geben, die Probleme damit haben, dass Prozeduren keine Strukturen zurück geben können.
Um mal eine andere Möglichkeit, außer die Benutzung von Pointer innerhalb der Parameter, zu zeigen, möchte ich hier mal folgenden "trickreichen" Code zeigen, um zB. zwei Floats (also ein 2D-Vektor) zurück zu geben:

Der Trick ist, den größtmöglichen Standard-Typ (Quad) als Speicherbuffer für zB zwei Floats zu "missbrauchen".
Außerhalb wird diese Mini-Struktur dann wie eine Quad behandelt.
Innerhalb der Prozeduren kann man sich die beiden Floats aufschlüsseln.

Mit Hilfe einiger geeigneter Prozeduren kann man sich damit schnell eine Include für 2D-Vektoren bauen, die ohne Pointer auskommt:

Code: Alles auswählen


Structure Float2D
	StructureUnion
		Quad.q : Float.f[2]
	EndStructureUnion
EndStructure

Procedure.q Float2D(X.f, Y.f)
	Protected Object.Float2D
	Object\Float[0] = X : Object\Float[1] = Y
	ProcedureReturn Object\Quad
EndProcedure

Procedure.q Plus2D(A.q, B.q)
	Protected *Object1.Float2D = @A, *Object2.Float2D = @B
	ProcedureReturn Float2D(*Object1\Float[0]+*Object2\Float[0], *Object1\Float[1]+*Object2\Float[1])
EndProcedure

Procedure.q Minus2D(A.q, B.q)
	Protected *Object1.Float2D = @A, *Object2.Float2D = @B
	ProcedureReturn Float2D(*Object1\Float[0]-*Object2\Float[0], *Object1\Float[1]-*Object2\Float[1])
EndProcedure

Procedure.q Times2D(A.q, Factor.f)
	Protected *Object.Float2D = @A
	ProcedureReturn Float2D(*Object\Float[0]*Factor, *Object\Float[1]*Factor)
EndProcedure

Procedure.f Scalar2D(A.q, B.q)
	Protected *Object1.Float2D = @A, *Object2.Float2D = @B
	ProcedureReturn *Object1\Float[0]**Object2\Float[0] + *Object1\Float[1]**Object2\Float[1]
EndProcedure

Procedure.q Rotate2D(A.q, Angle.f)
	Protected *Object.Float2D = @A
	ProcedureReturn Float2D(*Object\Float[0]*Cos(Angle)-*Object\Float[1]*Sin(Angle), *Object\Float[0]*Sin(Angle)+*Object\Float[1]*Cos(Angle))
EndProcedure

Procedure.f Abs2D(A.q)
	ProcedureReturn Sqr(Scalar2D(A, A))
EndProcedure

Procedure.q Normalize2D(A.q)
	Protected Abs.f = Abs2D(A)
	If Abs
		ProcedureReturn Times2D(A, 1/Abs)
	Else
		ProcedureReturn A
	EndIf
EndProcedure

Procedure.s Return2D(A.q)
	Protected *Object.Float2D = @A
	ProcedureReturn StrF(*Object\Float[0])+" , "+StrF(*Object\Float[1])
EndProcedure

Procedure.f ReturnX(A.q)
	Protected *Object.Float2D = @A
	ProcedureReturn *Object\Float[0]
EndProcedure

Procedure.f ReturnY(A.q)
	Protected *Object.Float2D = @A
	ProcedureReturn *Object\Float[1]
EndProcedure



A.q = Float2D(3, 4)
Debug Return2D(A)
Debug ReturnX(A)
Debug ReturnY(A)
Debug Abs2D(A)
Debug ""

C.q = Minus2D(A, Float2D(3.0, -0.5))
Debug Return2D(C)
Debug ""

D.q = Rotate2D(Float2D(1.0, 0.0), Radian(45))
Debug Return2D(Times2D(D,100))
Debug ""

Debug Return2D(Normalize2D(Float2D(3,4)))