Seite 1 von 1
Pfeil anhand eines Winkels zeichnen
Verfasst: Sonntag 20. Dezember 2009, 12:40
von MasterJulian
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.
Verfasst: Sonntag 20. Dezember 2009, 15:54
von EyDu
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.
Verfasst: Sonntag 20. Dezember 2009, 20:50
von problembär
Weißt Du, "Tkinter.Canvas.create_line()" kennt sogar ein Argument "arrow = ...".
Gruß
Verfasst: Sonntag 20. Dezember 2009, 22:07
von snafu
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.
Verfasst: Dienstag 22. Dezember 2009, 10:03
von 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()
(Man kann die vier Richtungsbuttons hier übrigens nicht in einer Liste verwalten, weil die Parameterübergabe mit "command = lamda :" dann nicht hinhaut ...)
Gruß
Verfasst: Dienstag 22. Dezember 2009, 10:24
von HWK
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
Verfasst: Dienstag 22. Dezember 2009, 21:17
von 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:
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

. Auch dafür danke, HWK!
Manchmal ist das schon toll, wie gut viele von euch sich in Python auskennen!
Gruß
Verfasst: Dienstag 22. Dezember 2009, 21:36
von HWK
Ansonsten gibt es ja statt lambda noch functools.partial.
MfG
HWK