[Gelöst] Problem mit Vektorenberechnung

Hidden Evil

Moderator
Teammitglied
Hi Leute,

leider ist mein Abi schon eine weile her, daher komme ich einfach nicht darauf, mein Problem zu lösen. Eigentlich ist es eine Programmier-Angelegenheit, aber da diese Sprache hier sicher keiner kennt (falls doch: "Expression2" aus dem Spiel "Garrys Mod") und es eher auf die Mathematik -die sich mir nicht erschließt- zurück zu führen ist würde ich es auch bei der Mathematik belassen und selbst dann in den nötigen Code umwandeln.

Nunja, folgendes ist mein Problem:

Ich habe 2 räumliche Vektoren v1(x1|y1|z1) und v2(x2|y2|z2).

Ich benötige von dem Vektor, der zwischen den beiden räumlichen Punkten liegt (also v2-v1) nun einen Richtungs-Vektor mit dem Interval -1 bis 1 für delta-x, delta-y und delta-z, ausgehen vom Punkt v2, der auf den Punkt v1 zeigt. Ich meine, man kann über den Winkel mittels Sinus und Kosinus darauf kommen, allerdings habe ich keinen Plan, wie ich diese im dreidimensionalen Raum anwenden muss. Wikipedia ist mir dafür leider auch inzwischen zu kompliziert.

Ich habe das ganze noch einmal skiziert, damit deutlicher wird, wovon zum Geier ich denn da spreche :)

Vielleicht hat da jemand ja einen kleinen Tipp für mich, wäre echt klasse :)

//Edit: Ich merke gerade, dass ich y und z in der Skizze vertauscht habe. z ist die Höhen-Angabe, nicht y. :wand
 

Anhänge

  • vektoren-problem.png
    vektoren-problem.png
    13,8 KB · Aufrufe: 167
Wenn ich dich richtig verstanden habe, brauchst du also Radius und Richtung deines gelben relativen Vektors.
Dazu muss also erst durch Vektorsubtraktion der relative Vektor zum Koordinatenursprung (v2) berechnet werden.
Hast du schon, aber genau falsch herum (richtig: v1 - v2).
Als nächstes muss dieser relative Vektor (kartesische Koordinaten) in Kugelkoordinaten umgerechnet werden.

Ich habe das schon in der Skriptsprache Lua programmiert, dürfte eigentlich nicht allzu schwer zu verstehen sein.

Die beiden Funktionen zur Vektorsubtraktion und der Umrechnung:
Code:
[COLOR="#008000"]-- Subtrahiert 'Vektor2' von 'Vector1'.
-- Liefert z.B. die relative Position des Vektors 'Vector1' zum Koordinatenursprung 'Vector2'.[/COLOR]

SubVector = function( Vector1, Vector2 )
    return {
        Vector1[1] - Vector2[1],    [COLOR="#008000"]-- x[/COLOR]
        Vector1[2] - Vector2[2],    [COLOR="#008000"]-- y[/COLOR]
        Vector1[3] - Vector2[3]     [COLOR="#008000"]-- z[/COLOR]
    }
end


[COLOR="#008000"]-- Rechnet Kartesische Koordinaten (x,y,z) in Kugelkoordinaten (r, Phi, Theta) um.
-- Liefert eine Tabelle mit den Parametern 'Radius', 'Azimut' und 'Polar' zurück.[/COLOR]

GetVectorSpherical = function( Vector )
    local x = Vector[1]
    local y = Vector[2]
    local z = Vector[3]
    local sqrVec = x * x + y * y
    local polar = 0.0
    if sqrVec > 0 then
        polar = PI / 2.0 - math.atan( z / math.sqrt( sqrVec ) )
    end
    return {
        Radius = math.sqrt( sqrVec + z * z ),	[COLOR="#008000"]-- Radius (Länge des Vektors)[/COLOR]
        Azimut = math.atan2( y, x ),		[COLOR="#008000"]-- Azimutwinkel (Winkel des Vektors in der X/Z-Ebene)[/COLOR]
        Polar  = polar				[COLOR="#008000"]-- Polarwinkel  (Winkel zwischen Y-Achse und Vektor)[/COLOR]
    }
end

atan ist die Arcustangens-Funktion.
atan2 ist das gleiche wie atan, berücksichtigt jedoch auch den Quadranten.
Zwei Bindestriche leiten einen Kommentar ein.
Geschweiftes Klammerpaar ist eine Tabelle (Array), in der zweiten Funktion eine Hash-Tabelle mit benannten Feldern.

Nun die Berechnung mit den beiden Funktionen:
Code:
[COLOR="#008000"]-- Relativen Vektor berechnen:[/COLOR]
RelativerVektor = SubVector( v1, v2 )

[COLOR="#008000"]-- Umwandlung des kartesischen Vektors in Kugelkoordinaten:[/COLOR]
Kugelkoordinaten = GetVectorSpherical( RelativerVektor )

