Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   2 Vektoren und 1 Punkt, wo näher drann? (https://www.delphipraxis.net/167563-2-vektoren-und-1-punkt-wo-naeher-drann.html)

Jonas Shinaniganz 5. Apr 2012 14:54

2 Vektoren und 1 Punkt, wo näher drann?
 
Ein bisschen Mathe... Nachhilfe für mich 8-)

Ich habe 2 Vektoren und einen Punkt. Im 2-Dimensionalem Raum. (2 Achsen Koordinatensystem)

Jetzt würde Ich gerne wissen an welchem Vektor der Punkt dichter drann ist.

Oder besser: Ist der Dichteste Punkt zwischen meinem Punkt und dem Dichtesten Punkt des Vektors an meinem Punkt immernoch weiter Weg als der dichteste Punkt vom anderen Vektor (aus der Sicht meines Punktes).

Dafür müsste Ich vielleicht zu erst wissen wie ich den Dichtesten Punkt eines Vektors an meinem Punkt errechne, dann kann ich mir aus den Beiden Punkten einen Vektor errechnen und daraus dann die Länge als Betrag und dann mit dem anderen das Gleiche und dann vergleichen :)

Ich weiß also schon genau was Ich machen will habe nur keinen Plan.

Grüße :)))

Medium 5. Apr 2012 15:05

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Ein Vektor hat an sich keinen Abstand zu irgendwas, da er lediglich eine Richtungs- und Längeninformation trägt, aber keine Ortsinformation. Meinst du Ortsvektoren? Für die ist der Koordinatenursprung als Fußpunkt definiert, womit die zumindest schon mal einen Ort haben. Dann muss man nur noch gedanklich den Schritt machen, und aus Fußpunkt sowie vom Vektor angezeigten Bildpunkt eine Strecke bilden, und zu DER ließe sich ein Abstand errechnen.

Lemmy 5. Apr 2012 15:09

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Hi,

das ist im Grunde eine Schnittberechnung zwischen Vektor und Kreis um den Punk P - wie das allerdings per Vektorrechung geht habe ich keinen Plan...

Aphton 5. Apr 2012 15:16

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Ortsvektoren A, B
Punkt P

Berechne AP -> P - A
Berechne BP -> P - B

Wenn |AP| < |BP| dann näher an A;
sonst näher an B

Jonas Shinaniganz 5. Apr 2012 15:31

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also ich mache immoment was falsch... Ich habe folgende Prozedur:

Delphi-Quellcode:
function TSetPoints.PrevPointCloser(Index : Integer; X,Y : Double): Boolean;
var
  OrtsVektorPrevPoint : array [0..1] of Double;
  OrtsVektorNextPoint : array [0..1] of Double;

  VektorPrevPoint : array [0..1] of Double;
  VektorNextPoint : array [0..1] of Double;

  BetragVektorPrev : Double;
  BetragVektorNext : Double;
begin
  Result := True;
  OrtsVektorPrevPoint[0] := FPoints[Index - 1].FX;
  OrtsVektorPrevPoint[1] := FPoints[Index - 1].FY;

  OrtsVektorNextPoint[0] := FPoints[Index + 1].FX;
  OrtsVektorNextPoint[1] := FPoints[Index + 1].FY;
  // Vektor NewP->PrevP
  VektorPrevPoint[0] := OrtsVektorPrevPoint[0] - X;
  VektorPrevPoint[1] := OrtsVektorPrevPoint[1] - Y;
  // Vektor NewP->NextP
  VektorNextPoint[0] := OrtsVektorNextPoint[0] - X;
  VektorNextPoint[1] := OrtsVektorNextPoint[1] - Y;

  // Länge (Betrag) des Vektors
  BetragVektorPrev := sqrt(power(VektorPrevPoint[0], 2) + power(VektorPrevPoint[1], 2));
  BetragVektorNext := sqrt(power(VektorNextPoint[0], 2) + power(VektorNextPoint[1], 2));

//  if FPoints[I + 1].FX dichter an FPoints[I].X als FPoints[I - 1].FX then
  if (BetragVektorPrev < BetragVektorNext) then
    Result := False;
end;
Also mein Problem: Das Bild sollte helfen,

Der Grüne Punkt ist mein X,Y was Ich der Prozedur übergebe,
Die SChwarze Linie ist mein Graph. Die Roten Punkte die Werte des Graphen, verbunden durch die Schwarzen Linien.

