Columba: Kreisbewegung scheitert/stoppt bei Cosinus 0

Hallo!

Ich verwende ein JavaScript mit dem Ziel, einen Punkt um einen anderen rotieren zu lassen. Dabei sind die Koordinaten beider Punkte gegeben sowie auch die Bewegungsrichtung und der Kreisradius. Anhand der Richtung habe ich "way" ausgerechnet - 0.02 für Bewegung im Uhrzeigersinn, -0.02 gegen den Uhrzeigersinn.
Nun versuche ich, anhand der Koordinaten des Mittelpunkts (assoziatives Array "m") und des Punktes auf der Außenlinie (assoziatives Array "posNeu") den neuen Punkt zu berechnen:

var bogen1=Math.acos( (posNeu["x"]-m["x"]) /radius);
posNeu["x"]=m["x"]+ radius * Math.cos(bogen1+way);
posNeu["y"]=m["y"]+ radius * Math.sin(bogen1+way);

Sinn des Ganzen: Aus dem gegebenen Punkt das aktuelle Bogenmaß herausbekommen, dazu 0.02 addieren oder halt abziehen, den neuen Punkt berechnen (vom Mittelpunkt aus den Sinus/Kosinus mal den Radius).

Problem, das auftritt:
Ich beginne bei meinem Test im 4. Quadranten und bin gegen den Uhrzeigersinn unterwegs. Dieser 4. Quadrant wird korrekt durchlaufen. Statt in den 1. Quadranten zu wechseln, bleibt der Punkt aber auf Höhe des Mittelpunkts stehen. bogen1 bleibt bei 0.01 hängen - weshalb?
Wenn ich im 2. Quadranten beginne und in den 3. wechseln will, tritt dasselbe Problem auf.