[COLOR="#008000"]-- Radius, Azimutwinkel und Polarwinkel:[/COLOR]
r     = Kugelkoordinaten.Radius
Phi   = Kugelkoordinaten.Azimut
Theta = Kugelkoordinaten.Polar

Vielleicht hilfts dir oder gibt zumindest einen Ansatzpunkt.
 
Zuletzt bearbeitet:
Du hast mir schon sehr damit geholfen, da ich nicht auf die Idee gekommen bin, in Polar-Koordinaten umzuwandeln. Und das, obwohl ich in einer anderen Funktion des gesamten Werks genau dies bereits getan hatte :wand

Ich rechne diesen Vektor einfach in Polar-Koordinaten um und mit Hilfe der Winkel wandel ich diese mit einem Radius von 1 wieder in kartesische Koordinaten um. Das dürfte hinhauen, wenn es nicht an der Umsetzung scheitert :angel

Vielen Dank soweit :), ich werde das aber erst Sonntag ausprobieren können.
 
Mag sein, dass ich es falsch verstanden, bin auch grad auf meim Handy unterwegs, aber ich geb ma meinen Senf dazu:

Du willst lediglich deinen (v1-v2)-Vektor so kurz machen, dass die jeweiligen Elemente nicht größer als 1 sind?
MeineMathe-Profs nennen das Normalisieren und machen das mit dem Kehrwert der Quadratischen Norm. Klingt fancy, ist aber nichts weiter als, dass du die Länge deines Vektors mit Pythargoras bestimmst und deinen Vektor dann dadurch teilst. Der Vektor hat danach die Länge 1.

Quadratnorm/Länge: ||V||2 = sqrt(v1^2+v2^2+v3^2)
Ist halt Pythargoras im 3-Dimensionalen.

Aus der Formel ergibt sich auch, dass die jeweiligen Werte der Bestandteile eines Vektors der Länge 1 selbst nicht größer als 1 sein können. Wenn eine Komponente 1 bzw. -1 ist, sind alle anderen Null.

Norberts Version hab ich mir nicht ganz durchgelesen, ich habs nicht so mit Code.
Aber Transformation in Kreiskoord., Teilen durch R und Rücktransformation klingt für mich nach genau dem gleichen wie meins in kompliziert.
 
@Hidden Evil:
Für das Normalisieren (Vektorlänge 1) und der Umrechnung in kartesische Koordinaten habe ich die Funktionen auch parat, wenn du sie brauchen solltest. :)

edit:
Noch ein Hinweis, die Funktionen oben rechnen bei den Winkeln immer mit dem Bogenmaß "rad". Dürfte aber durch den Einsatz der Kreiszahl Pi eigentlich klar sein.


edit2:
Das sehe ich ja jetzt erst...
"wieder in kartesische Koordinaten umwandeln"... du meine Güte, da hab ich wieder mal viel zu kompliziert gedacht.
Die Polarkoordinaten braucht es in dem Fall ja gar nicht, das geht viel einfacher.

1. Wie schon geschrieben, Vektorsubtraktion von v1 - v2 = relativer Vektor:
x = x1 - x2 | y = y1 - y2 | z = z1 - z2

2. Vektorlänge berechnen:
r = sqrt( x * x + y * y + z * z )

3. Normalisieren (ggf. erst die Länge auf 0 prüfen, sonst Division durch Null):
Faktor = 1 / r
xp = x * Faktor | yp = y * Faktor | zp = z * Faktor
oder einfacher, falls der Umrechnungsfaktor später nicht nochmal gebraucht wird:
xp = x / r | yp = y / r | zp = z / r
Jetzt hast du den Vektor für das Intervall von 0 bis 1.

4. Gegenvektor für das Intervall von -1 bis 0 bilden:
xm = -xp | ym = -yp | zm = -zp

Sollte das Intervall bei -1 aber schon am Punkt v2 beginnen, muss nur der Faktor geändert werden:
Faktor = 0.5 / r
Damit hätten Vektor und Gegenvektor zusammen die Länge 1.

Nun kannst du durch Multiplikation mit einem Faktor den Vektor auf jede beliebige Länge bringen
und durch Vektoraddition verschiebst du ihn im Raum auf jeden beliebigen Koordinatenursprung.

Einen Vorteil hätte die Berechnung mit Hilfe von Polarkoordinaten aber dennoch:
Wenn du bei den Berechnungen mal mit dem Vektor im Koordinatenursprung (0|0|0) landen solltest, ist Ende Gelände mit den kartesischen Koordinaten. Das ist wie ein Schwarzes Loch, dort kommst du nicht mehr raus. Mit den Polarkoordinaten hättest du dagegen immer noch die Richtung mit den beiden Winkeln, nur die Vektorlänge wird zu Null. Da setzt man halt eine neue ein, die einem sinnvoll erscheint, und weiter gehts. Selbst wenn beide Winkel gleich Null sind, ist das immer noch eine Richtung, dann gehts halt in Richtung Nordpol weiter. :)
 
Zuletzt bearbeitet:
Sorry für Doppelpost, ist nur wegen der Autobenachrichtigung und kann mit obigen Post zusammengeführt werden, wenn du es gelesen hast, Hidden Evil.

