Macros zur Vektorrechnung

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Macros zur Vektorrechnung

Beitrag von NicTheQuick »

Hallo alle miteinander!

Ich habe mir gerade mal die Zeit genommen und ein paar alte Procedures
von mir zur Vektorrechnung umgeschrieben, damit es (hoffentlich) schneller
wird.
Bei ein paar Macros bin ich mir nicht sicher, ob es so schneller ist, deswegen
hab ich da noch die äquivalente Procedure belassen. Wer zu viel Zeit hat,
kann ja mal Geschwindigkeitstests durchführen. Aber im Grunde müsste der
Geschwindigkeitsvorteil klar sein.

Manche Macros können direkt als Funktion benutzt werden, andere
bestehen aus mehreren Zeilen Code und sind reine "Subs", also geben
keinen Wert zurück und können demnach auch nicht in If-Abfragen oder
ähnlichem eingesetzt werden.

Hier der

Code: Alles auswählen

Structure Vector3D
  x.d
  y.d
  z.d
EndStructure

Structure Line3D
  s.Vector3D  ;Startpunkt (Start)
  d.Vector3D  ;Richtungsvektor (Direction)
EndStructure

;Gibt die Normale zu drei Punkten aus, die miteinander verbunden ein Dreieck ergeben
; [in]  p1          : 1. Punkt
; [in]  p2          : 2. Punkt
; [in]  p3          : 3. Punkt
; [out] n           : Normale
Macro GetNormal3PointsM(p1, p2, p3, n)
  n\x = (p2\y - p1\y) * (p3\z - p1\z) - (p2\z - p1\z) * (p3\y - p1\y)
  n\y = (p2\z - p1\z) * (p3\x - p1\x) - (p2\x - p1\x) * (p3\z - p1\z)
  n\z = (p2\x - p1\x) * (p3\y - p1\y) - (p2\y - p1\y) * (p3\x - p1\x)
EndMacro
Procedure GetNormal3Points(*p1.Vector3D, *p2.Vector3D, *p3.Vector3D, *n.Vector3D)
  Protected u.Vector3D, v.Vector3D
  
  u\x = *p2\x - *p1\x
  u\y = *p2\y - *p1\y
  u\z = *p2\z - *p1\z
  
  v\x = *p3\x - *p1\x
  v\y = *p3\y - *p1\y
  v\z = *p3\z - *p1\z
  
  *n\x = u\y * v\z - u\z * v\y
  *n\y = u\z * v\x - u\x * v\z
  *n\z = u\x * v\y - u\y * v\x
  
  ProcedureReturn #True
EndProcedure

;Gibt die Länge des Vektors aus
; [in]  v           : Vektor
; [out] RETURN      : Länge des Vektors
Macro GetLength(v)
  Sqr(v\x * v\x + v\y * v\y + v\z * v\z)
EndMacro

;Gibt die Länge des Vektors im Quadrat aus
; [in]  v           : Vektor
; [out] RETURN      : Länge des Vektors
Macro GetLengthSq(v)
  (v\x * v\x + v\y * v\y + v\z * v\z)
EndMacro

;Berechnet das Skalarprodukt zweier Vektoren
; [in]  a1          : 1. Vektor
; [in]  a2          : 2. Vektor
; [out] RETURN      : Skalarprodukt
Macro ScalarProduct(a, b)
  ((a\x * b\x) + (a\y * b\y) + (a\z * b\z))
EndMacro

;Gibt den Einheitsvektor eines Vektors zurück
; [in]  v           : Vektor (darf nicht (0|0|0) sein)
; [out] v_out       : Einheitsvektor
; RETURN            : #False, wenn die Länge des Vektors Null ist, sonst #True
Macro UnitVectorM(v, v_out)
  v_out\x = v\x / Sqr(v\x * v\x + v\y * v\y + v\z * v\z)
  v_out\y = v\y * v_out\x / v\x
  v_out\z = v\y * v_out\x / v\x
EndMacro
Procedure UnitVector(*v.Vector3D, *v_out.Vector3D)
  Protected l.d
  
  l = Sqr(*v\x * *v\x + *v\y * *v\y + *v\z * *v\z)
  
  If l = 0 : ProcedureReturn #False : EndIf
  l = 1 / l
  
  *v_out\x = *v\x * l
  *v_out\y = *v\y * l
  *v_out\z = *v\z * l
  
  ProcedureReturn #True
EndProcedure

;Berechnet das Vektorprodukt aus zwei Vektoren
; [in]  a           : 1. Vektor
; [in]  b           : 2. Vektor
; [out] axb         : Vektorprodukt
Macro CrossProduct(a, b, axb)
  axb\x = a\y * b\z - a\z * b\y
  axb\y = a\z * b\x - a\x * b\z
  axb\z = a\x * b\y - a\y * b\x