Grüße,
Columba

  1. Hallo Columba,

    die Punkte einer Kreisbahn berechnest du am einfachsten so:

    gegeben: Radius r, Winkel phi, Mittelpunkt (xm,ym)

    x = r * cos(phi) + xm
    y = r * sin(phi) + ym

    phi kann dann in einer Schleife um dphi(=+/-0.02) inkrementiert werden.

    Gruß, Jürgen

    1. gegeben: Radius r, Winkel phi, Mittelpunkt (xm,ym)

      x = r * cos(phi) + xm
      y = r * sin(phi) + ym

      Tja, und wie bekomme ich phi heraus aus den beiden Koordinaten? Daran bin ich bisher immer gescheitert. Bogenmaß/Gradmaß kann ich ja problemlos umrechnen, aber ich habe halt wirklich nur 2 Punkte. Und da die Berechnung sehr oft durchgeführt wird, sollte es auch noch schnell sein ...

      phi kann dann in einer Schleife um dphi(=+/-0.02) inkrementiert werden.

      Ist klar, Inkrementierung setze ich bereits ein. Habe ich nur nicht beschrieben, da funktional.

      1. Hallo Columba,

        Tja, und wie bekomme ich phi heraus aus den beiden Koordinaten?

        Zitat aus den Eingangsposting:

        Dabei sind die Koordinaten beider Punkte gegeben sowie auch die Bewegungsrichtung und der Kreisradius.

        d.h. du hast 2 Punkte und damit den Radius (Pytagoras). Den Winkel rechnest du mit dem Tangens aus, dabei musst du aber eine Fallunterscheidung machen, um den Quadranten zu finden.

        r = wurzel(dx^2+dy^2)
        phi = tan(dx/dy) und hier die Fälle
        dy<0 : 90°<phi<270°
        dy=0 : phi=90° oder 270°, je nach Vorzeichen von dx
        dy>0 : 270°<phi<360° und 0°<=phi<90°
        unterscheiden. Am bestem machst du dir dazu eine Zeichnung.

        Gruß, Jürgen

        1. Hallo,

          phi = tan(dx/dy) und hier die Fälle

          es muss natürlich der atan genommen werden.

          Gruß, Jürgen

  2. Hi!

    var bogen1=Math.acos( (posNeu["x"]-m["x"]) /radius);

    Der arcuscosionus ist nicht überall definiert, wenn ich mich an meinen letzten Mathe-Kurs richtig erinnere.

    Gruß

    Martin

    1. Hi Martin,

      Der arcuscosionus ist nicht überall definiert, wenn ich mich an meinen letzten Mathe-Kurs richtig erinnere.

      Aber für alle Werte im Intervall [-1, 1]. Und (posNeu["x"]-m["x"]) /radius) wird wohl in diesem Intervall liegen.

      Gruß,
      Gunnar

      --
      “I got my finger on the trigger / But I don’t know who to trust” (Bruce Springsteen, Devils and Dust)
  3. Hi there,

    Ich beginne bei meinem Test im 4. Quadranten und bin gegen den Uhrzeigersinn unterwegs. Dieser 4. Quadrant wird korrekt durchlaufen. Statt in den 1. Quadranten zu wechseln, bleibt der Punkt aber auf Höhe des Mittelpunkts stehen. bogen1 bleibt bei 0.01 hängen - weshalb?

    weil die Funktion acos nicht den Quadranten zurückgibt..

    Dein Lösung für eine Kreisbewegung ist schon etwas kompliziert; einfahcer wäre es , die Position aus einer Neuberechnung des Winkels zu ermitteln, dann wäre zb

    x=Math.sin(winkel) * Ausdehnung in horizontaler Richtung + Mittelpunkt x

    y=Math.cos(winkel) * Ausdehnung in vertikaler Richtung + Mittelpunkt y

    winkel erhöhst Du einfach je nach gewünschter Kreisgeschwindigkeit.

    damit vollführt der Punkt x/y je nach Parametern eine kreisförmige oder ellyptische Bewegung...

  4. Hallo,

    var bogen1=Math.acos( (posNeu["x"]-m["x"]) /radius);

    hier berücksichtigst du nur die x-Komponente deines Punktes, da liegt der Hase im Pfeffer.
    Math.asin() sollte dein Freund sein.

    cu,
    ziegenmelker

    1. Entschuldige die dumme Frage, aber wie komme ich denn mit asin() an den richtigen Wert heran? Problem sind die Vorzeichen und unterschiedlichen Quadranten ...

      Gruß,
      Columba

  5. Hi Columba,

    Anhand der Richtung habe ich "way" ausgerechnet - 0.02 für Bewegung im Uhrzeigersinn, -0.02 gegen den Uhrzeigersinn.

    Da hab ich erstmal gestutzt. Aber ja, das Koordinatensystem ist ja auch andersherum: positive x rechts, positive y UNTEN.

    Nun versuche ich, anhand der Koordinaten des Mittelpunkts (assoziatives Array "m") und des Punktes auf der Außenlinie (assoziatives Array "posNeu") den neuen Punkt zu berechnen:

    var bogen1=Math.acos( (posNeu["x"]-m["x"]) /radius);

    Liefert dir Werte im Intervall [0, π]. Du willst aber einen vollen Umlauf, also [0, 2π[ oder ]-π, π]. Nehmen wir der Einfachheit wegen das zweite.

    Das Vorzeichen des Winkels bogen1 stimmt dann mit dem Vorzeichen von posNeu["y"]-m["y"] überein. Also einfach

    if (posNeu["y"] < m["y"]) bogen1 = -bogen1;

    Das musst du nur einmal tun. In die Schleife kommt

    bogen1 += way;  
    posNeu["x"]=m["x"]+ radius * Math.cos(bogen1);  
    posNeu["y"]=m["y"]+ radius * Math.sin(bogen1);
    

    Gruß,
    Gunnar

    --
    “I got my finger on the trigger / But I don’t know who to trust” (Bruce Springsteen, Devils and Dust)
    1. var bogen1=Math.acos( (posNeu["x"]-m["x"]) /radius);

      Liefert dir Werte im Intervall [0, π]. Du willst aber einen vollen Umlauf, also [0, 2π[ oder ]-π, π]. Nehmen wir der Einfachheit wegen das zweite.

      Dankeschön! Das war mein Problem - jetzt funktioniert es endlich. Vielen, vielen Dank!

      Gruß,
      Columba

      1. Dankeschön! Das war mein Problem - jetzt funktioniert es endlich. Vielen, vielen Dank!

        Columba, Gerngeschehen.

        Aber eigentlich hab ich nicht viel mehr gesagt als ziegenmelker in https://forum.selfhtml.org/?t=108643&m=676928.

        posNeu["y"]-m["y"] ist doch der Sinus mal dem Radius, wobei letzterer für das Vorzeichen keine Rolle spielt.

        Gruß,
        Gunnar

        --
        “I got my finger on the trigger / But I don’t know who to trust” (Bruce Springsteen, Devils and Dust)
  6. Hi,

    in SELFHTML gibt's ein Beispiel.

    Gruß, Andreas

    --
    SELFFORUM - hier werden Sie geholfen,
    auch in Fragen zu richtiges Deutsch
    1. Hi,

      in SELFHTML gibt's ein Beispiel.

      Gruß, Andreas

      In diesem wurde aber nicht, wie gewünscht, von 2 Koordinaten ausgegangen.
      Naja, ich habe die Lösung bereits erhalten.

      Gruß

  7. Hallo nochmal!

    Okay, er stoppt nicht mehr mittendrin. Aber jetzt habe ich eine sehr ähnliche Frage, deshalb dasselbe Thema noch mal ...

    Ich habe 2 Punkte auf dem Kreis, ca. 20 Pixel Abstand. Die sind fest als "vorne" und "hinten" definiert. Außerdem habe ich wieder Radius und Mittelpunkt. Wie schaffe ich es, die korrekte Bewegungsrichtung zu errechnen? Ich bin gedanklich so verrannt - ich raff es nicht. Wie kriege ich das hin? Der springende Punkt ist der Punkt, wo zwischen 0 und Pi gewechselt wird / -pi und +pi.

    Hilfe!

    Gruß,
    Columba

    1. Hallo Columba,

      wenn du zwei Punkte (x1,y1) und (x2,y2) hast, dann bekommst du die Richtung mit dem Tangens:

      phi = tan((y2-y1)/(x2-x1)), wenn der Winkel gegen die Horizontale gehen soll. Natürlich benötigst du wieder die Fallunterscheidung für den Nenner.

      Nur, was hat das jetzt mit einem Kreis zu tun? Und warum hilft dir das Beispiel aus selfhtml nicht, bei den sich die Punkte auf Kreisbahnen um einen Mittelpunkt bewegen? Vieleicht solltest du noch einmal schreiben, was du wirklich willst. Sonst sind wir die Einzigen, die sich im Kreis drehen.

      Gruß, Jürgen

      1. Hallo,

        Und warum hilft dir das Beispiel aus selfhtml nicht, bei den sich die Punkte auf Kreisbahnen um einen Mittelpunkt bewegen?

        frag ich mich auch... funktioniert doch wunderbar. Und wenn er/sie die anggebenen Koordinaten nichtmal auf das eingene Beispiel übertragen kann, naja... vielleicht doch lieber was anderes programmieren - eine Gerade vielleicht, oder einen stehenden Punkt ;-)

        Gruß, Andreas

        --
        SELFFORUM - hier werden Sie geholfen,
        auch in Fragen zu richtiges Deutsch
      2. wenn du zwei Punkte (x1,y1) und (x2,y2) hast, dann bekommst du die Richtung mit dem Tangens:

        Jürgen, nach der Drehrichtung war gefragt.

        phi = tan((y2-y1)/(x2-x1)), wenn der Winkel gegen die Horizontale gehen soll. Natürlich benötigst du wieder die Fallunterscheidung für den Nenner.

        Mal abgesehen davon, dass du wohl arctan meinst:
        Folge mal deinem Ratschlag mit der Zeichnung, dann siehst du, dass du so nicht die Drehrichtung bekommst.

        Beispiel: Startpunkt bei  φ₁ = -π/4, also x₁ = x₀ + ½r √2, y₁ = y₀ - ½r √2.
        Wir drehen rechtsrum bis  φ₂ =  π/6, also x₂ = x₀ + ½r,    y₂ = y₀ + ½r √3.
        Noch ein Stück weiter bis φ₃ =  π/3, also x₃ = x₀ + ½r √3, y₃ = y₀ + ½r.

        Die Differenzen x₂ - x₁ und x₃ - x₁ haben unterschiedliche Vorzeichen, die Differenzen y₂ - y₁ und y₃ - y₁ haben gleiche Vorzeichen – bei gleicher Drehrichtung.

        Das war nichts mit arctan((y₂ - y₁)/(x₂ - x₁)).
        Und nach der Richtung der Verschiebung von (x₁, y₁) nach (x₂, y₂) war nicht gefragt.

        Gruß,
        Gunnar

        --
        “I got my finger on the trigger / But I don’t know who to trust” (Bruce Springsteen, Devils and Dust)
        1. Hallo Gunnar,

          Jürgen, nach der Drehrichtung war gefragt.

          wobei mit nicht wirklich klar ist, was damit gemeint ist.

          Mal abgesehen davon, dass du wohl arctan meinst:

          stimmt. Nicht aufgepasst.

          Folge mal deinem Ratschlag mit der Zeichnung, dann siehst du, dass du so nicht die Drehrichtung bekommst.

          Wie schon geschrieben, was versteht Columba unter der Drehrichtung? Wer oder was soll sich worum drehen?

          Ich hatte vor ewigen Zeiten mal ein ähnliches Problem mit dem atan und 4 Quadranten. Ich habe es dann mit einer Fallunterscheidung für den Nenner gelöst. Aber Columba scheint das Problem ja irgendwie gelöst zu haben.

          Gruß, Jürgen

          1. Jürgen, nach der Drehrichtung war gefragt.
            wobei mit nicht wirklich klar ist, was damit gemeint ist.

            Ob du links- oder rechtsrum von "vorne" nach "hinten" drehst. https://forum.selfhtml.org/?t=108643&m=677407

            Gruß,
            Gunnar

            --
            “I got my finger on the trigger / But I don’t know who to trust” (Bruce Springsteen, Devils and Dust)
    2. Hi Columba,

      Ich habe 2 Punkte auf dem Kreis, ca. 20 Pixel Abstand. Die sind fest als "vorne" und "hinten" definiert. Außerdem habe ich wieder Radius und Mittelpunkt. Wie schaffe ich es, die korrekte Bewegungsrichtung zu errechnen?

      Du kannst dir für beide Punkte die Phasenwinkel wie gehabt ausrechnen. Nenn sie meinetwegen bogen1 (für "vorne") und bogen2 (für "hinten").

      Dann bildest du die Differenz
        dbogen = bogen2 - bogen1;
      Dabei ist evtl. zu beachten, dass du nicht den weiteren Weg gehst (also z.B. nicht 1½π rechtsherum, sondern ½π linksherum).
        ~~~javascript if (dbogen > Math.PI) dbogen -= 2 * Math.PI;
        if (dbogen < Math.PI) dbogen += 2 * Math.PI;

        
      Dann gibt dir das Vorzeichen von dbogen die Drehrichtung an.  
        
      Gruß,  
      Gunnar
      
      -- 
      “I got my finger on the trigger / But I don’t know who to trust” (Bruce Springsteen, Devils and Dust)