Hab da noch etwas, das ganz nützlich sein könnte als Vorlage zur Veranschaulichung, vor allem, wenn wie in Darkstar One das Kugelkoordinatensystem nicht dem üblichen Standard entspricht. Der Betrachter schaut dort nicht von außen auf das System, sondern sitzt im Koordinatenursprung (0|0|0) und guckt in Richtung des imaginären äußeren Betrachters, wodurch die Richtungen der x-Achse von außen gesehen vertauscht sind. Und um das Maß voll zu machen, sind auch noch y- und z-Achse für die Berechnung der Polarkoordinaten praktisch vertauscht, haben aber ihre ursprüngliche Bezeichnung beibehalten. Für die Berechnung der kartesischen Koordinaten bleiben die Achsen aber mit Ausnahme der x-Richtungen wie gehabt. Keine Ahnung, was sich der Ex-Entwickler Ascaron damals dabei gedacht hatte.

In der Grafik entspricht die obere Kugel dem allgemeinen Standard mit den Winkeln, die Achsenbezeichnungen kann man sich selber wie gewünscht hinein malen. Die mittlere und untere Kugel sind nur Kopien von der oberen ohne den Winkeln, die kann man sich dort also auch selbst definieren. Koordinatensysteme kann man sich ja nach Belieben auslegen und muss dann halt nur bei dem einen bleiben, sonst wird's ganz irre mit den Umrechnungen.

Leider habe ich die Grafik nicht größer, aber zum darin herum Malen nach dem Ausdrucken dürfte es reichen und für Formeln ist links und rechts auch noch Platz. Freilich kann man den Ausdruck auch größer skalieren.


Dann noch etwas, falls es dich interessieren sollte:
Im Download-Archiv Darkstar One v2.1.2.rar meiner Mod befinden sich zwei Dateien namens MissionLib.lua und MissionLibEx.lua im Verzeichnis "\Darkstar One\lua\mission", welche ein Teil der Funktionsbibliotheken darstellen. Besonders in der großen komplett von mir erstellten MissionLibEx.lua befinden sich eine Menge Vektorberechnungen ab etwa Zeile 6600, in der anderen aber nur 2 einfache Grundfunktionen. Ist alles in Lua, was zumindest bei den Standard-Funktionen ein wenig Ähnlichkeit mit deinem Expression 2 - Wiremod Wiki hat. Vielleicht kannst du das ja gebrauchen.
(Wofür werden denn dort 4D-Vektoren gebraucht? Das würde mich doch mal interessieren. Ist der Hyperraum denn real? :ROFLMAO:)
 

Anhänge

  • Kugelkoordinaten.jpg
    Kugelkoordinaten.jpg
    104,4 KB · Aufrufe: 146
Auf die Gefahr hin, dass Ihr mich hassen werdet, aber ich muss Euch gestehen, dass ich mal wieder in eine Friteuse getreten bin. :wand

Der Compiler hat eine eigene Funktion, um einen Vektor zu normalisieren. Ich wusste nur leider nicht, dass das, was ich umsetzen wollte, auch schon erfunden wurde und "Normalisierung" genannt wurde. Die Funktion "V:normalized()", um einen normalisierten Vektor des angegebenen "V" zu erstellen, war daher nicht mehr schwer zu finden.

"Test=(V1-V2):normalized()" war also das Ende von diesem riesigen Lied.

Ich danke Euch gaaanz herzlich für all die Mühe, die Ihr auf Euch genommen habt um mir zu helfen. Immerhin hat es den erfreulichen Nebeneffekt, dass ich mein altes Wissen wieder auffrischen konnte. Und nun verkrümele ich mich ganz schnell, bevor ich was von Euch auf die Nuss bekomme :weg

PS: Den Link kannte ich schon (danke trotzdem :)), allerdings war mir halt, wie schon gesagt, die Funktion nicht namentlich bekannt.
 
Hatte ich auch beim Überfliegen des Wiki-Links gesehen, dass die und noch viel mehr Vektor-Funktionen drin sind.
In Lua musste ich mir ja etliche selber stricken, da dort standardmäßig wesentlich weniger vorhanden sind.

Aber das macht nichts, so weißt du wenigstens wieder, wie das berechnet wird und jene Funktion innen drin tickt.
Sonst hat man am Ende nur noch Funktionen als Black Boxen, ohne zu wissen, wie die das eigentlich machen. ;)

Kannst also hier bleiben, die Nüsse hebe ich mir für den Kuchen auf. :D :)

BTW: Für die 4D-Vektoren ist mir sogar selber noch eine Anwendung eingefallen. Und zwar habe ich beispielsweise eine Vektorberechnung zur Ermittlung des geometrischen Schwerpunkts beliebig vieler Objekte als Funktion erstellt. Möchte man nun den gravitatorischen Schwerpunkt haben, könnte man die Masse als vierten Vektorwert zur Gewichtung des räumlichen 3D-Vektors mit einsetzen.
 
Oben