Mit Pfeil und Kreis...



  • Hallo,

    gegeben habe ich zwei Punkte A und B. Zwischen den zwei Punkten will ich nun einen Pfeil zeichnen. Nur ich komme mit der Mathematik dahinter nicht ganz klar oO

    Die Pfeilspitze soll bei A sein und eine variable Dicke und Länge haben.
    Ich dachte, ich nehme mir zur Hilfe einen Kreis. Der Kreis hat den Radius von der Länge der Pfeilspitze. Dann brauch ich ja "nur" noch die Sehne zeichnen.

    Aber um überhaupt mit dem Kreis arbeiten zu können brauche ich ja einen Winkel. Den Winkel wollte ich bekommen, indem ich den Kreis nach den gegebenen Punkten zeichne. Also Kreismitte ist A und der Punkt auf dem Rand ist B.
    Einen Punkt auf dem Kreis berechnet man ja so:
    Px = Mx + r * cos( Winkel )
    Py = My + r * sin( Winkel )

    Das hab ich dann nach dem Winkel umgestellt:
    Winkel = ( Px - Mx ) / r

    Aber wenn ich das mit A( 50, 50 ) und B( 200, 100 ) berechne, kommt ein Winkel von -0,949... raus.
    Wie komm ich an den Winkel? Hab ich falsch umgestellt oder nehme ich die falsche Formel?

    Bzw. gibt es bessere Wege, einen Pfeil von A nach B zu zeichnen?

    MfG. Ich



  • ChristophLu schrieb:

    Das hab ich dann nach dem Winkel umgestellt:
    cos(Winkel) = ( Px - Mx ) / r

    Winkel = arccos(( Px - Mx ) / r).

    ChristophLu schrieb:

    Bzw. gibt es bessere Wege, einen Pfeil von A nach B zu zeichnen?

    Bresenham-Algorithmus



  • Hallo,

    ich hab das jetzt auf anderen Wegen hinbekommen, habe aber ein Problem.
    Hier mal eine Grafik dazu:
    http://home.arcor.de/minicrispie/dreieck.png

    Ich hab jeden Punkt, jede Länge und jeden Winkel. Das einzige, was fehlt, ist G.
    Wie komme ich an die x- und y-Koordinaten von G?
    Mir will da keine Lösung einfallen oO

    MfG. Ich


  • Mod

    ChristophLu schrieb:

    Wie komme ich an die x- und y-Koordinaten von G?

    Durch Vektorrechnung (Großbuchstaben sollen im Folgenden Vektoren bezeichnen):

    G = D + ((C-D) * Drehmatrix(-Winkel zwischen GDC))* y/x



  • Hallo,

    ich hab das jetzt doch mit den Kreisen gemacht, und habe da schonwieder nen Problem. In meinem Programm zeichne ich den Pfeil in jedem Winkel:

    #include <cmath>
    	//[...]
    
    	double winkel = 0.0;
    	Punkt Start;
    	Punkt Ende( 200, 200 );
    	double radius = 50.0;
    	while( !key[KEY_ESC] )
    	{
    		Start.x = Ende.x + radius * cos( winkel / DEGtoRAD );
    		Start.y = Ende.y + radius * sin( winkel / DEGtoRAD );
    		zeichnePfeil( puffer, Start, Ende, 0, false ); //Parameter: Bitmap, A, B, Farbe, Gefüllter Pfeil?
    		textprintf_ex( puffer, font, 3, 3, 0, -1, "Winkel: %f", winkel );
    		winkel += 1.0;
    		if( winkel > 360.0 )
    		{
    			winkel = 0.0;
    		}
    	}
    

    Um die Pfeilspitze zeichnen zu können, brauche ich wieder den Winkel. Den muss ich nun aus den übergebenen Punkten A und B wieder herauslesen. in zeichnePfeil() mache ich das so:

    #define DEGtoRAD ( 180 / M_PI )
    double winkel_pfeil = acos( ( B.x - A.x ) / pfeillaenge ) * DEGtoRAD;
    

    Der ausgelesene Winkel stimmt nie mit dem gesetzten überein. Zudem wird der Pfeil falsch gezeichnet. Aber ich finde den Fehler nicht.
    Hier sind mal ein paar Screenshots von ein paar Positionen:
    http://home.arcor.de/minicrispie/pfeil/1.png
    http://home.arcor.de/minicrispie/pfeil/2.png
    http://home.arcor.de/minicrispie/pfeil/3.png
    http://home.arcor.de/minicrispie/pfeil/4.png

    Die Pfeilspitze liegt bei Punkt A. Demnach ist der Kreis-Mittelpunkt bei B. Die rote Linie wird von A nach B gezeichnet.

    Falls das bei der Lösung hilft, hier ist die gesamte Pfeil-Mal-Funktion:

    const double pfeil_winkel = 25.0;
    const double pfeil_laenge = 10.0;
    int zeichnePfeil( BITMAP *buffer,
                      Punkt A,
                      Punkt B,
                      int color,
                      bool fill )
    {
    	if( buffer == NULL )
    	{
    		return -1;
    	}
    
    	/*
    		Bei Punkt A ist die Pfeilspitze
    		Bei Punkt B ist das Ende des Pfeils.
    	*/
    
    	//Die Pfeillänge berechnen
    	double pfeillaenge = satzDesPythagoras( ( A.x - B.x ), ( A.y - B.y ) );
    
    	//Die Winkel berechnen
    	#define DEGtoRAD ( 180 / M_PI )
    	double winkel_pfeil        = acos( ( B.x - A.x ) / pfeillaenge ) * DEGtoRAD;
    	double winkel_spitze_oben  = winkel_pfeil + pfeil_winkel;
    	double winkel_spitze_unten = winkel_pfeil - pfeil_winkel;
    
    	int zeile = 20;
    	#define ZEILE ( zeile += 10 )
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "Pfeillänge:          %f", pfeillaenge );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "winkel_pfeil:        %f", winkel_pfeil );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "winkel_spitze_oben:  %f", winkel_spitze_oben );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "winkel_spitze_unten: %f", winkel_spitze_unten );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "A.x: %f", A.x );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "B.x: %f", B.x );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "A.y: %f", A.y );
    	textprintf_ex( buffer, font, 50, ZEILE, 0, -1, "B.y: %f", B.y );
    
    	//Die Positionen der Pfeilenden berechnen
    	Punkt p_spitze_oben;
    	Punkt p_spitze_unten;
    	Punkt p_linie_start;
    	p_spitze_oben.x = A.x + pfeil_laenge * cos( winkel_spitze_oben / DEGtoRAD );
    	p_spitze_oben.y = A.y + pfeil_laenge * sin( winkel_spitze_oben / DEGtoRAD );
    	p_spitze_unten.x = A.x + pfeil_laenge * cos( winkel_spitze_unten / DEGtoRAD );
    	p_spitze_unten.y = A.y + pfeil_laenge * sin( winkel_spitze_unten / DEGtoRAD );
    	p_linie_start.x = A.x + pfeil_laenge * cos( winkel_pfeil / DEGtoRAD );
    	p_linie_start.y = A.y + pfeil_laenge * sin( winkel_pfeil / DEGtoRAD );
    
    	//Den Pfeil zeichnen
    	line( buffer, B.x, B.y, p_linie_start.x, p_linie_start.y, color );
    	line( buffer, A.x, A.y, p_spitze_unten.x, p_spitze_unten.y, color );
    	line( buffer, A.x, A.y, p_spitze_oben.x, p_spitze_oben.y, color );
    	line( buffer, p_spitze_unten.x, p_spitze_unten.y, p_spitze_oben.x, p_spitze_oben.y, color );
    
    	line( buffer, A.x, A.y, B.x, B.y, makecol( 255, 0, 0 ) );
    
    	//Soll der Pfeil gefüllt werden?
    	if( fill )
    	{
    		//Ein Punkt in der Pfeilspitze bestimmen
    		Punkt fuell_punkt;
    		fuell_punkt.x = A.x + ( pfeil_laenge / 2.0 ) * cos( winkel_pfeil / DEGtoRAD );
    		fuell_punkt.y = A.y + ( pfeil_laenge / 2.0 ) * sin( winkel_pfeil / DEGtoRAD );
    
    		//Den Pfeil füllen
    		floodfill( buffer, fuell_punkt.x, fuell_punkt.y, color );
    	}
    
    	return 0;
    }
    

    Ich hoffe, ihr findet den Fehler, ich bin mit meinem Latain am Ende. Und meine Mathe-Begabung hält sich auch in Grenzen 😞

    Danke schon mal
    MfG. Ich



  • So ... habs geschafft. Ich hatte erstens falsch gedacht und zweitens falsch berechnet oO.
    Problem behoben.


  • Mod

    Falls du es nicht kennst: Schlag mal nach, was atan2 ist.


Anmelden zum Antworten