Pfeil anhand eines Winkels zeichnen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MasterJulian
User
Beiträge: 14
Registriert: Sonntag 8. November 2009, 17:46

Da dies kein GUI bezogenes Problem ist, sondern ein mathematisches, habe ich es hier gepostet. Ich möchte einen Pfeil (Polygon) in Abhängigkeit eines Winkels zeichnen. Er soll also um den Mittelpunkt (210,210) gedreht werden. Die Ursprungskoordinaten lauten (210.0, 30.0), (190.0, 210.0), (230.0, 210.0). Meine Funktion zum berechnen der neuen Punkte sieht so aus:

Code: Alles auswählen

def calcarrow(angle):
    angle = math.radians(angle)
    AX = 0
    AY = 180
    AX2 = math.cos(angle) * AX - AY * math.sin(angle)
    AY2 = math.cos(angle) * AY - AX * math.sin(angle)
    
    BX = 20
    BY = 0
    BX2 = math.cos(angle) * BX - BY * math.sin(angle)
    BY2 = math.cos(angle) * BY - BX * math.sin(angle)

    CX = -20
    CY = 0
    CX2 = math.cos(angle) * CX - CY * math.sin(angle)
    CY2 = math.cos(angle) * CY - CX * math.sin(angle)
    return [(210 - AX2, 210 - AY2),(210 - BX2, 210 - BY2),(210 - CX2, 210 - CY2)]
Die Spitze stimmt, der rest leider nicht. Der Pfeil wird immer schmäler zwischen 0 und 45 Grad und dann immer größer. Warscheinlich eine triviale Sache, aber ich stehe irgendwie auf dem Schlauch. Dieses ganze Vektor-, Verschiebung-, Drehungsgedöns hab ich schon in der Schule nie gemocht.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

ax = cos(angle) * l
ay = sin(angle) * l

#Spitze
bx = cos(angle + delta) * s
by = sin(angle + delta) * s

cx = cos(angle - delta) * s
cy = cos(angle - delta) * s
Damit hast du einen Pfeil, welcher immer auf den Ursprung zeigt. Den zu verschieben sollte jetzt nicht mehr so schwer sein.
Das Leben ist wie ein Tennisball.
problembär

Weißt Du, "Tkinter.Canvas.create_line()" kennt sogar ein Argument "arrow = ...".

Gruß
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Woran machst du fest, dass er Tkinter nutzen will? Aber die Anregung ist an sich ja nicht schlecht. Vielleicht einfach mal schauen, ob das verwendete Toolkit Unterstützung in dieser Richtung bietet.
problembär

snafu hat geschrieben:Woran machst du fest, dass er Tkinter nutzen will?
Das weiß ich natürlich nicht, das ist nur eine Anregung.

Hier noch mal ein Beispiel mit Tkinter:

Code: Alles auswählen

#!/usr/bin/env python

import Tkinter
from Tkconstants import *
 
class ArrowWindow:

    def __init__(self):

        self.mw = Tkinter.Tk()
        self.mw.title("Arrow")
        self.mw.geometry("+300+250")

        self.cv = Tkinter.Canvas(self.mw, bg = "white")
        self.cv.pack()

        self.arrow = 0
        self.drawArrow("Right")

        self.btnOk = Tkinter.Button(self.mw,
                                    text = "Ok",
                                    command = self.mw.destroy)

        self.btnOk.bind(sequence = "<Return>",
                      func = lambda event: self.mw.destroy())

        self.btnOk.focus()

        self.btnOk.pack(side = RIGHT, padx = 10, pady = 10)

        self.fr = Tkinter.Frame(self.mw)
        self.fr.pack(side = RIGHT, padx = 10, pady = 10)

        self.btnl = Tkinter.Button(self.fr, text = "Left", command = lambda: self.drawArrow("Left")).pack(side = LEFT, padx = 10)

        self.btnu = Tkinter.Button(self.fr, text = "Up", command = lambda: self.drawArrow("Up")).pack(side = LEFT, padx = 5)

        self.btnd = Tkinter.Button(self.fr, text = "Down", command = lambda: self.drawArrow("Down")).pack(side = LEFT, padx = 5)
    
        self.btnr = Tkinter.Button(self.fr, text = "Right", command = lambda: self.drawArrow("Right")).pack(side = LEFT, padx = 10)

        self.mw.mainloop()


    def drawArrow(self, direction):

        self.cv.delete(self.arrow)

        if direction in ("Left", "Right"):
            coords = (100, 100, 200, 100)
        else:
            coords = (150, 50, 150, 150)

        if direction in ("Left", "Up"):
            arrdir = FIRST
        else:
            arrdir = LAST

        self.arrow = self.cv.create_line(coords, arrow = arrdir, arrowshape = (8, 10, 3))

if __name__ == "__main__":
   app = ArrowWindow()
:wink:

(Man kann die vier Richtungsbuttons hier übrigens nicht in einer Liste verwalten, weil die Parameterübergabe mit "command = lamda :" dann nicht hinhaut ...)

Gruß
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

problembär hat geschrieben:(Man kann die vier Richtungsbuttons hier übrigens nicht in einer Liste verwalten, weil die Parameterübergabe mit "command = lamda :" dann nicht hinhaut ...)
Warum nicht? Ungetestet:

Code: Alles auswählen

for text in ('Left', 'Up', 'Down', 'Right'):
    self.button_list.append(Tkinter.Button(self.fr, text=text,
                                           command=lambda arg=text:
                                               self.draw_arrow(arg)))
    self.button_list[-1].pack(side=LEFT, padx=10 if text in ('Left', 'Right')
                                                 else 5)
Übrigens: Du weißt, was Du mit

Code: Alles auswählen

self.btnu = Tkinter.Button(self.fr, text = "Up", command = lambda: self.drawArrow("Up")).pack(side = LEFT, padx = 5)
in self.btnu speicherst?
MfG
HWK
problembär

HWK hat geschrieben:
problembär hat geschrieben:(Man kann die vier Richtungsbuttons hier übrigens nicht in einer Liste verwalten, weil die Parameterübergabe mit "command = lamda :" dann nicht hinhaut ...)
Warum nicht?
Hey super! Mit der Syntax aus Deinem Beispiel:

Code: Alles auswählen

... lamda arg = text: self.drawArrow(arg)
geht's: Vielen Dank!
HWK hat geschrieben:Übrigens: Du weißt, was Du mit

Code: Alles auswählen

self.btnu = Tkinter.Button(self.fr, text = "Up", command = lambda: self.drawArrow("Up")).pack(side = LEFT, padx = 5)
in self.btnu speicherst?
Ääh, jedenfalls nicht das, was ich speichern wollte :oops: :P. Auch dafür danke, HWK!

Manchmal ist das schon toll, wie gut viele von euch sich in Python auskennen!

Gruß
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Ansonsten gibt es ja statt lambda noch functools.partial.
MfG
HWK
Antworten