Gleichgewicht, Schwerpunkt und Hebelarm an einer Balkenwaage (Software)
Dieses Python-3-Programm mit Tkinter-Grafik und Mausbedienung über Schieberegler war in ähnlicher Form im vergangenen Jahr die Beispiellösung für die Programmieraufgabe im ersten Semester. Eine Balkenwaage hat vier mit der Maus beeinflussbare Parameter: die Längen der beiden Balkenarme und die Massen am jeweiligen Armende. Die Schieber sind so angeordnet, dass die Bedienung möglichst intuitiv ist. Die Regler für die Längen sind horizontal angeordnet und entgegengesetzt skaliert, die Regler für die Massen sind vertikal angeordnet.
Die Beschriftung der einzelnen Komponenten wird dynamisch an die sich ändernde Geometrie der Anordnung angepasst und auch eine gedrehte Beschriftung kommt vor. Ein (minimaler) 3D-Effekt wird durch einen Stapel immer heller und kleiner werdender Kreisscheiben erzielt, die eine Art Glanzpunkt auf den Massekugeln darstellen.
Download: ZIP-Archiv_F8RAASYL1.zip
# Simulation einer Balkenwaage # # Die Massen an den Balkenenden sowie die Längen der Waagbalkenhälften # sind variabel und können mit Schiebereglern beeinflusst werden. # # Durch Rechtsklick auf einen Schieberegler lässt sich die Waage wieder # ins Gleichgewicht bringen. from tkinter import Tk, Canvas, Label, Entry, Scale, mainloop, messagebox from math import sin, cos, atan2, degrees, hypot # Programmfenster einrichten T = Tk() T.title("Gleichgewicht und Schwerpunkt") # Zeichenfläche definieren C = Canvas(T, width=800, height=600, bg="white") C.grid(row=0, column=1, columnspan=2, rowspan=2) def kreis(p, r, fill="black", outline=None, width=1): """Zeichnet Kreis um Punkt p mit Radius r""" # Falls Randfarbe nicht angegeben wurde, entspricht sie der Füllfarbe. if not outline: outline = fill # Der Kreis wird über das ihn umschließende Quadrat definiert. C.create_oval(p[0]-r, p[1]-r, p[0]+r, p[1]+r, fill=fill, outline=outline, width=width) def kugel(p, m): """Zeichnet Kugel der Masse m an Punkt p""" # Der Radius ist proportional zur dritten Wurzel der Masse. r = m**(1/3)*10 # Die Kreisscheibe ist rot. kreis(p, r, "#E00000") # Oben links befindet sich ein kleiner Glanzpunkt. Er besteht aus # vielen Kreisen, die immer heller und immer kleiner werden. for ri in range(int(r/2), 0, -1): pi = (p[0]-r/3, p[1]-r/3) fi = "#E0%02X%02X" % (int(180*(1-2*ri/r)), int(180*(1-2*ri/r))) kreis(pi, ri, fi) # Beschriftung C.create_text(p, text=m, fill="white") def zeichnung(event=None): """Baut die Zeichnung komplett neu auf""" C.delete("all") # Maßstab: 1 Meter entspricht 30 Pixeln m = 30 # Höhe des senkrechten Aufhängestabes h = 0.1 * m # Fadenlänge der aufgehängten Massen fl = 3*m # Massen links/rechts von Schiebereglern ablesen lm = S_LMasse.get() rm = S_RMasse.get() # Längen links/rechts von Schiebereglern ablesen ll = S_LLänge.get() rl = S_RLänge.get() # Schwerpunktordinate auf dem Waagbalken try: s = rm/(lm+rm)*(ll+rl) except ZeroDivisionError: C.create_text(400, 100, text="Eine der beiden Massen muss größer als" " null sein.") return # Startpunkt (Gelenkige Aufhängung) p0 = x0, y0 = 400, 100 # Winkel der Waage alpha = atan2(s-ll, h) # Hypotenuse des rechtwinkligen Dreiecks # Aufhängepunkt-Schwerpunkt-Balkenschnittpunkt hyp = h*m/cos(alpha)+fl # Schwerpunkt ps = x0, y0+hyp # Schnittpunkt von Aufhängestab und Waagbalken p1 = x0-h*m*sin(alpha), y0+h*m*cos(alpha) # Punkt des rechten Winkels im blauen Schwerpunktdreieck pw = x0-hyp*sin(alpha)*cos(alpha), y0+hyp*cos(alpha)*cos(alpha) # Linker Endpunkt des Waagbalkens pl = p1[0]-ll*m*cos(alpha), p1[1]-ll*m*sin(alpha) # Rechter Endpunkt des Waagbalkens pr = p1[0]+rl*m*cos(alpha), p1[1]+rl*m*sin(alpha) # Aufhängestab C.create_line(p0, p1, width=10, fill="brown") # Gelenkige Aufhängung kreis(p0, 0.3*m, fill="white", outline="black", width=4) # Waagbalken C.create_line(pl, pr, width=10, capstyle="round", fill="brown") # Linke Masse pl1 = pl[0], pl[1]+fl C.create_line(pl, pl1, width=2) kugel(pl1, lm) # Rechte Masse pr1 = pr[0], pr[1]+fl C.create_line(pr, pr1, width=2) kugel(pr1, rm) # Schwerpunkt zeichnen und beschriften kreis(ps, 3, fill="blue") C.create_text(x0, y0+hyp+5, fill="blue", text="Schwerpunkt", anchor="n") # Winkel einzeichnen: # Das blaue Dreieck C.create_polygon(p0, ps, pw, outline="blue", fill="") # Der Maßbogen des Winkels C.create_arc(x0-2.5*m, y0-2.5*m, x0+2.5*m, y0+2.5*m, style="arc", outline="blue", start=270, extent=-degrees(alpha)) # Die Pfeilspitze des Maßbogens nur bei ausreichend großem Winkel zeichnen if abs(degrees(alpha)) > 5: x2 = x0+10 if alpha < 0 else x0-10 y2 = y0+2.5*m C.create_polygon(x2, y2-5, x0, y2, x2, y2+3, fill="blue") # Winkelbemaßung je nach Vorzeichen links- oder rechtsbündig C.create_text(x0, y0+2.5*m, fill="blue", text=" α = %.2f° " % abs(degrees(alpha)), anchor="e" if alpha < 0 else "w") # Schwerpunktabstand (falls kein Gleichgewicht) beschriften if alpha: sa = hypot(ps[0]-pw[0], ps[1]-pw[1])/m C.create_text((ps[0]+pw[0])/2, (ps[1]+pw[1])/2, anchor="s", fill="blue", angle=degrees(-alpha), text="%.2fm" % sa) # Eingabebereich: Jeder Schieberegler lässt sich mit Rechtsklick # in die Gleichgewichtslage zurücksetzen (falls möglich). # Vertikaler linker Regler Label(text="linke Massen[kg]").grid(row=0, column=0, sticky="ew") S_LMasse = Scale(from_=0, to=99, width=20, orient="vertical", length=500, tickinterval=10, resolution=0.1, command=zeichnung) S_LMasse.set(10) S_LMasse.grid(row=1, column=0, sticky="ns") def reset_LMasse(event): S_LMasse.set(S_RMasse.get()*S_RLänge.get()/S_LLänge.get()) zeichnung() S_LMasse.bind("<Button-3>", reset_LMasse) # Vertikaler rechter Regler Label(text="rechte Massen[kg]").grid(row=0, column=3, sticky="ew") S_RMasse = Scale(from_=0, to=99, width=20, orient="vertical", length=500, tickinterval=10, resolution=0.1, command=zeichnung) S_RMasse.set(10) S_RMasse.grid(row=1, column=3, sticky="ns") def reset_RMasse(event): S_RMasse.set(S_LMasse.get()*S_LLänge.get()/S_RLänge.get()) zeichnung() S_RMasse.bind("<Button-3>", reset_RMasse) # Horizontaler linker Regler Label(text="Länge des linken Waagbalkenarmesn[m]", ).grid(row=3, column=0, columnspan=2, sticky="ew") S_LLänge = Scale(from_=10, to=1, width=20, orient="horizontal", tickinterval=1, resolution=0.1, command=zeichnung) S_LLänge.set(5) S_LLänge.grid(row=4, column=0, columnspan=2, sticky="ew") def reset_LLänge(event): if S_LMasse.get(): S_LLänge.set(S_RLänge.get()*S_RMasse.get()/S_LMasse.get()) zeichnung() S_LLänge.bind("<Button-3>", reset_LLänge) # Horizontaler rechter Regler Label(text="Länge des rechten Waagbalkenarmesn[m]" ).grid(row=3, column=2, columnspan=2, sticky="ew") S_RLänge = Scale(from_=1, to=10, width=20, orient="horizontal", tickinterval=1, resolution=0.1, command=zeichnung) S_RLänge.set(5) S_RLänge.grid(row=4, column=2, columnspan=2, sticky="ew") def reset_RLänge(event): if S_RMasse.get(): S_RLänge.set(S_LLänge.get()*S_LMasse.get()/S_RMasse.get()) zeichnung() S_RLänge.bind("<Button-3>", reset_RLänge) # Anfangsdarstellung zeichnung() mainloop()
--
Dipl.-Ing. Martin Vogel
Leiter des Bauforums
Bücher:
CAD mit BricsCAD
Bauinformatik mit Python