![]() |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Zitat:
Mein „Kreuzprodukt“ ist im Grunde das Skalarprodukt mit einem Vektor orthogonal zu Vektor B. Du kannst im zweidimensionalen Raum ja leicht einen orthogonalen Vektor bilden, indem du die Koordinaten wie folgt vertauschst: (X, Y) → (Y, -X). Wenn du das dann in das Skalarprodukt einsetzt, kommst du auf meine Formel. |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Hmm... Siehe Edit
|
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Zitat:
|
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Danke, ja ich habe #2 gemeint. Da scheint das kein "x" zu sein, sondern einfach ein "*"..
|
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Zitat:
Bei Kurven gilt das übrigens nicht mehr, was auch bei mir der Grund war meine Splines in eine Serie von Strecken aufzulösen bevor ich die Abstände berechnet habe. (So ähnlich schaut das beim TE auch aus.) Das ging flotter als Schnitte mit Funktionen 3. Grades (plus Normalenberechnung auf einer kontinuierlichen Funktion), selbst bei Subpixelauflösung. Fazit: So lange alles linear bleibt, ist der orthogonale Abstand auch der kleinste (bzw. kleinst-mögliche). \\Edit: Lösung: Berechne die Normale zu deinen "Vektoren" (aka Strecken, aka begrenzten Geraden) nach der von NamenLozer genannten Weise. Bilde mit diesen Normalen eine Gerade, die auf deinem "grünen Punkt" fußt, und berechne die Schnittpunkte zwischen diesen und den von deinen "Vektoren" gebildeten Geraden. Dabei bekommst du jeweils zwei skalare Parameter, einer, der sagt um wie viel der Länge deiner "Vektoren" verschoben der Schnittpunkt liegt (so lange du diese nicht vorher noch umherskalierst). Ist dieser innerhalb (0, 1), dann ist der Abstand zwischen dem Schnittpunkt und deinem grünen Punkt einer der beiden Kandidaten. Dann einfach den Abstand zwischen den 2 Schnittpunkten und deinem grünen berechnen, und der kleinere ist es. (Mit etwas Geschick kann dafür auch der 2. Parameter verwendet werden, aber da in der Regel eh skaliert/normalisiert werden müsste, ist es in der Praxis nahezu gleich schnell einfach die Abstände "naiv" zu berechnen). Sollte einer/beide der Parameter ausserhalb (0, 1) liegen, musst du den Abstand vom grünen Punkt zu den zwei Randpunkten der betroffenen Strecke(n) bilden, und der kleinere ist dann der Abstand zu der jeweiligen Strecke. Der abschließende Vergleich bleibt natürlich gleich. |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Hi, bin über Ostern zu nichts gekommen und wollte mich noch kurz für die vielen Hilfestellungen bedanken.
Bei mir geht es um einen Graphischen Editor in welchem User per Klick neue Punkte eintragen können und die Punkte sind fortlaufend sortiert. (Nicht Räumlich sonder in der zugefügten Reihenfolge) Zusätzlich sollen aber nun Punkte auch in den räumlichen Aspekt eingefügt werden können und dafür muss ich meine Reihe "aufbrechen" um die Punkte korrekt einzufügen und nicht anzuhängen. ;) ps.: hat garnichts mit spielen zu tun :| |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Liste der Anhänge anzeigen (Anzahl: 1)
Also entweder so, wie bei
![]() |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Irks, wo Trigonometrie vermeidbar ist, sollte man das finde ich auch tun. Die ist langsam, anfällig für unerwartete Fehler (Polstellen und so Gemeinheiten), und gerade in der Nähe von Grenzfällen auch hart an der sinnvoll verwendbaren Genauigkeit von Floats. Das ist alles prima mit schöner, schlanker linearen Algebra lösbar, was fast immer der bessere Weg ist, wenn er möglich ist.
Edit: Zudem würde man so auch ein unsinniges "h" bekommen, wenn die Höhe nicht mehr auf der Hypotenuse steht, sondern auf ihrer Verlängerung zur Geraden. Das wäre der gleiche Fall, der bei einer algebraischen Lösung (Geradenschnitt) einen Parameter ausserhalb (0, 1) liefert, und dadurch sehr einfach erkenn- und behandelbar ist. |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Okay Ich habe jetzt weitestgehend Antwort7 umgesetzt und auch einen Vektor2D eingeführt.
Delphi-Quellcode:
Meine Funktionen zur Vektorrechnung sehen so aus:
function TSetPoints.PrevLineCloser(Index : Integer; X, Y : Double): Boolean;
var NewPoint : TFloatPoint; A : TVector2d; B : TVector2d; B0 : TVector2d; H1, H2 : Double; PrevPoint, NextPoint, IndexPoint : TFloatPoint; begin Result := True; NewPoint.X := X; NewPoint.Y := Y; PrevPoint.X := FPoints[Index - 1].FX; PrevPoint.Y := FPoints[Index - 1].FY; NextPoint.X := FPoints[Index + 1].FX; NextPoint.Y := FPoints[Index + 1].FY; IndexPoint.X := FPoints[Index].FX; IndexPoint.Y := FPoints[Index].FX; A := Vector2DGetFromTwoPoints(PrevPoint, NewPoint); B := Vector2DGetFromTwoPoints(PrevPoint, IndexPoint); B0 := Vektor2DMultiplyTwo(Vektor2DDivideWithFloat(B,1), B); H1 := Vector2DCrossProduct(A, B0); A := Vector2DGetFromTwoPoints(NextPoint, NewPoint); B := Vector2DGetFromTwoPoints(NextPoint, IndexPoint); B0 := Vektor2DMultiplyTwo(Vektor2DDivideWithFloat(B,1), B); H2 := Vector2DCrossProduct(A, B0); if (H1 < H2) then Result := False; end;
Delphi-Quellcode:
function Vector2DCrossProduct(Vekt1, Vekt2 : TVector2D) : Double;
begin Result := Vekt1.X * Vekt2.Y - Vekt1.Y * Vekt2.X; end;
Delphi-Quellcode:
function Vektor2DMultiplyTwo(Vekt1 : TVector2D; Vekt2 : TVector2D) : TVector2d;
begin Result.X := Vekt1.X + Vekt2.X; Result.Y := Vekt1.Y + Vekt2.Y; end;
Delphi-Quellcode:
function Vektor2DDivideWithFloat(Vekt : TVector2D; Value : Double) : TVector2d;
begin Result.X := Value / Vekt.X; Result.Y := Value / Vekt.X; end;
Delphi-Quellcode:
Mein Vektor2D record ist so von euch übernommen:
function Vector2DPointToOrt(P1 : TFloatPoint) : TVector2d;
begin Result.X := P1.X; Result.Y := P1.Y; end;
Delphi-Quellcode:
Die Floatpoints sind:
TVector2d = record
procedure Assign(const newX, newY: Double); function Length: Double; case Boolean of False: (X: Double; Y: Double); True: (Values: Array[0..1] of Double); end;
Delphi-Quellcode:
Jetzt habe Ich leider immernoch nicht das gewünschte Verhalten, scheinbar sind H1 und H2 noch nicht wirklich das, was sie sein sollen. Ich Debugge nochmal ein bisschen und Poste hier meine Sourcen.
TFloatPoint = packed record
X : Single; Y : Single; end; |
AW: 2 Vektoren und 1 Punkt, wo näher drann?
Ich sehe hier einen Fehler:
Delphi-Quellcode:
B0 := Vektor2DMultiplyTwo(Vektor2DDivideWithFloat(B,1), B);
Wenn Vektor2DMultiplyTwo das tun würde, was man erwartet (andere Baustelle, s.u.), nämlich zwei Vektoren komponentenweise zu multiplizieren, würde diese Rechnung darauf hinauslaufen, dass du immer den Vektor (1, 1) für B0 erhältst (weil (1/x)*x immer 1 ist (sofern x ≠ 0)). Das wäre natürlich unsinnig. Du musst durch den Betrag des Vektors dividieren. Dieser ist definiert über den Satz des Pythagoras: |v| = sqrt(v.x² + v.y²), was deinem v.Length entsprechen sollte. Korrekt wäre also:
Delphi-Quellcode:
Weiter zur nächsten Baustelle:
B0.X := B.X/B.Length;
B0.Y := B.Y/B.Length;
Delphi-Quellcode:
Wieso heißt die Funktion „Multiply“, obwohl sie die Vektoren schlichtweg addiert?
function Vektor2DMultiplyTwo(Vekt1 : TVector2D; Vekt2 : TVector2D) : TVector2d;
begin Result.X := Vekt1.X + Vekt2.X; Result.Y := Vekt1.Y + Vekt2.Y; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:00 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz