Wendeltreppenprogramm für glatte Unterseite und beidseitigen Handlauf (Software)

Martin Vogel ⌂ @, Dortmund / Bochum, Freitag, 22.06.2018, 13:47 (vor 146 Tagen) @ Martin Vogel

Weil es viel einfacher ist, überflüssige Elemente zu löschen, als fehlende Elemente hinzuzufügen, erzeugt das in den letzten beiden Foreneinträgen vorgestellte Python-Wendeltreppenprogramm für AutoCAD und BricsCAD jetzt auch gleich noch zwei Handläufe.

Eine Wahlmöglichkeit besteht nicht. Die Geländer sind 100 cm hoch, der Handlaufdurchmesser beträgt 7 cm, pro Stufe werden auf der Innenseite ein und auf der Außenseite zwei Geländerstäbe mit 2,5 cm Durchmesser angeordnet. Wer das variabel haben möchte, darf das Pythonprogramm gerne an seine Bedürfnisse anpassen.

Download: ZIP-Datei

[image]
So sieht eine mit dem Programm erzeugte und mit Materialien (Marmor, Messing) versehene Wendeltreppe aus.

  1. #!/usr/bin/env python3
  2. #
  3. # Dieses Programm benötigt mindestens Python 3.6
  4.  
  5. from math import pi, degrees, radians, sin, cos
  6. import os.path
  7.  
  8. print("""
  9. Dieses Programm erzeugt eine AutoCAD/BricsCAD-Scriptdatei zur Konstruktion
  10. einer Wendeltreppe in einer leeren Zeichnungsdatei.
  11.  
  12. Autor: Martin Vogel, 2018
  13. Lizenz: Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland
  14. (CC BY-SA 3.0 DE) https://creativecommons.org/licenses/by-sa/3.0/de/
  15. Info: https://bauforum.wirklichewelt.de/index.php?id=11644
  16. """)
  17.  
  18. # Funktion zur Eingabe einer Gleitkommazahl (mit optionalem Vorgabewert):
  19. def fi(s, vorgabe=None):
  20. while True:
  21. print(f"{s}{f' ({vorgabe})' if vorgabe else ''}: ", end="")
  22. inp = input().replace(",", ".")
  23. if not inp:
  24. inp = vorgabe
  25. try:
  26. return float(inp)
  27. except:
  28. print("Fehler: Eingabe wurde nicht als Zahl erkannt.")
  29.  
  30. # Funktion zur Koordinatendrehung im Gegenuhrzeigersinn (GUZ)
  31. def rot(x, y, grad):
  32. w = radians(grad)
  33. return x * cos(w) - y * sin(w), x * sin(w) + y * cos(w)
  34.  
  35. # Funktion zum Finden eines noch nicht benutzten Dateinamens
  36. def freiername(maske):
  37. # Die Maske ist ein Musterdateiname, der um eine fortlaufende Zahl
  38. # in einer Klammer vor der Dateinamenerweiterung ergänzt wird.
  39. # Wo ist der letzte Punkt in der Maske?
  40. p = len(maske) - maske[::-1].find(".") - 1
  41. # Eventuell wird der Dateiname in der Maske noch gar nicht verwendet.
  42. name = maske
  43. i = 1
  44. # Ansonsten erhöhen wir den Zähler i, bis ein freier Name gefunden wurde.
  45. while os.path.isfile(name):
  46. i += 1
  47. # aus "Wendeltreppe.scr" wird "Wendeltreppe(2).scr"
  48. name = maske[:p] + f"({i})" + maske[p:]
  49. return name
  50.  
  51. # Für die Geländerabmessungen ist keine Interaktion vorgesehen.
  52. # Geländerhöhe
  53. hg = 100
  54. # Geländerhandlaufdurchmesser
  55. dg = 7
  56. # Geländerstabdurchmesser
  57. ds = 2.5
  58. # Der Abschlusskugeldurchmesser ist etwas größer als der Handlaufdurchmesser.
  59. dk = 1.5 * dg
  60.  
  61. # Abfrage der Treppenparameter und Berechnung der abhängigen Werte
  62.  
  63. # Außendurchmesser
  64. print("Der Außendurchmesser sollte nicht kleiner als 120 cm sein.")
  65. da = fi("Außendurchmesser der Treppe", 250)
  66.  
  67. # Die Lauflinie ist die Linie, auf der die Treppe am bequemsten zu gehen ist.
  68. # Wir legen sie 30 cm vom inneren Rand des äußeren Handlaufs aus nach innen an.
  69. dl = da - 2 * dg - 60
  70. print(f"\nDer Durchmesser der Lauflinie beträgt {dl} cm.")
  71.  
  72. # Der Umfang der Lauflinie ist die Strecke, die man bei einer vollen
  73. # Wendelumdrehung horizontal zurücklegen würde
  74. ul = pi * dl
  75. print(f"Ihr Umfang beträgt {ul:.1f} cm.")
  76.  
  77. # Innendurchmesser
  78. # Wenn der Innendurchmesser null ist, kann die Unterseite nicht ausgeformt
  79. # werden.
  80. print("\nDer Innendurchmesser muss größer als null sein.")
  81. di = fi("Innendurchmesser der Treppe", 50)
  82.  
  83. # Wie hoch soll die Treppe sein? Gemessen wird von der Unterkante der
  84. # untersten Stufe bis zur Oberkante der obersten Stufe.
  85. ht = fi("\nHöhe der Treppe", 260)
  86.  
  87. # Wie viele Stufen werden benötigt (Idealhöhe 17 cm)?
  88. n = round(ht / 17)
  89. print(f"\nDie Treppe erhält {n} Stufen.")
  90.  
  91. # Welche Stufenhöhe ergibt sich aus dieser Anzahl?
  92. hs = ht / n
  93. print(f"Die Stufenhöhe beträgt {hs:.1f} cm.")
  94.  
  95. # Die rechnerische Auftrittslänge (Stufentiefe) ergibt sich aus der
  96. # Schrittmaßregel.
  97. ra = 63 - 2 * hs
  98.  
  99. # Der rechnerische Drehwinkel der Treppe hat vermutlich ein recht krummes Maß.
  100. rw = 360 * n * ra / ul
  101.  
  102. # Wir runden ihn auf ein Vielfaches von 15°.
  103. rwg = int(round(rw / 15) * 15)
  104.  
  105. # Vermutlich sind ohnehin nur Vielfache von 90° gewünscht.
  106. # Wir halten uns da raus.
  107. print("\nLinks herum ansteigende Treppen besitzen einen positiven Drehwinkel,"
  108. "\nrechts herum ansteigende Treppen einen negativen.")
  109. wt = fi("Gesamtdrehwinkel der Treppe", rwg)
  110.  
  111. # Daraus ergibt sich der Drehwinkel einer einzelnen Stufe.
  112. ws = wt/n
  113.  
  114. # Alle Geometriewerte sind eingesammelt,
  115. # die Scriptdatei kann geschrieben werden:
  116. wtn = freiername("Wendeltreppe.scr")
  117. with open(wtn, "w") as scr:
  118. # Koordinateneingabe geht vor Objektfang
  119. scr.write("OSnapCoord 1\n")
  120. # Einheit Zentimeter
  121. scr.write("_InsUnits 5\n")
  122. # Definierende Geometrie automatisch löschen (z. B. Handlauf-Spirale)
  123. scr.write("DelObj 2\n")
  124. # Seitenansicht, um sicherzustellen, dass beim Ausformen der
  125. # Treppenunterseite alle Stufenrückseiten angeklickt werden können.
  126. scr.write("-APunkt 0,-1,0\n")
  127. # Dummykörper als Zoomziel
  128. scr.write(f"Zylinder 0,0,0 {da/2} {ht+hg+hs}\n")
  129. scr.write("Zoom Objekt L \n")
  130. scr.write("_Erase L \n")
  131.  
  132. # Die Unterseite der Wendeltreppe wird als Ausformungskörper entlang
  133. # der Rückseiten der (späteren) Stufenprofile angelegt.
  134.  
  135. # In der Liste Lp merken wir uns einen Punkt pro Querschnitt, den
  136. # wir beim Ausformen anklicken können.
  137. Lp = []
  138.  
  139. # Für alle Stufen ab der zweiten:
  140. for i in range(1,n+1):
  141. # Die Hinterseite jeder Stufe ist ein Rechteck.
  142. # Koordinaten auf der x-y-Ebene:
  143. xi, yi = rot(di/2, 0, i*ws)
  144. xa, ya = rot(da/2, 0, i*ws)
  145. # Vier Punkte im Raum:
  146. p0 = f"{xi},{yi},{(i-1)*hs}"
  147. p1 = f"{xa},{ya},{(i-1)*hs}"
  148. p2 = f"{xa},{ya},{i*hs}"
  149. p3 = f"{xi},{yi},{i*hs}"
  150. # CAD-Befehl zum Zeichnen der geschlossenen 3D-Polylinie:
  151. scr.write(f"3DPoly {p0} {p1} {p2} {p3} s\n")
  152. # Wir merken uns einen Anklickpunkt ganz außen auf halber Stufenhöhe.
  153. Lp.append(f"{xa},{ya},{(i-0.5)*hs}")
  154.  
  155. # Ausformen der "Rampe"
  156. scr.write(f"_Loft {' '.join(Lp)}\n\n\n")
  157.  
  158. # Drehrichtung der Handläufe
  159. twist = "GUZ" if wt>0 else "UZ"
  160.  
  161. # Handlauf außen:
  162. # Pfad
  163. scr.write(f"Spirale 0,0,{hg+hs} {da/2-dg/2} "
  164. f"_T {abs(wt)/360} _W {twist} A 0,0,{hg+hs+ht}\n")
  165. # Profil
  166. scr.write(f"Kreis 0,0,0 {dg/2}\n")
  167. # Extrudiere Profil entlang Pfad
  168. scr.write(f"_Sweep l {da/2-dg/2},0,{hg+hs}\n")
  169.  
  170. # Handlauf innen:
  171. # Pfad
  172. scr.write(f"Spirale 0,0,{hg+hs} {di/2+dg/2} "
  173. f"_T {abs(wt)/360} _W {twist} A 0,0,{hg+hs+ht}\n")
  174. # Profil
  175. scr.write(f"Kreis 0,0,0 {dg/2}\n")
  176. # Extrudiere Profil entlang Pfad
  177. scr.write(f"_Sweep l {di/2+dg/2},0,{hg+hs}\n")
  178.  
  179. # Geländerstäbe außen:
  180. # Für alle Stufen je zwei Stäbe in den Viertelspunkten
  181. for i in range(n):
  182. x,y = rot(da/2-dg/2, 0, (i+1/4)*ws)
  183. scr.write(f"Zylinder {x},{y},{(i+1)*hs} {ds/2} {hg+hs/4}\n")
  184. x,y = rot(da/2-dg/2, 0, (i+3/4)*ws)
  185. scr.write(f"Zylinder {x},{y},{(i+1)*hs} {ds/2} {hg+hs*3/4}\n")
  186.  
  187. # Geländerstäbe innen:
  188. # Für alle Stufen je ein Stab in Stufenmitte
  189. for i in range(n):
  190. x,y = rot(di/2+dg/2, 0, (i+0.5)*ws)
  191. scr.write(f"Zylinder {x},{y},{(i+1)*hs} {ds/2} {hg+hs/2}\n")
  192.  
  193. # Noch etwas Deko: Kugeln als Handlaufabschluss
  194. scr.write(f"Kugel {(di+dg)/2},0,{hg+hs} {dk/2}\n")
  195. scr.write(f"Kugel {(da-dg)/2},0,{hg+hs} {dk/2}\n")
  196. x, y = rot((di+dg)/2,0,wt)
  197. scr.write(f"Kugel {x},{y},{hg+ht+hs} {dk/2}\n")
  198. x, y = rot((da-dg)/2,0,wt)
  199. scr.write(f"Kugel {x},{y},{hg+ht+hs} {dk/2}\n")
  200.  
  201. # Nun werden die einzelnen Stufen auf die „Rampe“ gesetzt.
  202.  
  203. # Für alle Stufen:
  204. for i in range(n):
  205. # Die Vorderseite jeder Stufe ist ein Rechteck.
  206. # Koordinaten auf der x-y-Ebene:
  207. xi,yi = rot(di/2, 0, i*ws)
  208. xa,ya = rot(da/2, 0, i*ws)
  209. # Vier Punkte im Raum:
  210. p0 = f"{xi},{yi},{i*hs}"
  211. p1 = f"{xa},{ya},{i*hs}"
  212. p2 = f"{xa},{ya},{(i+1)*hs}"
  213. p3 = f"{xi},{yi},{(i+1)*hs}"
  214. # CAD-Befehl zum Zeichnen der geschlossenen 3D-Polylinie:
  215. scr.write(f"3DPoly {p0} {p1} {p2} {p3} s\n")
  216. # Durch Rotieren der Stufenvorderseite um die Mittelachse entsteht die
  217. # Stufe als Volumenkörper. Der Drehwinkel ist so gewählt, dass die
  218. # Stufen sich jeweils an einer Kante berühren. Diese liegt außerdem
  219. # genau auf der oberen Fläche der Rampe.
  220. scr.write(f"Rotation l 0,0,0 0,0,1 {ws}\n")
  221.  
  222. # Anzeige anpassen, perspektivische Ansicht von vorne rechts:
  223. scr.write("-APunkt 1,-1,1\n")
  224. scr.write("Perspective 1\n")
  225. scr.write(f"Zoom Grenzen\n")
  226.  
  227. # Automatisches Löschen erzeugender Geometrie wieder ausschalten.
  228. scr.write("DelObj 0\n")
  229.  
  230. print(f"""
  231. Fertig.
  232.  
  233. Starten Sie die erzeugte Scriptdatei "{wtn}" im CAD-Programm
  234. in einer leeren Zeichnung (Einheit Zentimeter) mit dem Befehl SCRIPT!
  235. """)
  236. input("[Enter]")

--
Dipl.-Ing. Martin Vogel
Leiter des Bauforums

Heute schon programmiert? Einführung in Python 3 (PDF)

Tags:
Python, CAD, AutoCAD, BricsCAD, Wendeltreppe



gesamter Thread:

 RSS-Feed dieser Diskussion

powered by my little forum