Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Frage zu Winkelberechnungen... (https://www.delphipraxis.net/57884-frage-zu-winkelberechnungen.html)

md_mse 28. Nov 2005 12:20


Frage zu Winkelberechnungen...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo!

Ich habe mal wieder ein mathematisches Problem... :wall:
Diesmal geht es um Winkelberechnungen, und zwar: Ich habe einen Pfad (eine Spline), ich kenne die Koordinaten jedes Punktes der Spline. Nun möchte ich ein Objekt diesen Pfad folgen lassen, was an sich kein Problem ist... Nur macht mir die Berechnung des richtigen Winkels um den das Objekt gedreht werden muss, damit es realistisch aussieht.

Mein Ansatz bisher war folgender:
Delphi-Quellcode:
LenX := XKoordinateVonSplinePunkt;
LenY := YKoordinateVonSplinePunkt;
VecLen := Sqrt(Sqr(LenX) + Sqr(LenY));
Yaw := ArcSin(YKoordinateVonSplinePunkt / VecLen);
Dies funktioniert aber nicht so wie es sollte, zumindest stimmt der Winkel meistens nicht.
Was kann man da machen???

Im Anhang habe ich versucht mein Problem nochmal zu verdeutlichen.

chrisw 28. Nov 2005 12:32

Re: Frage zu Winkelberechnungen...
 
Hab das mal so gelöst, ist aber schon länger her !
Delphi-Quellcode:
function AngleOfPoint (Pt :TPoint) : double;
begin
  Result := 0;
  if ((Pt.X = 0) and (Pt.Y < 0)) then Result := 270 else
  if ((Pt.X = 0) and (Pt.Y > 0)) then Result := 90  else
  if ((Pt.X > 0) and (Pt.Y >= 0)) then Result := ArcTan(Pt.Y / Pt.X) * RadToDeg else
  if ((Pt.X < 0) and (Pt.Y > 0)) then Result := 180 + ArcTan(Pt.Y / Pt.X) * RadToDeg else
  if ((Pt.X < 0) and (Pt.Y <= 0)) then Result := 180 + ArcTan(Pt.Y / Pt.X) * RadToDeg else
  if ((Pt.X > 0) and (Pt.Y < 0)) then Result := 360 + ArcTan(Pt.Y / Pt.X) * RadToDeg else
  Result := 0;
end;

function PointOfAngAndDist (Angle,Distance : Double) : TPoint;
var Radians : Double;
begin
  Radians := Angle * DegToRad;
  Result.X := Round(Distance * Cos(Radians));
  Result.Y := Round(Distance * Sin(Radians));
end;
Musst immer den Punkt angeben, auf den "gezeigt" werden soll, der Winkel wird zurückgegeben.

Vielleicht kannst Du da was mit anfangen !



//EDIT : Sry, hatte die 2. Funktion vergessen !!!

shmia 28. Nov 2005 13:12

Re: Frage zu Winkelberechnungen...
 
Du müsstest an jedem Punkt auf der Spline Kurve die Ableitung der Spline-Funktion berechnen,
denn die Steigung entspricht dem Winkel.
Winkel = arctan(steigung)
Wenn du kubische Splines verwendest siehe: Spline-Interpolation

md_mse 28. Nov 2005 13:57

Re: Frage zu Winkelberechnungen...
 
Hm...
@chrisw: Leider stimmt der Winkel nicht mit der Spline überein...
@shima: Könntest du einer Mathe-Null wie mir ein Beispiel geben?

Ich berechne die Punkte in der Spline folgendermaßen:
Delphi-Quellcode:
CurrX := A.X * Power(Step, 3)   +    3 * B.X * Power(1 - Step, 2) * Step   +    3 * C.X * (1 - Step) * Power(Step, 2)   +    D.X * Power(Step, 3);
CurrY := A.Y * Power(Step, 3)   +    3 * B.Y * Power(1 - Step, 2) * Step   +    3 * C.Y * (1 - Step) * Power(Step, 2)   +    D.Y * Power(Step, 3);
Wobei
Code:
Step
jeweils um
Code:
1 / SplineLänge-1
erhöht wird...

Die Ableitung meiner Funktion müsste ja eigentlich so aussehen, wobei ich nicht weiss ob ich die X oder die Y "Achse" ableiten soll :/
Delphi-Quellcode:
DerivationX := 3 * A.X * Power(Step, 2)   +    6 * B.X * (1 - Step) * Step   +    6 * C.X * (1 - Step) * Step   +    3 * D.X * Power(Step, 2);

md_mse 29. Nov 2005 18:50

Re: Frage zu Winkelberechnungen...
 
*Push* :oops:

mare_crisium 29. Nov 2005 19:50

Re: Frage zu Winkelberechnungen...
 
md_mse,

der Irrtum bei Deinem ersten Ansatz ist folgender: In der Formel

Delphi-Quellcode:
  LenX := XKoordinateVonSplinePunkt;
  LenY := YKoordinateVonSplinePunkt;
  VecLen := Sqrt(Sqr(LenX) + Sqr(LenY));
  Yaw := ArcSin(YKoordinateVonSplinePunkt / VecLen);
geht der Vektor immer vom Nullpunkt aus zum augenblicklichen Punkt (LenX|LenY). Der Winkel, den Du herausbekommst, ist deshalb immer der Winkel zwischen dem Vektor vom Nullpunkt nach (LenX|LenY) und der x-Koordinate. Du willst aber, wie shmia richtig erkannt hat, die Ableitung der Splinefunktion haben, um Dein Objekt immer die Kurve entlang gucken zu lassen.

Bei mir ist das mit der Mathe auch schon ein Weilchen her, aber ich würde das so machen: Du suchst die Steigung:

Delphi-Quellcode:
.     dy
.s = ----
.     dx
Das ist aber nicht so ohne Weiteres zu berechnen, weil sowohl x, als auch y von "step" abhängen. Erinnerst Du Dich noch an die Kettenregel beim Ableiten von Funktionen? Die verwendet man hier mit Vorteil:

Delphi-Quellcode:
.                                   dy
.                                  -----
.     dy     dy      dstep       dstep
.s = ---- = ------- * -------- = --------------
.     dx    dstep      dx         dx
.                                  -------
.                                   dstep
Du musst also die y-Komponente Deiner Spline nach "step" ableiten und durch die Ableitung der x-Komponente der Spline nach "step" dividieren. Zeig' die Formel bloss keinem Mathematiker! Der kriegt dann nämlich einen Herzanfall (weil er alle Ausnahmen kennt, unter denen meine Formel falsch ist)!

Probier's trotzdem mal und lass uns wissen ob's damit klappt.

mare_crisium

turboPASCAL 29. Nov 2005 20:48

Re: Frage zu Winkelberechnungen...
 
Ich hatte mal so ein ähnliches Problem: http://www.delphipraxis.net/internal...=460057#460057
Wenn's hilft. ;)

md_mse 30. Nov 2005 09:35

Re: Frage zu Winkelberechnungen...
 
So, ich möchte euch erstmal für eure Mühen danken, jedoch hat mich keine vorgeschlagene Lösung weiter gebracht :oops:.
Die Ableitung der X Achse brachte mir immer nur den gleichen Wert, die Ableitung der Y-Achse war unberechenbar :?, zumindest bei der von mir verwendeten Spline-Funktion.
Ein Kommillitone hat sich mal folgende Lösung ausgedacht, die perfekt funktioniert:
Delphi-Quellcode:
function SubtractVectors(AVec1, AVec2: TD3DVector): TD3DVector; inline;
begin
  Result := D3DXVector3(AVec2.x - AVec1.x, AVec2.y - AVec1.y, AVec2.z - AVec1.z);
end;

//x1,y1 : Vector Startpunkt, x2,y2 : Vector End punkt
function CalculateAngel(AVec1, AVec2: TD3DVector): Single;
var
  Flt: Single;
begin
  // Vektor in sein eigenes System bewegen
  SubtractVectors(AVec1, AVec2);
  AVec2.x := 1;
  AVec2.z := 0;

  // Winkel berechen
  Flt := Sqrt( Sqr(AVec1.x) + Sqr(AVec1.z) ) * Sqrt( Sqr(AVec2.x) + Sqr(AVec2.z) );
  if not IsZero(Flt) then
    Result := Abs(ArcCos(((AVec1.x * AVec2.x) + (AVec1.z * AVec2.z)) / Flt)) else
    Result := 0.0;

  //1. Quadrant
  if (AVec1.x > 0) and (AVec1.z > 0) then
    // keine Änderung
    //2. Quadrant
    else if (AVec1.x < 0) and (AVec1.z > 0) then
    // keine Änderung
    //3.Quadrant
    else if (AVec1.x < 0) and (AVec1.z < 0) then
      Result := Result + Pi
    //4.Quadrant
    else if (AVec1.x > 0) and (AVec1.z < 0) then
      Result := Result + Pi;
end;
Trotzdem nochmal vielen Dank! :cheers:

P.S.: Vielleicht etwas für die CodeLib (Stichwort Direct3D/Winkelberechnung)?


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz