From b509527b7c03a522cc539472141e7123d6fa31d2 Mon Sep 17 00:00:00 2001 From: MrGeorgen Date: Wed, 5 Jan 2022 18:16:15 +0100 Subject: [PATCH] delete drawings --- lindenmayer/__main__.py | 1 + lindenmayer/drawer.py | 73 +++++++++++++++++------ lindenmayer/inputHelper.py | 118 ++++++++++++++++++++++++++----------- lindenmayer/lSystems.py | 1 + 4 files changed, 141 insertions(+), 52 deletions(-) diff --git a/lindenmayer/__main__.py b/lindenmayer/__main__.py index 2e9b0e7..49196c4 100644 --- a/lindenmayer/__main__.py +++ b/lindenmayer/__main__.py @@ -5,5 +5,6 @@ import time turtle.tracer(0, 0) turtleObject = turtle.Turtle() turtleObject.hideturtle() +turtleObject.screen.colormode(255) inputHelper.takeInput(turtleObject) turtleObject.screen.mainloop() diff --git a/lindenmayer/drawer.py b/lindenmayer/drawer.py index 16250c6..2f8453d 100644 --- a/lindenmayer/drawer.py +++ b/lindenmayer/drawer.py @@ -1,25 +1,48 @@ import turtle from dataclasses import dataclass +import lSystems @dataclass class State: heading: float position: turtle.Vec2D +@dataclass +class DrawingInfo: + lSystem: lSystems.LSytem + position: turtle.Vec2D + rotation: float + color: any + scale: float + recursionDepth: int + +drawings = [] + class Drawer(): - def __init__(self, productionRules, angel, forwardDistance, startPosition, startRotation, turtle): - self.productionRules = productionRules - self.angel = angel - self.forwardDistance = forwardDistance - self.turtle = turtle - self.turtle.setposition(startPosition) - self.turtle.setheading(startRotation) + def __init__(self, drawingInfo, turtleObject): + self.startWord = drawingInfo.lSystem.startWord + self.recursionDepth = drawingInfo.recursionDepth + self.productionRules = drawingInfo.lSystem.productionRules + self.angel = drawingInfo.lSystem.angel + self.forwardDistance = drawingInfo.scale + self.turtle = turtleObject + self.turtle.penup() + self.turtle.setposition(drawingInfo.position) + self.turtle.setheading(drawingInfo.rotation) self.turtle.pendown() + self.turtle.pencolor(drawingInfo.color) def storeEdges(self): pass - def draw(self, word, n): + def pendown(self): + self.turtle.pendown() + + def draw(self, word = None, n = None): + if n == None: + n = self.recursionDepth + if word == None: + word = self.startWord turtleStates = [] if n == 0: self.turtle.screen.update() @@ -36,9 +59,11 @@ class Drawer(): case "[": turtleStates.append(State(self.turtle.heading(), self.turtle.position())) case "]": + self.turtle.penup() state = turtleStates.pop() self.turtle.setposition(state.position) self.turtle.setheading(state.heading) + self.pendown() if character in self.productionRules: self.draw(self.productionRules[character], n - 1) @@ -54,8 +79,8 @@ class Edges: return turtle.Vec2D(self.max[0], self.max[1]) class DrawerSimulation(Drawer): - def __init__(self, productionRules, angel, forwardDistance, startPosition, startRotation, turtle): - super(DrawerSimulation, self).__init__(productionRules, angel, forwardDistance, startPosition, startRotation, turtle) + def __init__(self, drawingInfo, turtleObject): + super(DrawerSimulation, self).__init__(drawingInfo, turtleObject) self.turtle.penup() self.edges = Edges() @@ -66,18 +91,28 @@ class DrawerSimulation(Drawer): elif koord > self.edges.max[i]: self.edges.max[i] = koord -def draw(turtleObject, lSystem, recursionDepth, middel, rotation, size): - print(size) - simulatedDraw = DrawerSimulation(lSystem.productionRules, lSystem.angel, 1, turtle.Vec2D(0, 0), rotation, turtleObject) - simulatedDraw.draw(lSystem.startWord, recursionDepth) + def pendown(self): + pass + +def draw(turtleObject, lSystem, recursionDepth, middle, rotation, size, color): + drawingInfo = DrawingInfo(lSystem, turtle.Vec2D(0, 0), rotation, color, 1, recursionDepth) + simulatedDraw = DrawerSimulation(drawingInfo, turtleObject) + simulatedDraw.draw() maxVec = simulatedDraw.edges.maxVec() minVec = simulatedDraw.edges.minVec() distance = maxVec - minVec - print(distance) xScale = size[0] / distance[0] yScale = size[1] / distance[1] scale = yScale if xScale > yScale else xScale - pos = middel + (-minVec - distance * (1/2)) * scale - print(pos) - actualDrawer = Drawer(lSystem.productionRules, lSystem.angel, scale, pos, rotation, turtleObject) - actualDrawer.draw(lSystem.startWord, recursionDepth) + pos = middle + (-minVec - distance * (1/2)) * scale + drawingInfo.position = pos + drawingInfo.scale = scale + actualDrawer = Drawer(drawingInfo, turtleObject) + actualDrawer.draw() + drawings.append(drawingInfo) + +def redraw(turtleObject): + turtleObject.clear() + for drawing in drawings: + drawer = Drawer(drawing, turtleObject) + drawer.draw() diff --git a/lindenmayer/inputHelper.py b/lindenmayer/inputHelper.py index 58525af..fadbbf6 100644 --- a/lindenmayer/inputHelper.py +++ b/lindenmayer/inputHelper.py @@ -4,48 +4,100 @@ import lSystems def inputNum(inputType, description, rangeErrorMsg, minRange, maxRange, defaultValue = None): n: int - inputError = True - while inputError: + while True: inputValue = input(description) try: n = inputType(inputValue) + inputError = n < minRange or n > maxRange + if inputError: + print(rangeErrorMsg) + else: + return n except ValueError: if inputValue == "" and defaultValue != None: return defaultValue print("Fehler: keine gültige Zahl") - continue - inputError = n < minRange or n > maxRange - if inputError: - print(rangeErrorMsg) - return n +def inputColorError(): + print("Fehler: ungültige Farbeingabe") + +def inputColor(turtleObject, question, defaultValue = None): + while True: + defaultValueMsg = f" (Standartwert: {defaultValue})" if defaultValue != None else "" + inputValue = input(f"{question} RGB-Wert eingeben, wobei die Farben mit Leerzeichen getrennt werden, oder einen Tk-Farbnamen eingeben [0 0 0 - 255 255 255 oder Farben auf https://www.tcl.tk/man/tcl8.4/TkCmd/colors.html]{defaultValueMsg}: ") + if inputValue == "": + if defaultValue != None: + return defaultValue + inputColorError() + else: + oldPenColor = turtleObject.pencolor() + try: + color = tuple([int(color) for color in inputValue.split()]) + turtleObject.pencolor(color) + turtleObject.pencolor(oldPenColor) + return color + except: + try: + turtleObject.pencolor(inputValue) + turtleObject.pencolor(oldPenColor) + return inputValue + except: + inputColorError() def takeInput(turtleObject): - for i, lSystem in enumerate(lSystems.LSystems): - print(f"{i}: {lSystem.name}") - lSystemIndex = inputNum(int, "Bitte ein Lindenmayer-System auswählen und die entsprechende Nummer eingeben: ", "Es gibt kein L-System mit dieser Nummer.", 0, len(lSystems.LSystems) - 1) - lSystem = lSystems.LSystems[lSystemIndex] - recursionDepth = inputNum(int, "Rekursiontiefe des Lindenmayer-Systems eingeben [1-20] (Standartwert: 5): ", "Rekursionstiefe nicht im vorgegebenen Bereich.", 1, 20, 5) - rotation = inputNum(float, "Bitte die Rotation in Grad gegen den Uhrzeigersinn angeben, wobei 0° rechts ist (Standartwert: 90°): ", "nur Gradzahlen von 0 bis 360 werden akzeptiert.", 0, 360, 90) - inputError = True - while inputError: - match input("Möchtest du das das Lindenmayer-System das ganze Fenster ausfüllt? [J/n]: ").lower(): - case "j"|"": - inputError = False - drawer.draw(turtleObject, lSystem, recursionDepth, turtle.Vec2D(0, 0), rotation, turtleObject.screen._window_size()) - takeInput(turtleObject) - case "n": - inputError = False - pos = [] - def afterClick(vec): - pos.append(vec) - if len(pos) == 2: - turtleObject.screen.onclick(None) - size = pos[1] - pos[0] - middel = pos[0] + (1/2) * size - print(middel) - size = turtle.Vec2D(abs(size[0]), abs(size[1])) - drawer.draw(turtleObject, lSystem, recursionDepth, middel, rotation, size) + inputValue = input("Bitte einen Befehl eingeben. h für Hilfe: ") + match inputValue: + case "h": + print("""h: Hilfe anzeigen +d: ein neues Lindenmayer-System zeichnen +l: ein Lindenmayer-System löschen +b: Hintergrundfarbe ändern +q: Programm beenden""") + case "d": + for i, lSystem in enumerate(lSystems.LSystems): + print(f"{i}: {lSystem.name}") + lSystemIndex = inputNum(int, "Bitte ein Lindenmayer-System auswählen und die entsprechende Nummer eingeben: ", "Es gibt kein L-System mit dieser Nummer.", 0, len(lSystems.LSystems) - 1) + lSystem = lSystems.LSystems[lSystemIndex] + recursionDepth = inputNum(int, "Rekursiontiefe des Lindenmayer-Systems eingeben [1-20] (Standartwert: 5): ", "Rekursionstiefe nicht im vorgegebenen Bereich.", 1, 20, 5) + rotation = inputNum(float, "Bitte die Rotation in Grad gegen den Uhrzeigersinn angeben, wobei 0° rechts ist (Standartwert: 90°): ", "nur Gradzahlen von 0 bis 360 werden akzeptiert.", 0, 360, 90) + inputError = True + color = inputColor(turtleObject, "Welche Farbe soll das Lindenmayer-System haben?", "black") + while inputError: + match input("Möchtest du das das Lindenmayer-System das ganze Fenster ausfüllt? [J/n]: ").lower(): + case "j"|"": + inputError = False + drawer.draw(turtleObject, lSystem, recursionDepth, turtle.Vec2D(0, 0), rotation, turtleObject.screen._window_size(), color) takeInput(turtleObject) + case "n": + inputError = False + pos = [] + def afterClick(vec): + pos.append(vec) + if len(pos) == 2: + turtleObject.screen.onclick(None) + size = pos[1] - pos[0] + middle = pos[0] + (1/2) * size + size = turtle.Vec2D(abs(size[0]), abs(size[1])) + drawer.draw(turtleObject, lSystem, recursionDepth, middle, rotation, size, color) + takeInput(turtleObject) - turtleObject.screen.onclick(lambda x, y: afterClick(turtle.Vec2D(x, y))) + turtleObject.screen.onclick(lambda x, y: afterClick(turtle.Vec2D(x, y))) + case _: + print("Bitte j oder n eingeben") + case "b": + turtleObject.screen.bgcolor(inputColor(turtleObject, "Hintergrundfarbe eingeben")) + case "q": + quit() + case "l": + if len(drawer.drawings) == 0: + print("Es gibt nichts, was man löschen könnte.") + else: + for i, drawing in enumerate(drawer.drawings): + print(f"{i}: {drawing.lSystem.name} Position: {drawing.position}") + iDelete = inputNum(int, "Nummer des zu löschenden Zeichnung eingeben: ", "Es gibt keine Zeichnung mit dieser Nummer", 0, len(drawer.drawings) - 1) + del drawer.drawings[iDelete] + drawer.redraw(turtleObject) + case _: + print("unbekannter Befehl") + if inputValue != "d": + takeInput(turtleObject) diff --git a/lindenmayer/lSystems.py b/lindenmayer/lSystems.py index 4a10726..a5eb15b 100644 --- a/lindenmayer/lSystems.py +++ b/lindenmayer/lSystems.py @@ -15,4 +15,5 @@ LSystems = [ LSytem("AB d", "X", {"X": "F[+X]F[-X]+X", "F": "FF"}, 20.0), LSytem("AB e", "X", {"X": "F[+X][-X]FX", "F": "FF"}, 25.7), LSytem("AB f", "X", {"X": "F-[[X]+X]+F[+FX]-X", "F": "FF"}, 22.5), + LSytem("Drachenkurve", "FX", {"X": "X+YF+", "Y": "-FX-Y"}, 90.0), ]