import drawsvg as draw import os import math class Circle: def __init__(self, name: str, filepath: str, length=50, height=50, radius=1, distance=2.4, offset_percentage=50): assert length >= 0, "length can not be negative" assert height >= 0, "height can not be negative" assert radius >= 0, "radius can not be negative" assert radius <= distance / 2, "radius must be smaller then half the distance" assert distance >= 2*radius, "distance must be grater then two times the radius" assert offset_percentage >= 0, "offset can only be 0 - 100 %" assert offset_percentage <= 100, "offset can only be 0 - 100 %" self.__name = name self.__filepath = filepath self.__length = length self.__height = height self.__radius = radius self.__distance = distance self.__offset_percentage = offset_percentage self.__offset = (distance / 100) * offset_percentage @property def length(self): return self.__length @length.setter def length(self, val): assert val >= 0, "length can not be negative" self.__length = val @property def height(self): return self.__height @height.setter def height(self, val): assert val >= 0, "height can not be negative" self.__height = val @property def radius(self): return self.__radius @radius.setter def radius(self, val): assert val >= 0, "radius can not be negative" assert radius <= self.__distance / 2, "radius must be smaller then half the distance" self.__radius = val @property def distance(self): return self.__distance @distance.setter def distance(self, val): assert val >= 2 * self.__radius, "distance must be grater then two times the radius" self.__distance = val self.__offset = (val / 100) * self.__offset_percentage @property def offset_percentage(self): return self.__offset_percentage @offset_percentage.setter def offset_percentage(self, val): assert val >= 0, "offset can only be 0 - 100 %" assert val <= 100, "offset can only be 0 - 100 %" self.__offset_percentage = val self.__offset = (self.__distance / 100) * val def circle_generation(self, filetype='svg', generate_shifted_pattern=True): assert filetype == 'svg' or 'png', "Dateityp mus svg oder png sein" x = self.__radius y = self.__radius i = 1 distance_y = (math.sqrt(3) / 2) * self.__distance canvas = draw.Drawing(self.__length, self.__height, origin=(0, 0)) alignment_dot = draw.Circle(0.1, 0.1, 0.1, stroke='black', stroke_width=0.05) canvas.append(alignment_dot) while y + self.__radius <= self.__height: while x + self.__radius <= self.__length: canvas.append(draw.Circle(x, y, self.__radius, fill='none', stroke_width=0.1, stroke='black')) x = x + self.__distance if i % 2 == 0: x = self.__radius else: x = self.__radius + self.__offset y = y + distance_y i = i + 1 if generate_shifted_pattern: i = 1 x_shifted = self.__radius + self.__distance / 2 y_shifted = self.__radius + distance_y / (2 * math.sqrt(3)) canvas_shifted = draw.Drawing(self.__length, self.__height, origin=(0, 0)) canvas_shifted.append(alignment_dot) while y_shifted + self.__radius <= self.__height: while x_shifted + self.__radius <= self.__length: canvas_shifted.append(draw.Circle(x_shifted, y_shifted, self.__radius, fill='none', stroke_width=0.1, stroke='black')) x_shifted = x_shifted + self.__distance if i % 2 == 0: x_shifted = self.__radius + self.__distance / 2 else: x_shifted = self.__radius + self.__distance / 2 + self.__offset y_shifted = y_shifted + distance_y i = i + 1 if filetype == 'svg': canvas_shifted.save_svg(f'{self.__filepath}/{self.__name}_versetzt.svg') if filetype == 'png': canvas_shifted.save_png(f'{self.__filepath}/{self.__name}_versetzt.png') if filetype == 'svg': canvas.save_svg(f'{self.__filepath}/{self.__name}.svg') if filetype == 'png': canvas.save_png(f'{self.__filepath}/{self.__name}.png') class Hexagon: def __init__(self, name: str, filepath: str, length=50, height=50, key_width=2, bridge_width=0.5): assert length >= 0, "length can not be negative" assert height >= 0, "height can not be negative" assert key_width >= 0, "key width can not be negative" assert bridge_width >= 0, "bridge width can not be negative" self.__name = name self.__filepath = filepath self.__length = length self.__height = height self.__key_width = key_width self.__bridge_width = bridge_width @property def length(self): return self.__length @length.setter def length(self, val): assert val >= 0, "length can not be negative" self.__length = val @property def height(self): return self.__height @height.setter def height(self, val): assert val >= 0, "height can not be negative" self.__height = val @property def key_width(self): return self.__key_width @key_width.setter def key_width(self, val): assert val >= 0, "length can not be negative" self.__key_width = val @property def bridge_width(self): return self.__bridge_width @bridge_width.setter def bridge_width(self, val): assert val >= 0, "bridge width can not be negative" self.__bridge_width = val def hexagon_generation(self, filetype='svg', generate_shifted_pattern=True): assert filetype == 'svg' or 'png', "Dateityp mus svg oder png sein" i = 1 x = 0 y = 0 side_length = self.__key_width / math.sqrt(3) sin_expression = math.sin(math.radians(30)) * side_length distance = self.__key_width + self.__bridge_width distance_y = (math.sqrt(3) / 2) * distance canvas = draw.Drawing(self.__length, self.__height, origin=(0, 0)) alignment_dot = draw.Circle(0.1, 0.1, 0.1, stroke='black', stroke_width=0.05) canvas.append(alignment_dot) while y + (2 * side_length) < self.__height: while x + self.__key_width < self.__length: p1_x = x + self.__key_width / 2 p1_y = y p2_x = x p2_y = y + sin_expression p3_x = x p3_y = y + sin_expression + side_length p4_x = x + self.__key_width / 2 p4_y = y + 2 * side_length p5_x = x + self.__key_width p5_y = y + sin_expression + side_length p6_x = x + self.__key_width p6_y = y + sin_expression hexagon = draw.Lines(p1_x, p1_y, p2_x, p2_y, p3_x, p3_y, p4_x, p4_y, p5_x, p5_y, p6_x, p6_y, fill='none', stroke='black', close='true', stroke_width=0.1) canvas.append(hexagon) x = x + distance if i % 2 == 0: x = 0 else: x = distance / 2 y = y + distance_y i = i + 1 if generate_shifted_pattern: x_shifted = distance / 2 y_shifted = distance / (2 * math.sqrt(3)) i = 1 canvas_shifted = draw.Drawing(self.__length, self.__height, origin=(0, 0)) canvas_shifted.append(alignment_dot) while y_shifted + (2 * side_length) < self.__height: while x_shifted + self.__key_width < self.__length: p1_x_2 = x_shifted + self.__key_width / 2 p1_y_2 = y_shifted p2_x_2 = x_shifted p2_y_2 = y_shifted + sin_expression p3_x_2 = x_shifted p3_y_2 = y_shifted + sin_expression + side_length p4_x_2 = x_shifted + self.__key_width / 2 p4_y_2 = y_shifted + 2 * side_length p5_x_2 = x_shifted + self.__key_width p5_y_2 = y_shifted + sin_expression + side_length p6_x_2 = x_shifted + self.__key_width p6_y_2 = y_shifted + sin_expression hexagon_shifted = draw.Lines(p1_x_2, p1_y_2, p2_x_2, p2_y_2, p3_x_2, p3_y_2, p4_x_2, p4_y_2, p5_x_2, p5_y_2, p6_x_2, p6_y_2, fill='none', stroke='black', close='true', stroke_width=0.1) canvas_shifted.append(hexagon_shifted) x_shifted = x_shifted + distance if i % 2 == 0: x_shifted = distance / 2 else: x_shifted = distance y_shifted = y_shifted + distance_y i = i + 1 if filetype == 'svg': canvas_shifted.save_svg(f'{self.__filepath}/{self.__name}_versetzt.svg') if filetype == 'png': canvas_shifted.save_png(f'{self.__filepath}/{self.__name}_versetzt.png') if filetype == 'svg': canvas.save_svg(f'{self.__filepath}/{self.__name}.svg') if filetype == 'png': canvas.save_png(f'{self.__filepath}/{self.__name}.png') class Triangle: def __init__(self, name: str, filepath: str, length=50, height=50, side_length=2, bridge_width=0.5): assert length >= 0, "length can not be negative" assert height >= 0, "height can not be negative" assert side_length >= 0, "side length can not be negative" assert bridge_width >= 0, "bridge width can not be negative" self.__name = name self.__filepath = filepath self.__length = length self.__height = height self.__side_length = side_length self.__bridge_width = bridge_width @property def length(self): return self.__length @length.setter def length(self, val): assert val >= 0, "length can not be negative" self.__length = val @property def height(self): return self.__height @height.setter def height(self, val): assert val >= 0, "height can not be negative" self.__height = val @property def side_length(self): return self.__side_length @side_length.setter def side_length(self, val): assert val >= 0, "length can not be negative" self.__side_length = val @property def bridge_width(self): return self.__bridge_width @bridge_width.setter def bridge_width(self, val): assert val >= 0, "bridge width can not be negative" self.__bridge_width = val def triangle_generation(self, filetype='svg'): assert filetype == 'svg' or 'png', "Dateityp mus svg oder png sein" x = 0 y = 0 i = 1 distance = self.__bridge_width / math.sin(math.radians(60)) canvas = draw.Drawing(self.__length, self.__height, origin=(0, 0)) while y + math.sqrt(3) / 2 * self.__side_length <= self.__height: while x + 1.5 * self.__side_length + distance <= self.__length: triangle1_p1_x = x triangle1_p1_y = y triangle1_p2_x = x + self.__side_length triangle1_p2_y = y triangle1_p3_x = x + math.sin(math.radians(30)) * self.__side_length triangle1_p3_y = y + math.cos(math.radians(30)) * self.__side_length triangle = draw.Lines(triangle1_p1_x, triangle1_p1_y, triangle1_p2_x, triangle1_p2_y, triangle1_p3_x, triangle1_p3_y, close='true', stroke='black', fill='none', stroke_width=0.1) canvas.append(triangle) x = x + self.__side_length + distance triangle2_p1_x = x triangle2_p1_y = y triangle2_p2_x = x - self.__side_length / 2 triangle2_p2_y = y + math.sqrt(3) / 2 * self.__side_length triangle2_p3_x = x + self.__side_length / 2 triangle2_p3_y = triangle2_p2_y triangle2 = draw.Lines(triangle2_p1_x, triangle2_p1_y, triangle2_p2_x, triangle2_p2_y, triangle2_p3_x, triangle2_p3_y, close='true', stroke='black', fill='none', stroke_width=0.1) canvas.append(triangle2) x = x + distance if i % 2 == 0: x = 0 else: x = self.__side_length / 2 + distance y = y + self.__bridge_width + math.sqrt(3) / 2 * self.__side_length i = i + 1 if filetype == 'svg': canvas.save_svg(f'{self.__filepath}/{self.__name}.svg') if filetype == 'png': canvas.save_png(f'{self.__filepath}/{self.__name}.png') if __name__ == '__main__': name = input("Dateinamen:") path = input("Dateipfad (0 für aktuelles Verzeichnis):") if path == "0": path = os.getcwd() shape = int(input("Form (1: Kreis, 2: Hexagon, 3: Dreieck):")) filetype = 'svg' shift = True if shape == 1: circle = Circle(name, path) print(f"\nStandardwerte\n1. Höhe: {circle.height} mm\n2. Länge: {circle.length} mm\n3. Radius: {circle.radius} mm\n4. Abstand: {circle.distance} mm\n5. Offset: {circle.offset_percentage} %\n6. Versetztes Muster generiren: {shift}\n7. Dateityp: {filetype}\n") selection_flag = True while selection_flag: try: parameter_selection = int(input("Parameter ändern (0: keinen Parameter ändern, 1: Höhe, 2: Länge, 3: Radius, 4: Abstand, 5: Offste, 6: Versetztes Muster, 7: Dateityp):")) if parameter_selection == 0: selection_flag = False elif parameter_selection == 1: height = float(input("Höhe in mm eingeben:")) circle.height = height elif parameter_selection == 2: length = float(input("Länge in mm:")) circle.length = length elif parameter_selection == 3: radius = float(input("Radius in mm:")) circle.radius = radius elif parameter_selection == 4: distance = float(input("Abstand in mm:")) circle.distance = distance elif parameter_selection == 5: offset = float(input("Offset in %:")) circle.offset_percentage = offset elif parameter_selection == 6: shift_select = int(input("Versetztes muster generieren (0: nein, 1: ja):")) if shift_select == 0: shift = False elif shift_select == 1: shift = True else: raise ValueError elif parameter_selection == 7: filetype_selection = int(input(f"1: {name}.svg, 2: {name}.png:")) if filetype_selection == 1: filetype = "svg" elif filetype_selection == 2: filetype = "png" else: raise ValueError else: print("ungültiger Wert") except ValueError: print("ungültiger Wert") except AssertionError as error: print(error) print( f"\nAktuelle Werte\n1. Höhe: {circle.height} mm\n2. Länge: {circle.length} mm\n3. Radius: {circle.radius} mm\n4. Abstand: {circle.distance} mm\n5. Offset: {circle.offset_percentage} %\n6. Versetztes Muster generiren: {shift}\n7. Dateityp: {filetype}\n") circle.circle_generation(filetype, shift) elif shape == 2: hexagon = Hexagon(name, path) print( f"\nStandardwerte\n1. Höhe: {hexagon.height} mm\n2. Länge: {hexagon.length} mm\n3. Schlüsselweite: {hexagon.key_width} mm\n4. Stegbreite: {hexagon.bridge_width} mm\n5. Versetztes Muster generiren: {shift}\n6. Dateityp: Dateityp: {filetype}\n") selection_flag = True while selection_flag: try: parameter_selection = int(input("Parameter ändern (0: keinen Parameter ändern, 1: Höhe, 2: Länge, 3: Schlüsselweite, 4: Stegbreite, 5: Versetztes Muster, 6: Dateityp):")) if parameter_selection == 0: selection_flag = False elif parameter_selection == 1: height = float(input("Höhe in Pixeln eingeben:")) hexagon.height = height elif parameter_selection == 2: length = float(input("Länge in mm:")) hexagon.length = length elif parameter_selection == 3: key_width = float(input("Schlüsselweite in mm:")) hexagon.key_width = key_width elif parameter_selection == 4: bridge_width = float(input("Stegbreite in mm:")) hexagon.bridge_width = bridge_width elif parameter_selection == 5: shift_select = int(input("Versetztes Muster generieren (0: nein, 1: ja):")) if shift_select == 0: shift = False elif shift_select == 1: shift = True else: raise ValueError elif parameter_selection == 6: filetype_selection = int(input(f"1: {name}.svg, 2: {name}.png:")) if filetype_selection == 1: filetype = "svg" elif filetype_selection == 2: filetype = "png" else: raise ValueError else: print("ungültiger Wert") except ValueError: print("ungültiger Wert") except AssertionError as error: print(error) print( f"\nAktuelle Werte\n1. Höhe: {hexagon.height} mm\n2. Länge: {hexagon.length} mm\n3. Schlüsselweite: {hexagon.key_width} mm\n4. Stegbreite: {hexagon.bridge_width} mm\n5. Versetztes Muster generiren: {shift}\n6.Dateityp: {filetype}\n") hexagon.hexagon_generation(filetype, shift) elif shape == 3: triangle = Triangle(name, path) print( f"\nStandardwerte\n1. Höhe: {triangle.height} mm\n2. Länge: {triangle.length} mm\n3. Seitenlänge: {triangle.side_length} mm\n4. Stegbreite: {triangle.bridge_width} mm\n5. Dateityp: {filetype}\n") selection_flag = True while selection_flag: try: parameter_selection = int(input( "Parameter ändern (0: keinen Parameter ändern, 1: Höhe, 2: Länge, 3: Seitenlänge, 4: Stegbreite, 5: Dateityp):")) if parameter_selection == 0: selection_flag = False elif parameter_selection == 1: height = float(input("Höhe in mm eingeben:")) triangle.height = height elif parameter_selection == 2: length = float(input("Länge in mm:")) triangle.length = length elif parameter_selection == 3: side_length = float(input("Seitenlänge in mm:")) triangle.side_length = side_length elif parameter_selection == 4: bridge_width = float(input("Stegbreite in mm:")) triangle.bridge_width = bridge_width elif parameter_selection == 5: filetype_selection = int(input(f"1: {name}.svg, 2: {name}.png:")) if filetype_selection == 1: filetype = "svg" elif filetype_selection == 2: filetype = "png" else: raise ValueError else: print("ungültiger Wert") except ValueError: print("ungültiger Wert") except AssertionError as error: print(error) print( f"\nAktuelle Werte\n1. Höhe: {triangle.height} mm\n2. Länge: {triangle.length} mm\n3. Seitenlänge: {triangle.side_length} mm\n4. Stegbreite: {triangle.bridge_width} mm\n5. Dateityp: {filetype}\n") triangle.triangle_generation(filetype) else: print("ungültiger Wert")