diff --git a/lindenmayer/__main__.py b/lindenmayer/__main__.py index 70c01bc..eaf9e07 100644 --- a/lindenmayer/__main__.py +++ b/lindenmayer/__main__.py @@ -1,17 +1,25 @@ import drawer import turtle +import lSystems +import inputHelper turtle.tracer(0, 0) turtleObject = turtle.Turtle() turtleObject.hideturtle() -simulatedDraw = drawer.DrawerSimulation({"F": "F[+F]F[-F]F"}, 25.7, 1, turtle.Vec2D(0, 0), 90.0, turtleObject) -simulatedDraw.draw("F", 5) -xDistance = simulatedDraw.edges[0].max - simulatedDraw.edges[0].min -yDistance = simulatedDraw.edges[1].max - simulatedDraw.edges[1].min -xScale = turtleObject.screen.window_width() / xDistance -yScale = turtleObject.screen.window_height() / yDistance +for i, lSystem in enumerate(lSystems.LSystems): + print(f"{i}: {lSystem.name}") +lSystemIndex = inputHelper.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] +simulatedDraw = drawer.DrawerSimulation(lSystem.productionRules, lSystem.angel, 1, turtle.Vec2D(0, 0), 90.0, turtleObject) +simulatedDraw.draw(lSystem.startWord, 5) +maxVec = simulatedDraw.edges.maxVec() +minVec = simulatedDraw.edges.minVec() +distance = maxVec - minVec +xScale = turtleObject.screen.window_width() / distance[0] +yScale = turtleObject.screen.window_height() / distance[1] scale = yScale if xScale > yScale else xScale -pos = turtle.Vec2D( -(simulatedDraw.edges[0].min + xDistance / 2) * scale, -(simulatedDraw.edges[1].min + yDistance / 2) * scale) -actualDrawer = drawer.Drawer({"F": "F[+F]F[-F]F"}, 25.7, scale, pos, 90.0, turtleObject) -actualDrawer.draw("F", 5) -print(turtleObject.screen._window_size()) +pos = (-minVec - distance * (1/2)) * scale +print(pos) +print(distance) +actualDrawer = drawer.Drawer(lSystem.productionRules, lSystem.angel, scale, pos, 90.0, turtleObject) +actualDrawer.draw(lSystem.startWord, 5) turtleObject.screen.exitonclick() diff --git a/lindenmayer/drawer.py b/lindenmayer/drawer.py index 8649af8..c01befd 100644 --- a/lindenmayer/drawer.py +++ b/lindenmayer/drawer.py @@ -1,6 +1,5 @@ import turtle from dataclasses import dataclass -import typing @dataclass class State: @@ -45,18 +44,24 @@ class Drawer(): class Edges: def __init__(self): - self.min = 0 - self.max = 0 + self.min = [0, 0] + self.max = [0, 0] + + def minVec(self): + return turtle.Vec2D(self.min[0], self.min[1]) + + def maxVec(self): + 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) self.turtle.penup() - self.edges = [Edges(), Edges()] + self.edges = Edges() def storeEdges(self): for i, koord in enumerate(self.turtle.position()): - if koord < self.edges[i].min: - self.edges[i].min = koord - elif koord > self.edges[i].max: - self.edges[i].max = koord + if koord < self.edges.min[i]: + self.edges.min[i] = koord + elif koord > self.edges.max[i]: + self.edges.max[i] = koord diff --git a/lindenmayer/input.py b/lindenmayer/input.py new file mode 100644 index 0000000..4a6af52 --- /dev/null +++ b/lindenmayer/input.py @@ -0,0 +1,13 @@ +def inputInt(description, indexErrorMsg): + lSystemIndex: int + while inputError: + try: + lSystemIndex = int(input(description)) + except ValueError: + print("Fehler: keine gültige Zahl") + continue + inputError = lSystemIndex < 0 or lSystemIndex >= len(lSystems.LSystems) + if inputError: + print(indexErrorMsg) + + return lSystemIndex diff --git a/lindenmayer/inputHelper.py b/lindenmayer/inputHelper.py new file mode 100644 index 0000000..5ba8cf2 --- /dev/null +++ b/lindenmayer/inputHelper.py @@ -0,0 +1,17 @@ +def inputNum(inputType, description, rangeErrorMsg, minRange, maxRange, defaultValue = None): + n: int + inputError = True + while inputError: + inputValue = input(description) + try: + n = inputType(inputValue) + 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 diff --git a/lindenmayer/lSystems.py b/lindenmayer/lSystems.py new file mode 100644 index 0000000..0153ed4 --- /dev/null +++ b/lindenmayer/lSystems.py @@ -0,0 +1,18 @@ +from dataclasses import dataclass +import typing + +@dataclass +class LSytem: + name: str + startWord: str + productionRules: typing.Dict[str, str] + angel: float + +LSystems = [ + LSytem("AB a", "F", {"F": "F[+F]F[-F]F"}, 25.7), + LSytem("AB b", "F", {"F": "F[+F]F[-F][F]"}, 20.0), + LSytem("AB c", "F", {"F": "FF-[-F+F+F]+[+F-F-F]"}, 22.5), + 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), + ]