EndMacro

;Gibt den Abstand zweier Punkte zurück
; [in]  p1          : 1. Punkt
; [in]  p2          : 2. Punkt
; [out] RETURN      : Abstand
Macro DistanceM(p1, p2)
  Sqr((p2\x - p1\x) * (p2\x - p1\x) + (p2\y - p1\y) * (p2\y - p1\y) + (p2\z - p1\z) * (p2\z - p1\z))
EndMacro
Procedure.d Distance(*p1.Vector3D, *p2.Vector3D)
  Protected v.Vector3D
  
  v\x = *p2\x - *p1\x
  v\y = *p2\y - *p1\y
  v\z = *p2\z - *p1\z
  
  ProcedureReturn Sqr(v\x * v\x + v\y * v\y + v\z * v\z)
EndProcedure

;Gibt das Quadrat des Abstandes zweier Punkte zurück
; [in]  p1          : 1. Punkt
; [in]  p2          : 2. Punkt
; [out] RETURN      : Abstand²
Macro DistanceSqM(p1, p2)
  ((p2\x - p1\x) * (p2\x - p1\x) + (p2\y - p1\y) * (p2\y - p1\y) + (p2\z - p1\z) * (p2\z - p1\z))
EndMacro
Procedure.d DistanceSq(*p1.Vector3D, *p2.Vector3D)
  Protected v.Vector3D
  
  v\x = *p2\x - *p1\x
  v\y = *p2\y - *p1\y
  v\z = *p2\z - *p1\z
  
  ProcedureReturn (v\x * v\x + v\y * v\y + v\z * v\z)
EndProcedure

;Addiert einen Vektor zu einem anderen
; [in]  a           : Ausgangsvektor
; [out] a           : Ergebnisvektor (a + add)
; [in]  add         : zu addierender Vektor
Macro AddVector(a, add)
  a\x + add\x
  a\y + add\y
  a\z + add\z
EndMacro

;Subtrahiert einen Vektor von einem anderen
; [in]  a           : Ausgangsvektor
; [out] a           : Ergebnisvektor (a - sub)
; [in]  sub         : zu subtrahierender Vektor
Macro SubVector(a, sub)
  a\x - sub\x
  a\y - sub\y
  a\z - sub\z
EndMacro

;Gibt die Differenz zweier Vektoren zurück
; [in]  a           : 1. Vektor
; [in]  b           : 2. Vektor
; [out] diff        : Differenzvektor
Macro DiffVector(a, b, diff)
  diff\x = b\x - a\x
  diff\y = b\y - a\y
  diff\z = b\z - a\z
EndMacro

;Gibt die Verbindungslinie zwischen zwei Punkten zurück
; [in]  a           : 1. Punkt
; [in]  b           : 2. Punkt
; [out] line        : Linie zwischen den beiden Punkten
Macro TwoPoints2Line(p1, p2, line)
  line\d\x = p2\x - p1\x
  line\d\y = p2\y - p1\y
  line\d\z = p2\z - p1\z
  
  line\s\x = p1\x
  line\s\y = p1\y
  line\s\z = p1\z
EndMacro

;Errechnet den Winkel zwischen zwei Vektoren und gibt den Kosinus dazu aus
; [in]  a           : 1. Vektor
; [in]  b           : 2. Vektor
; [out] RETURN      : Kosinus des Winkels zwischen den Vektoren
Macro VectorCosinus(a, b)
  (((a\x * b\x) + (a\y * b\y) + (a\z * b\z)) / Sqr(((a\x * a\x) + (a\y * a\y) + (a\z * a\z)) * ((b\x * b\x) + (b\y * b\y) + (b\z * b\z))))
EndMacro

;Errechnet den Winkel zwischen zwei Vektoren
; [in]  a           : 1. Vektor
; [in]  b           : 2. Vektor
; [out] RETURN      : Winkel zwischen den Vektoren
Macro VectorAngle(a, b)
  ACos(((a\x * b\x) + (a\y * b\y) + (a\z * b\z)) / Sqr(((a\x * a\x) + (a\y * a\y) + (a\z * a\z)) * ((b\x * b\x) + (b\y * b\y) + (b\z * b\z))))
EndMacro

;Multipliziert einen Vektor mit einer skalaren Größe
; [in]  a           : Vektor
; [out] a           : Ergebnis
; [in]  s           : Multiplikator
Macro SMul(a, s)
  a\x * s
  a\y * s
  a\z * s
EndMacro

;Kopiert einen Vektor in einen anderen
; [out] Dest        : Vektor, der die Daten bekommt
; [in]  Source      : Vektor, der kopiert werden soll
Macro CopyVector(Dest, Source)
  Dest\x = Source\x
  Dest\y = Source\y
  Dest\z = Source\z
EndMacro