Immoment Berechne Ich die beiden Roten Vektoren und schaue welcher kürzer ist. Ich will aber den Betrag der Grauen Linien berechnen und die länge vergleichen...

aber es geht vorran.

Lemmy 5. Apr 2012 15:37

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Zitat:

Zitat von Jonas Shinaniganz (Beitrag 1160397)

Immoment Berechne Ich die beiden Roten Vektoren und schaue welcher kürzer ist. Ich will aber den Betrag der Grauen Linien berechnen und die länge vergleichen...

also gehts dir um den senkrechten Abstand zum Vektor (der im übrigend nicht der kürzeste Abstand sein muss) - das ist einfach: Zieh eine weitere Rote Linie zu dem Polygonpunkt in der Mitte (das Rote X). Damit kannst Du alle Längen in dem Dreieck bestimmen, über die Längen die Winkel und mit den Winkeln in einem der rechtwinkligen Dreiecke in denen der Abstand eine Kathete ist, diese berechnen. So würde ich das Problem lösen, weiß nicht ob es da verktortechnisch andere Vorgehensweisen gibt...

Grüße

Namenloser 5. Apr 2012 16:00

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Den senkrechten Abstand zu einer Strecke kannst du im zweidimensionalen Raum über das Kreuzprodukt berechnen (s. Anhang).
[edit]
Sorry, habe wohl zu lange mit dreidimensionalen Vektoren hantiert... Das „Kreuzprodukt“ ist ja für den zweidimensionalen Raum nicht wirklich definiert. Was ich damit meinte ist:
Delphi-Quellcode:
function &#8222;Kreuzprodukt&#8220; (A, B: TVec2): Single;
begin
  Result := A.X*B.Y - A.Y*B.X;
end;
Es kommt, wie du siehst, auch kein Vektor heraus, sondern ein Skalar, aber mehr brauchen wir hier ja auch gar nicht ;)
[/edit]

Btw, darf man fragen, was du programmierst? Deine Skizze erinnert mich nämlich extrem an den kleinen Sonic-Klon (* nicht wirklich ein Klon, aber die Engine nachprogrammiert), den ich letztes Jahr geschrieben habe ;)

Aphton 5. Apr 2012 16:31

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Ach noch etwas:
Delphi-Quellcode:
// das hier
  OrtsVektorPrevPoint : array [0..1] of Double;
sieht nicht schön aus.

Lieber soetwas:
Delphi-Quellcode:
type
  TVector2d = record
  case Boolean of
    False: (X: Double; Y: Double);
    True: (Values: Array[0..1] of Double);
  end;

(...)
var
  P: TVector2d;
Damit kannste nämlich direkt per P.X und P.Y oder P.Values[0] und P.Values[1] auf die X & Y Koordinaten zugreifen

Praktisch sind dann noch folgende Erweiterungen:
Delphi-Quellcode:
  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;
   

procedure TVector2d.Assign(const newX, newY: Double);
begin
  X := newX;
  Y := newY;
end;

function TVector2d.Length: Double;
begin
  Result := SQRT(X*X + Y*Y);
end;

shmia 5. Apr 2012 16:36

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Zitat:

Zitat von Jonas Shinaniganz (Beitrag 1160387)
Ich habe 2 Vektoren und einen Punkt. Im 2-Dimensionalem Raum. (2 Achsen Koordinatensystem) ... an welchem Vektor der Punkt dichter drann ist

Das Wort Vektor macht so keinen Sinn. (wie schon Medium festgestellt hat)
Zwei Geraden und ein Punkt, das würde deutlich mehr Sinn ergeben.
Bitte nicht mehr vom Vektor sprechen, wenn eine Gerade gemeint ist.

Eine Gerade kann auf zwei Arten definiert werden:
* 2 Punkte (nicht gleich) durch die die Gerade läuft
* eine Punkt und ein (Richtungs-)vektor (mit Länge > 0)
Beide Darstellungen lassen sich in einander uumrechnen.

Dann reduziere das Problem auf:
Welchen Abstand hat ein Punkt im 2D-Raum von einer Geraden?

Aphton 5. Apr 2012 16:43

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Zitat:

Zitat von NamenLozer (Beitrag 1160402)
Den senkrechten Abstand zu einer Strecke kannst du im zweidimensionalen Raum über das Kreuzprodukt berechnen (s. Anhang).
[edit]
Sorry, habe wohl zu lange mit dreidimensionalen Vektoren hantiert... Das „Kreuzprodukt“ ist ja für den zweidimensionalen Raum nicht wirklich definiert. Was ich damit meinte ist:
Delphi-Quellcode:
function &#8222;Kreuzprodukt&#8220; (A, B: TVec2): Single;
begin
  Result := A.X*B.Y - A.Y*B.X;
end;
Es kommt, wie du siehst, auch kein Vektor heraus, sondern ein Skalar, aber mehr brauchen wir hier ja auch gar nicht ;)
[/edit]

Richtig wäre es so (Skalarprodukt):
A.X * B.X + A.Y * B.Y

=P

Edit: Soweit ich das richtig in Erinnerung, haben wir bei der Formel cos(Winkel) = (a x b) / (|a| * |b|) beim "x" das Skalarprodukt berechnet (im 2D Raum)

Namenloser 5. Apr 2012 16:44

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Zitat:

Zitat von Aphton (Beitrag 1160415)
Richtig wäre es so (Skalarprodukt):
A.X * B.X + A.Y * B.Y

=P

Ich meine aber nicht das  Skalarprodukt :roll:


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.

Aphton 5. Apr 2012 16:45

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Hmm... Siehe Edit

Namenloser 5. Apr 2012 16:59

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Zitat:

Zitat von Aphton (Beitrag 1160415)
Edit: Soweit ich das richtig in Erinnerung, haben wir bei der Formel cos(Winkel) = (a x b) / (|a| * |b|) beim "x" das Skalarprodukt berechnet (im 2D Raum)

Es gibt zwei sehr ähnliche Formeln, einmal für den Sinus bzw. das Kreuzprodukt und einmal für den Kosinus bzw. das Skalarprodukt:
  1. |a × b| = |a| * |b| * sin(φ)
  2. a * b = |a| * |b| * cos(φ)
Ich nehme an, du hast die beiden Formeln verwechselt...

Aphton 5. Apr 2012 17:18

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 "*"..

Medium 6. Apr 2012 01:09

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Zitat:

Zitat von Lemmy (Beitrag 1160399)
also gehts dir um den senkrechten Abstand zum Vektor (der im übrigend nicht der kürzeste Abstand sein muss)

Doch, muss er. Bei Strecken (im Gegensatz zu Geraden) kommt allerdings noch hinzu, dass man ggf. gar keinen orthogonalen Abstand zu einem Punkt bilden kann - in dem Fall ist der Abstand zu einem der beiden streckenbegrenzenden Punkten der gesuchte. Glaub mir, darauf basierte ein größerer Teil meiner Bachelorarbeit ;) (Die übrigens nichts mit Spielen zu tun hatte. Man kann das ganze auch total "seriös" anwenden ;))
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.

Jonas Shinaniganz 10. Apr 2012 10:37

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 :|

Aphton 10. Apr 2012 14:09

AW: 2 Vektoren und 1 Punkt, wo näher drann?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also entweder so, wie bei Antwort #7 beschrieben, lösen ODER vielleicht so... (längere Variante; sofern keine Fehler vorhanden sind)

Medium 10. Apr 2012 14:27

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.

Jonas Shinaniganz 11. Apr 2012 10:17

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:
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;
Meine Funktionen zur Vektorrechnung sehen so aus:


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:
function Vector2DPointToOrt(P1 : TFloatPoint) : TVector2d;
begin
  Result.X := P1.X;
  Result.Y := P1.Y;
end;
Mein Vektor2D record ist so von euch übernommen:

Delphi-Quellcode:
  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;
Die Floatpoints sind:

Delphi-Quellcode:
  TFloatPoint = packed record
    X : Single;
    Y : Single;
  end;
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.

Namenloser 12. Apr 2012 03:35

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:
B0.X := B.X/B.Length;
B0.Y := B.Y/B.Length;
Weiter zur nächsten Baustelle:
Delphi-Quellcode:
function Vektor2DMultiplyTwo(Vekt1 : TVector2D; Vekt2 : TVector2D) : TVector2d;
begin
  Result.X := Vekt1.X + Vekt2.X;
  Result.Y := Vekt1.Y + Vekt2.Y;
end;
Wieso heißt die Funktion „Multiply“, obwohl sie die Vektoren schlichtweg addiert?


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:55 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